JDT codeassist module, nothing changed yet
authorkhartlage <khartlage>
Thu, 30 Jan 2003 19:45:33 +0000 (19:45 +0000)
committerkhartlage <khartlage>
Thu, 30 Jan 2003 19:45:33 +0000 (19:45 +0000)
85 files changed:
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/BufferChangedEvent.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IBuffer.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IBufferChangedListener.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IBufferFactory.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/ICodeAssist.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/ICodeFormatter.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/ICompilationUnit.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/ICompletionRequestor.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IField.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IInitializer.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IJavaElement.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IJavaModel.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IJavaModelStatus.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IJavaModelStatusConstants.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IJavaProject.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IMember.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IMethod.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IOpenable.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IParent.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IProblemRequestor.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/ISourceManipulation.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/ISourceRange.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/ISourceReference.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IType.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IWorkingCopy.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/JavaModelException.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/Signature.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/CompletionEngine.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/ISearchRequestor.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/ISearchableNameEnvironment.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/ISelectionRequestor.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/RelevanceConstants.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/SelectionEngine.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionNodeFound.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnArgumentName.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnClassLiteralAccess.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnClassReference.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnExceptionReference.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnExplicitConstructorCall.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnFieldName.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnFieldType.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnImportReference.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnInterfaceReference.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnLocalName.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnMemberAccess.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnMessageSend.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnMethodName.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnMethodReturnType.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnPackageReference.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnQualifiedAllocationExpression.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnQualifiedClassReference.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnQualifiedExceptionReference.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnQualifiedInterfaceReference.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnQualifiedNameReference.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnQualifiedTypeReference.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnSingleNameReference.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnSingleTypeReference.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionParser.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionScanner.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/InvalidCursorLocation.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/impl/AssistOptions.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/impl/AssistParser.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/impl/Engine.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionNodeFound.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnArgumentName.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnExplicitConstructorCall.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnFieldReference.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnFieldType.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnImportReference.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnLocalName.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnMessageSend.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnPackageReference.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnQualifiedAllocationExpression.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnQualifiedNameReference.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnQualifiedSuperReference.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnQualifiedTypeReference.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnSingleNameReference.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnSingleTypeReference.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnSuperReference.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionParser.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionScanner.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/BasicCompilationUnit.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/JavaElementInfo.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/JavaModelStatus.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/TypeConverter.java [new file with mode: 0644]

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 (file)
index 0000000..7422223
--- /dev/null
@@ -0,0 +1,109 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     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 <code>IBufferChangedListener</code> notifications.
+ * <p>
+ * For text insertions, <code>getOffset</code> is the offset
+ * of the first inserted character, <code>getText</code> is the
+ * inserted text, and <code>getLength</code> is 0.
+ * </p>
+ * <p>
+ * For text removals, <code>getOffset</code> is the offset
+ * of the first removed character, <code>getText</code> is <code>null</code>,
+ * and <code>getLength</code> is the length of the text that was removed.
+ * </p>
+ * <p>
+ * For replacements (including <code>IBuffer.setContents</code>), 
+ * <code>getOffset</code> is the offset
+ * of the first replaced character, <code>getText</code> is the replacement
+ * text, and <code>getLength</code> is the length of the original text
+ * that was replaced.
+ * </p>
+ * <p>
+ * When a buffer is closed, <code>getOffset</code> is 0, <code>getLength</code>
+ * is 0, and <code>getText</code> is <code>null</code>.
+ * </p>
+ * <p>
+ * This class is not intended to be instantiated or subclassed by clients.
+ * Instances of this class are automatically created by the Java model.
+ * </p>
+ *
+ * @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.
+ */
+public BufferChangedEvent(IBuffer buffer, int offset, int length, String text) {
+       super(buffer);
+       this.offset = offset;
+       this.length = length;
+       this.text = text;
+}
+/**
+ * Returns the buffer which has changed.
+ *
+ * @return the buffer affected by the change
+ */
+public IBuffer getBuffer() {
+       return (IBuffer) source;
+}
+/**
+ * Returns the length of text removed or replaced in the buffer, or
+ * 0 if text has been inserted into the buffer.
+ *
+ * @return the length of the original text fragment modified by the 
+ *   buffer change (<code> 0 </code> in case of insertion).
+ */
+public int getLength() {
+       return this.length;
+}
+/**
+ * Returns the index of the first character inserted, removed, or replaced
+ * in the buffer.
+ *
+ * @return the source offset of the textual manipulation in the buffer
+ */
+public int getOffset() {
+       return this.offset;
+}
+/**
+ * Returns the text that was inserted, the replacement text,
+ * or <code>null</code> if text has been removed.
+ *
+ * @return the text corresponding to the buffer change (<code> null </code>
+ *   in case of deletion).
+ */
+public String getText() {
+       return this.text;
+}
+}
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 (file)
index 0000000..01660ae
--- /dev/null
@@ -0,0 +1,263 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     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 <code>IOpenable</code>. 
+ * If a buffer does not have an underlying resource, saving the buffer has no effect. 
+ * Buffers can be read-only.
+ * <p>
+ * Note that java model operations that manipulate an <code>IBuffer</code> (e.g. 
+ * <code>IType.createMethod(...)</code>) ensures that the same line delimiter 
+ * (i.e. either <code>"\n"</code> or <code>"\r"</code> or <code>"\r\n"</code>) 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 <code>IBuffer</code>
+ * might not do such transformations beforehand.
+ * <p>
+ * This interface may be implemented by clients.
+ * </p>
+ */
+public interface IBuffer {
+       
+/**
+ * Adds the given listener for changes to this buffer.
+ * Has no effect if an identical listener is already registered or if the buffer
+ * is closed.
+ *
+ * @param listener the listener of buffer changes
+ */
+public void addBufferChangedListener(IBufferChangedListener listener);
+/**
+ * Appends the given character array to the contents of the buffer.
+ * This buffer will now have unsaved changes.
+ * Any client can append to the contents of the buffer, not just the owner of the buffer.
+ * Reports a buffer changed event.
+ * <p>
+ * Has no effect if this buffer is read-only.
+ * <p>
+ * A <code>RuntimeException</code> might be thrown if the buffer is closed.
+ *
+ * @param text the given character array to append to contents of the buffer
+ */
+public void append(char[] text);
+/**
+ * Appends the given string to the contents of the buffer.
+ * This buffer will now have unsaved changes.
+ * Any client can append to the contents of the buffer, not just the owner of the buffer.
+ * Reports a buffer changed event.
+ * <p>
+ * Has no effect if this buffer is read-only.
+ * <p>
+ * A <code>RuntimeException</code> might be thrown if the buffer is closed.
+ *
+ * @param text the <code>String</code> to append to the contents of the buffer
+ */
+public void append(String text);
+/**
+ * Closes the buffer. Any unsaved changes are lost. Reports a buffer changed event
+ * with a 0 offset and a 0 length. When this event is fired, the buffer should already
+ * be closed.
+ * <p>
+ * Further operations on the buffer are not allowed, except for close.  If an
+ * attempt is made to close an already closed buffer, the second attempt has no effect.
+ */
+public void close();
+/**
+ * Returns the character at the given position in this buffer.
+ * <p>
+ * A <code>RuntimeException</code> might be thrown if the buffer is closed.
+ *
+ * @param position a zero-based source offset in this buffer
+ * @return the character at the given position in this buffer
+ */
+public char getChar(int position);
+/**
+ * Returns the contents of this buffer as a character array, or <code>null</code> if
+ * the buffer has not been initialized.
+ * <p>
+ * Callers should make no assumption about whether the returned character array
+ * is or is not the genuine article or a copy. In other words, if the client
+ * wishes to change this array, they should make a copy. Likewise, if the
+ * client wishes to hang on to the array in its current state, they should
+ * make a copy.
+ * </p>
+ * <p>
+ * A <code>RuntimeException</code> might be thrown if the buffer is closed.
+ *
+ * @return the characters contained in this buffer
+ */
+public char[] getCharacters();
+/**
+ * Returns the contents of this buffer as a <code>String</code>. Like all strings,
+ * the result is an immutable value object., It can also answer <code>null</code> if
+ * the buffer has not been initialized.
+ * <p>
+ * A <code>RuntimeException</code> might be thrown if the buffer is closed.
+ *
+ * @return the contents of this buffer as a <code>String</code>
+ */
+public String getContents();
+/**
+ * Returns number of characters stored in this buffer.
+ * <p>
+ * A <code>RuntimeException</code> might be thrown if the buffer is closed.
+ *
+ * @return the number of characters in this buffer
+ */
+public int getLength();
+/**
+ * Returns the 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.
+ * <p>
+ * A <code>RuntimeException</code> might be thrown if the buffer is closed.
+ *
+ * @param offset the  zero-based starting offset
+ * @param length the number of characters to retrieve
+ * @return the given range of text in this buffer
+ */
+public String getText(int offset, int length);
+/**
+ * Returns the underlying resource for which this buffer was opened,
+ * or <code>null</code> if this buffer was not opened on a resource.
+ *
+ * @return the underlying resource for this buffer, or <code>null</code>
+ *  if none.
+ */
+public IResource getUnderlyingResource();
+/**
+ * Returns whether this buffer has been modified since it
+ * was opened or since it was last saved.
+ * If a buffer does not have an underlying resource, this method always
+ * returns <code>true</code>.
+ *
+ * @return a <code>boolean</code> indicating presence of unsaved changes (in
+ *   the absence of any underlying resource, it will always return <code>true</code>).
+ */
+public boolean hasUnsavedChanges();
+/**
+ * Returns whether this buffer has been closed.
+ *
+ * @return a <code>boolean</code> indicating whether this buffer is closed.
+ */
+public boolean isClosed();
+/**
+ * Returns whether this buffer is read-only.
+ *
+ * @return a <code>boolean</code> indicating whether this buffer is read-only
+ */
+public boolean isReadOnly();
+/**
+ * Removes the given listener from this buffer.
+ * Has no affect if an identical listener is not registered or if the buffer is closed.
+ *
+ * @param listener the listener
+ */
+public void removeBufferChangedListener(IBufferChangedListener listener);
+/**
+ * Replaces the given range of characters in this buffer with the given text.
+ * <code>position</code> and <code>position + length</code> must be in the range [0, getLength()].
+ * <code>length</code> must not be negative.
+ * <p>
+ * A <code>RuntimeException</code> might be thrown if the buffer is closed.
+ *
+ * @param position the zero-based starting position of the affected text range in this buffer
+ * @param length the length of the affected text range in this buffer
+ * @param text the replacing text as a character array
+ */
+public void replace(int position, int length, char[] text);
+/**
+ * Replaces the given range of characters in this buffer with the given text.
+ * <code>position</code> and <code>position + length</code> must be in the range [0, getLength()].
+ * <code>length</code> must not be negative.
+ * <p>
+ * A <code>RuntimeException</code> might be thrown if the buffer is closed.
+ *
+ * @param position the zero-based starting position of the affected text range in this buffer
+ * @param length the length of the affected text range in this buffer
+ * @param text the replacing text as a <code>String</code>
+ */
+public void replace(int position, int length, String text);
+/**
+ * Saves the contents of this buffer to its underlying resource. If
+ * successful, this buffer will have no unsaved changes.
+ * The buffer is left open. Saving a buffer with no unsaved
+ * changes has no effect - the underlying resource is not changed.
+ * If the buffer does not have an underlying resource or is read-only, this
+ * has no effect.
+ * <p>
+ * The <code>force</code> parameter controls how this method deals with
+ * cases where the workbench is not completely in sync with the local file system.
+ * If <code>false</code> is specified, this method will only attempt
+ * to overwrite a corresponding file in the local file system provided
+ * it is in sync with the workbench. This option ensures there is no 
+ * unintended data loss; it is the recommended setting.
+ * However, if <code>true</code> is specified, an attempt will be made
+ * to write a corresponding file in the local file system, 
+ * overwriting any existing one if need be.
+ * In either case, if this method succeeds, the resource will be marked 
+ * as being local (even if it wasn't before).
+ * <p>
+ * A <code>RuntimeException</code> might be thrown if the buffer is closed.
+ *
+ * @param progress the progress monitor to notify
+ * @param force a <code> boolean </code> flag indicating how to deal with resource
+ *   inconsistencies.
+ *
+ * @exception 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.
+ * <p>
+ * Equivalent to <code>replace(0,getLength(),contents)</code>.
+ * </p>
+ * <p>
+ * Has no effect if this buffer is read-only.
+ * <p>
+ * A <code>RuntimeException</code> might be thrown if the buffer is closed.
+ *
+ * @param contents the new contents of this buffer as a character array
+ */
+public void setContents(char[] contents);
+/**
+ * Sets the contents of this buffer to the given <code>String</code>.
+ * This buffer will now have unsaved changes.
+ * Any client can set the contents of the buffer, not just the owner of the buffer.
+ * Reports a buffer changed event.
+ * <p>
+ * Equivalent to <code>replace(0,getLength(),contents)</code>.
+ * </p>
+ * <p>
+ * Has no effect if this buffer is read-only.
+ * <p>
+ * A <code>RuntimeException</code> might be thrown if the buffer is closed.
+ *
+ * @param contents the new contents of this buffer as a <code>String</code>
+ */
+public void setContents(String contents);
+}
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 (file)
index 0000000..1cfe50d
--- /dev/null
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     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 <em>after</em> the buffer has been closed.
+ * A listener is not notified when a buffer is saved.
+ * <p>
+ * This interface may be implemented by clients.
+ * </p>
+ */
+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 (file)
index 0000000..38c45db
--- /dev/null
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.core;
+
+/**
+ * A factory that creates <code>IBuffer</code>s for openables.
+ * <p>
+ * This interface may be implemented by clients.
+ * </p>
+ * @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 <code>null</code>).
+        * 
+        * @param owner the owner of the buffer
+        * @see IBuffer
+        */
+       IBuffer createBuffer(IOpenable owner);
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/ICodeAssist.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/ICodeAssist.java
new file mode 100644 (file)
index 0000000..5f3c04c
--- /dev/null
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.core;
+
+/**
+ * Common protocol for Java elements that support source code assist and code
+ * resolve.
+ * <p>
+ * This interface is not intended to be implemented by clients.
+ * </p>
+ */
+public interface ICodeAssist {
+
+       /**
+        * Performs code completion at the given offset position in this compilation unit,
+        * reporting results to the given completion requestor. The <code>offset</code>
+        * is the 0-based index of the character, after which code assist is desired.
+        * An <code>offset</code> of -1 indicates to code assist at the beginning of this
+        * compilation unit.
+        *
+        * @param offset the given offset position
+        * @param requestor the given completion requestor
+        * @exception JavaModelException if code assist could not be performed. Reasons include:<ul>
+        *  <li>This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+        *  <li> The position specified is < -1 or is greater than this compilation unit's
+        *      source length (INDEX_OUT_OF_BOUNDS)
+        * </ul>
+        *
+        * @exception IllegalArgumentException if <code>requestor</code> is <code>null</code>
+        * @since 2.0
+        *       */
+       void codeComplete(int offset, ICompletionRequestor requestor)
+               throws JavaModelException;
+       /**
+        * Performs code selection on the given selected text in this compilation unit,
+        * reporting results to the given selection requestor. The <code>offset</code>
+        * is the 0-based index of the first selected character. The <code>length</code> 
+        * is the number of selected characters.
+        * 
+        * @param offset the given offset position
+        * @param length the number of selected characters
+        *
+        * @exception JavaModelException if code resolve could not be performed. Reasons include:
+        *  <li>This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+        *  <li> The range specified is not within this element's
+        *      source range (INDEX_OUT_OF_BOUNDS)
+        * </ul>
+        *
+        */
+       IJavaElement[] codeSelect(int offset, int length) throws JavaModelException;
+
+       /**
+        * Performs code completion at the given offset position in this compilation unit,
+        * reporting results to the given completion requestor. The <code>offset</code>
+        * is the 0-based index of the character, after which code assist is desired.
+        * An <code>offset</code> of -1 indicates to code assist at the beginning of this
+        * compilation unit.
+        * 
+        * @param offset the given offset position
+        * @param requestor the given completion requestor
+        *
+        * @exception JavaModelException if code assist could not be performed. Reasons include:<ul>
+        *  <li>This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+        *  <li> The position specified is < -1 or is greater than this compilation unit's
+        *      source length (INDEX_OUT_OF_BOUNDS)
+        * </ul>
+        *
+        * @exception IllegalArgumentException if <code>requestor</code> is <code>null</code>
+        * @deprecated - use codeComplete(int, ICompletionRequestor) instead
+        */
+//     void codeComplete(int offset, ICodeCompletionRequestor requestor)
+//             throws JavaModelException;
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/ICodeFormatter.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/ICodeFormatter.java
new file mode 100644 (file)
index 0000000..15d6dcb
--- /dev/null
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.core;
+
+/**
+ * Specification for a generic source code formatter. Client plug-ins can contribute
+ * an implementation for an ICodeFormatter, through the extension point "net.sourceforge.phpdt.core.codeFormatter".
+ * In case none is found, a default formatter can be provided through the ToolFactory.
+ * 
+ * @see ToolFactory#createCodeFormatter()
+ * @see ToolFactory#createDefaultCodeFormatter(Map options)
+ * @since 2.0
+ */
+public interface ICodeFormatter {
+
+       /** 
+        * Formats the String <code>sourceString</code>,
+        * and returns a string containing the formatted version.
+        * 
+        * @param string the string to format
+        * @param indentationLevel the initial indentation level, used 
+        *      to shift left/right the entire source fragment. An initial indentation
+        *      level of zero has no effect.
+        * @param positions an array of positions to map. These are
+        *      character-based source positions inside the original source,
+        *     for which corresponding positions in the formatted source will
+        *     be computed (so as to relocate elements associated with the original
+        *     source). It updates the positions array with updated positions.
+        *     If set to <code>null</code>, then no positions are mapped.
+        * @param lineSeparator the line separator to use in formatted source,
+        *     if set to <code>null</code>, then the platform default one will be used.
+        * @return the formatted output string.
+        */
+       String format(String string, int indentationLevel, int[] positions, String lineSeparator);
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/ICompilationUnit.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/ICompilationUnit.java
new file mode 100644 (file)
index 0000000..4d44420
--- /dev/null
@@ -0,0 +1,208 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.core;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+
+/**
+ * Represents an entire Java compilation unit (<code>.java</code> source file).
+ * Compilation unit elements need to be opened before they can be navigated or manipulated.
+ * The children are of type <code>IPackageDeclaration</code>,
+ * <code>IImportContainer</code>, and <code>IType</code>,
+ * and appear in the order in which they are declared in the source.
+ * If a <code>.java</code> file cannot be parsed, its structure remains unknown.
+ * Use <code>IJavaElement.isStructureKnown</code> to determine whether this is 
+ * the case.
+ * <p>
+ * This interface is not intended to be implemented by clients.
+ * </p>
+ */
+public interface ICompilationUnit extends IJavaElement, ISourceReference, IParent, IOpenable, IWorkingCopy, ISourceManipulation, ICodeAssist {
+/**
+ * Creates and returns an import declaration in this compilation unit
+ * with the given name.
+ * <p>
+ * Optionally, the new element can be positioned before the specified
+ * sibling. If no sibling is specified, the element will be inserted
+ * as the last import declaration in this compilation unit.
+ * <p>
+ * If the compilation unit already includes the specified import declaration,
+ * the import is not generated (it does not generate duplicates).
+ * Note that it is valid to specify both a single-type import and an on-demand import
+ * for the same package, for example <code>"java.io.File"</code> and
+ * <code>"java.io.*"</code>, in which case both are preserved since the semantics
+ * of this are not the same as just importing <code>"java.io.*"</code>.
+ * Importing <code>"java.lang.*"</code>, or the package in which the compilation unit
+ * is defined, are not treated as special cases.  If they are specified, they are
+ * included in the result.
+ *
+ * @param name the name of the import declaration to add as defined by JLS2 7.5. (For example: <code>"java.io.File"</code> or
+ *  <code>"java.awt.*"</code>)
+ * @param sibling the existing element which the import declaration will be inserted immediately before (if
+ *     <code> null </code>, then this import will be inserted as the last import declaration.
+ * @param monitor the progress monitor to notify
+ * @return the newly inserted import declaration (or the previously existing one in case attempting to create a duplicate)
+ *
+ * @exception JavaModelException if the element could not be created. Reasons include:
+ * <ul>
+ * <li> This Java element does not exist or the specified sibling does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+ * <li> A <code>CoreException</code> occurred while updating an underlying resource
+ * <li> The specified sibling is not a child of this compilation unit (INVALID_SIBLING)
+ * <li> The name is not a valid import name (INVALID_NAME)
+ * </ul>
+ */
+//IImportDeclaration createImport(String name, IJavaElement sibling, IProgressMonitor monitor) throws JavaModelException;
+/**
+ * Creates and returns a package declaration in this compilation unit
+ * with the given package name.
+ *
+ * <p>If the compilation unit already includes the specified package declaration,
+ * it is not generated (it does not generate duplicates).
+ *
+ * @param name the name of the package declaration to add as defined by JLS2 7.4. (For example, <code>"java.lang"</code>)
+ * @param monitor the progress monitor to notify
+ * @return the newly inserted package declaration (or the previously existing one in case attempting to create a duplicate)
+ *
+ * @exception JavaModelException if the element could not be created. Reasons include:
+ * <ul>
+ * <li>This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+ * <li> A <code>CoreException</code> occurred while updating an underlying resource
+ * <li> The name is not a valid package name (INVALID_NAME)
+ * </ul>
+ */
+ //IPackageDeclaration createPackageDeclaration(String name, IProgressMonitor monitor) throws JavaModelException;   
+/**
+ * Creates and returns a type in this compilation unit with the
+ * given contents. If this compilation unit does not exist, one
+ * will be created with an appropriate package declaration.
+ * <p>
+ * Optionally, the new type can be positioned before the specified
+ * sibling. If <code>sibling</code> is <code>null</code>, the type will be appended
+ * to the end of this compilation unit.
+ *
+ * <p>It is possible that a type with the same name already exists in this compilation unit.
+ * The value of the <code>force</code> parameter effects the resolution of
+ * such a conflict:<ul>
+ * <li> <code>true</code> - in this case the type is created with the new contents</li>
+ * <li> <code>false</code> - in this case a <code>JavaModelException</code> is thrown</li>
+ * </ul>
+ *
+ * @param contents the source contents of the type declaration to add.
+ * @param sibling the existing element which the type will be inserted immediately before (if
+ *     <code> null </code>, then this type will be inserted as the last type declaration.
+ * @param force a <code> boolean </code> flag indicating how to deal with duplicates
+ * @param monitor the progress monitor to notify
+ * @return the newly inserted type
+ *
+ * @exception JavaModelException if the element could not be created. Reasons include:
+ * <ul>
+ * <li>The specified sibling element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+ * <li> A <code>CoreException</code> occurred while updating an underlying resource
+ * <li> The specified sibling is not a child of this compilation unit (INVALID_SIBLING)
+ * <li> The contents could not be recognized as a type declaration (INVALID_CONTENTS)
+ * <li> There was a naming collision with an existing type (NAME_COLLISION)
+ * </ul>
+ */
+IType createType(String contents, IJavaElement sibling, boolean force, IProgressMonitor monitor) throws JavaModelException;
+/**
+ * Returns all types declared in this compilation unit in the order
+ * in which they appear in the source. 
+ * This includes all top-level types and nested member types.
+ * It does NOT include local types (types defined in methods).
+ *
+ * @return the array of top-level and member types defined in a compilation unit, in declaration order.
+ * @exception JavaModelException if this element does not exist or if an
+ *             exception occurs while accessing its corresponding resource
+ */
+IType[] getAllTypes() throws JavaModelException;
+/**
+ * Returns the smallest element within this compilation unit that 
+ * includes the given source position (that is, a method, field, etc.), or
+ * <code>null</code> if there is no element other than the compilation
+ * unit itself at the given position, or if the given position is not
+ * within the source range of this compilation unit.
+ *
+ * @param position a source position inside the compilation unit
+ * @return the innermost Java element enclosing a given source position or <code>null</code>
+ *     if none (excluding the compilation unit).
+ * @exception JavaModelException if the compilation unit does not exist or if an
+ *             exception occurs while accessing its corresponding resource
+ */
+IJavaElement getElementAt(int position) throws JavaModelException;
+/**
+ * Returns the first import declaration in this compilation unit with the given name.
+ * This is a handle-only method. The import declaration may or may not exist. This
+ * is a convenience method - imports can also be accessed from a compilation unit's
+ * import container.
+ *
+ * @param name the name of the import to find as defined by JLS2 7.5. (For example: <code>"java.io.File"</code> 
+ *     or <code>"java.awt.*"</code>)
+ * @return a handle onto the corresponding import declaration. The import declaration may or may not exist.
+ */
+// IImportDeclaration getImport(String name) ;
+/**
+ * Returns the import container for this compilation unit.
+ * This is a handle-only method. The import container may or
+ * may not exist. The import container can used to access the 
+ * imports.
+ * @return a handle onto the corresponding import container. The 
+ *             import contain may or may not exist.
+ */
+// IImportContainer getImportContainer();
+/**
+ * Returns the import declarations in this compilation unit
+ * in the order in which they appear in the source. This is
+ * a convenience method - import declarations can also be
+ * accessed from a compilation unit's import container.
+ *
+ * @exception JavaModelException if this element does not exist or if an
+ *             exception occurs while accessing its corresponding resource
+ */
+// IImportDeclaration[] getImports() throws JavaModelException;
+/**
+ * Returns the first package declaration in this compilation unit with the given package name
+ * (there normally is at most one package declaration).
+ * This is a handle-only method. The package declaration may or may not exist.
+ *
+ * @param name the name of the package declaration as defined by JLS2 7.4. (For example, <code>"java.lang"</code>)
+ */
+// IPackageDeclaration getPackageDeclaration(String name);
+/**
+ * Returns the package declarations in this compilation unit
+ * in the order in which they appear in the source.
+ * There normally is at most one package declaration.
+ *
+ * @return an array of package declaration (normally of size one)
+ *
+ * @exception JavaModelException if this element does not exist or if an
+ *             exception occurs while accessing its corresponding resource
+ */
+// IPackageDeclaration[] getPackageDeclarations() throws JavaModelException;
+/**
+ * Returns the top-level type declared in this compilation unit with the given simple type name.
+ * The type name has to be a valid compilation unit name.
+ * This is a handle-only method. The type may or may not exist.
+ *
+ * @param name the simple name of the requested type in the compilation unit
+ * @return a handle onto the corresponding type. The type may or may not exist.
+ * @see JavaConventions#validateCompilationUnitName(String name)
+ */
+IType getType(String name);
+/**
+ * Returns the top-level types declared in this compilation unit
+ * in the order in which they appear in the source.
+ *
+ * @exception JavaModelException if this element does not exist or if an
+ *             exception occurs while accessing its corresponding resource
+ */
+IType[] getTypes() throws JavaModelException;
+
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/ICompletionRequestor.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/ICompletionRequestor.java
new file mode 100644 (file)
index 0000000..4586a1d
--- /dev/null
@@ -0,0 +1,405 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.core;
+
+import net.sourceforge.phpdt.core.compiler.IProblem;
+
+/**
+ * A completion requestor accepts results as they are computed and is aware
+ * of source positions to complete the various different results.
+ * <p>
+ * This interface may be implemented by clients.
+ * </p>
+ *
+ * @see ICodeAssist
+ * @since 2.0
+ */
+public interface ICompletionRequestor {
+/**
+ * Code assist notification of an anonymous type declaration completion.
+ * @param superTypePackageName Name of the package that contains the super type of this 
+ *             new anonymous type declaration .
+ * 
+ * @param superTypeName Name of the super type of this new anonymous type declaration.
+ * 
+ * @param parameterPackageNames Names of the packages in which the parameter types are declared.
+ *     Should contain as many elements as parameterTypeNames.
+ * 
+ * @param parameterTypeNames Names of the parameters types. 
+ *             Should contain as many elements as parameterPackageNames.
+ * 
+ * @param completionName The completion for the anonymous type declaration.
+ *             Can include zero, one or two brackets. If the closing bracket is included,
+ *             then the cursor should be placed before it.
+ * 
+ * @param modifiers The modifiers of the constructor.
+ * 
+ * @param completionStart The start position of insertion of the name of this new anonymous type declaration.
+ * 
+ * @param completionEnd The end position of insertion of the name of this new anonymous type declaration.
+ * 
+ * @param relevance The relevance of the completion proposal
+ *             It is a positive integer which are used for determine if this proposal is more relevant than another proposal.
+ *             This value can only be used for compare relevance. A proposal is more relevant than another if his relevance
+ *             value is higher.
+ * 
+ * NOTE - All package and type names are presented in their readable form:
+ *    Package names are in the form "a.b.c".
+ *    Base types are in the form "int" or "boolean".
+ *    Array types are in the qualified form "M[]" or "int[]".
+ *    Nested type names are in the qualified form "A.M".
+ *    The default package is represented by an empty array.
+ *
+ * NOTE: parameter names can be retrieved from the source model after the user selects a specific method.
+ */
+void acceptAnonymousType(
+       char[] superTypePackageName,
+       char[] superTypeName,
+       char[][] parameterPackageNames,
+       char[][] parameterTypeNames,
+       char[][] parameterNames,
+       char[] completionName,
+       int modifiers,
+       int completionStart,
+       int completionEnd,
+       int relevance);
+/**
+ * Code assist notification of a class completion.
+ * 
+ * @param packageName Declaring package name of the class.
+ * @param className Name of the class.
+ * @param completionName The completion for the class. Can include ';' for imported classes.
+ * @param modifiers The modifiers of the class.
+ * @param completionStart The start position of insertion of the name of the class.
+ * @param completionEnd The end position of insertion of the name of the class.
+ * @param relevance The relevance of the completion proposal
+ *             It is a positive integer which are used for determine if this proposal is more relevant than another proposal.
+ *             This value can only be used for compare relevance. A proposal is more relevant than another if his relevance
+ *             value is higher.
+ *
+ * NOTE - All package and type names are presented in their readable form:
+ *    Package names are in the form "a.b.c".
+ *    Nested type names are in the qualified form "A.M".
+ *    The default package is represented by an empty array.
+ */
+void acceptClass(
+       char[] packageName,
+       char[] className,
+       char[] completionName,
+       int modifiers,
+       int completionStart,
+       int completionEnd,
+       int relevance);
+/**
+ * Code assist notification of a compilation error detected during completion.
+ *  @param error Only problems which are categorized as non-syntax errors are notified to the 
+ *     requestor, warnings are silently ignored.
+ *             In case an error got signalled, no other completions might be available,
+ *             therefore the problem message should be presented to the user.
+ *             The source positions of the problem are related to the source where it was
+ *             detected (might be in another compilation unit, if it was indirectly requested
+ *             during the code assist process).
+ *      Note: the problem knows its originating file name.
+ */
+void acceptError(IProblem error);
+/**
+ * Code assist notification of a field completion.
+ * 
+ * @param declaringTypePackageName Name of the package in which the type that contains this field is declared.
+ * @param declaringTypeName Name of the type declaring this new field.
+ * @param name Name of the field.
+ * @param typePackageName Name of the package in which the type of this field is declared.
+ * @param typeName Name of the type of this field.
+ * @param completionName The completion for the field.
+ * @param modifiers The modifiers of this field.
+ * @param completionStart The start position of insertion of the name of this field.
+ * @param completionEnd The end position of insertion of the name of this field.
+ * @param relevance The relevance of the completion proposal
+ *             It is a positive integer which are used for determine if this proposal is more relevant than another proposal.
+ *             This value can only be used for compare relevance. A proposal is more relevant than another if his relevance
+ *             value is higher.
+ * 
+ * NOTE - All package and type names are presented in their readable form:
+ *    Package names are in the form "a.b.c".
+ *    Base types are in the form "int" or "boolean".
+ *    Array types are in the qualified form "M[]" or "int[]".
+ *    Nested type names are in the qualified form "A.M".
+ *    The default package is represented by an empty array.
+ */
+void acceptField(
+       char[] declaringTypePackageName,
+       char[] declaringTypeName,
+       char[] name,
+       char[] typePackageName,
+       char[] typeName,
+       char[] completionName,
+       int modifiers,
+       int completionStart,
+       int completionEnd,
+       int relevance);
+/**
+ * Code assist notification of an interface completion.
+ * 
+ * @param packageName Declaring package name of the interface.
+ * @param className Name of the interface.
+ * @param completionName The completion for the interface.     Can include ';' for imported interfaces.
+ * @param modifiers The modifiers of the interface.
+ * @param completionStart The start position of insertion of the name of the interface.
+ * @param completionEnd The end position of insertion of the name of the interface.
+ * @param relevance The relevance of the completion proposal
+ *             It is a positive integer which are used for determine if this proposal is more relevant than another proposal.
+ *             This value can only be used for compare relevance. A proposal is more relevant than another if his relevance
+ *             value is higher.
+ *
+ * NOTE - All package and type names are presented in their readable form:
+ *    Package names are in the form "a.b.c".
+ *    Nested type names are in the qualified form "A.M".
+ *    The default package is represented by an empty array.
+ */
+void acceptInterface(
+       char[] packageName,
+       char[] interfaceName,
+       char[] completionName,
+       int modifiers,
+       int completionStart,
+       int completionEnd,
+       int relevance);
+/**
+ * Code assist notification of a keyword completion.
+ * @param keywordName The keyword source.
+ * @param completionStart The start position of insertion of the name of this keyword.
+ * @param completionEnd The end position of insertion of the name of this keyword.
+ * @param relevance The relevance of the completion proposal
+ *             It is a positive integer which are used for determine if this proposal is more relevant than another proposal.
+ *             This value can only be used for compare relevance. A proposal is more relevant than another if his relevance
+ *             value is higher.
+ */
+void acceptKeyword(char[] keywordName, int completionStart, int completionEnd, int relevance);
+/**
+ * Code assist notification of a label completion.
+ * 
+ * @param labelName The label source.
+ * @param completionStart The start position of insertion of the name of this label.
+ * @param completionEnd The end position of insertion of the name of this label.
+ * @param relevance The relevance of the completion proposal
+ *             It is a positive integer which are used for determine if this proposal is more relevant than another proposal.
+ *             This value can only be used for compare relevance. A proposal is more relevant than another if his relevance
+ *             value is higher.
+ */
+void acceptLabel(char[] labelName, int completionStart, int completionEnd, int relevance);
+/**
+ * Code assist notification of a local variable completion.
+ * 
+ * @param name Name of the new local variable.
+ * @param typePackageName Name of the package in which the type of this new local variable is declared.
+ * @param typeName Name of the type of this new local variable.
+ * @param modifiers The modifiers of this new local variable.
+ * @param completionStart The start position of insertion of the name of this new local variable.
+ * @param completionEnd The end position of insertion of the name of this new local variable.
+ * @param relevance The relevance of the completion proposal
+ *             It is a positive integer which are used for determine if this proposal is more relevant than another proposal.
+ *             This value can only be used for compare relevance. A proposal is more relevant than another if his relevance
+ *             value is higher.
+ *
+ * NOTE - All package and type names are presented in their readable form:
+ *    Package names are in the form "a.b.c".
+ *    Base types are in the form "int" or "boolean".
+ *    Array types are in the qualified form "M[]" or "int[]".
+ *    Nested type names are in the qualified form "A.M".
+ *    The default package is represented by an empty array.
+ */
+void acceptLocalVariable(
+       char[] name,
+       char[] typePackageName,
+       char[] typeName,
+       int modifiers,
+       int completionStart,
+       int completionEnd,
+       int relevance);
+/**
+ * Code assist notification of a method completion.
+ * 
+ * @param declaringTypePackageName Name of the package in which the type that contains this new method is declared.
+ * @param declaringTypeName Name of the type declaring this new method.
+ * @param selector Name of the new method.
+ * @param parameterPackageNames Names of the packages in which the parameter types are declared.
+ *     Should contain as many elements as parameterTypeNames.
+ * @param parameterTypeNames Names of the parameters types.
+ *     Should contain as many elements as parameterPackageNames.
+ * @param returnTypePackageName Name of the package in which the return type is declared.
+ * @param returnTypeName Name of the return type of this new method, should be <code>null</code> for a constructor.
+ * @param completionName The completion for the method. Can include zero, one or two brackets. If the closing bracket is included, then the cursor should be placed before it.
+ * @param modifiers The modifiers of this new method.
+ * @param completionStart The start position of insertion of the name of this new method.
+ * @param completionEnd The end position of insertion of the name of this new method.
+ * @param relevance The relevance of the completion proposal
+ *             It is a positive integer which are used for determine if this proposal is more relevant than another proposal.
+ *             This value can only be used for compare relevance. A proposal is more relevant than another if his relevance
+ *             value is higher.
+ *
+ * NOTE - All package and type names are presented in their readable form:
+ *    Package names are in the form "a.b.c".
+ *    Base types are in the form "int" or "boolean".
+ *    Array types are in the qualified form "M[]" or "int[]".
+ *    Nested type names are in the qualified form "A.M".
+ *    The default package is represented by an empty array.
+ *
+ * NOTE: parameter names can be retrieved from the source model after the user selects a specific method.
+ */
+void acceptMethod(
+       char[] declaringTypePackageName,
+       char[] declaringTypeName,
+       char[] selector,
+       char[][] parameterPackageNames,
+       char[][] parameterTypeNames,
+       char[][] parameterNames,
+       char[] returnTypePackageName,
+       char[] returnTypeName,
+       char[] completionName,
+       int modifiers,
+       int completionStart,
+       int completionEnd,
+       int relevance);
+
+/**
+ * Code assist notification of a method completion.
+ * 
+ * @param declaringTypePackageName Name of the package in which the type that contains this new method is declared.
+ * @param declaringTypeName Name of the type declaring this new method.
+ * @param selector Name of the new method.
+ * @param parameterPackageNames Names of the packages in which the parameter types are declared.
+ *     Should contain as many elements as parameterTypeNames.
+ * @param parameterTypeNames Names of the parameters types.
+ *     Should contain as many elements as parameterPackageNames.
+ * @param returnTypePackageName Name of the package in which the return type is declared.
+ * @param returnTypeName Name of the return type of this new method, should be <code>null</code> for a constructor.
+ * @param completionName The completion for the method. Can include zero, one or two brackets. If the closing bracket is included, then the cursor should be placed before it.
+ * @param modifiers The modifiers of this new method.
+ * @param completionStart The start position of insertion of the name of this new method.
+ * @param completionEnd The end position of insertion of the name of this new method.
+ * @param relevance The relevance of the completion proposal
+ *             It is a positive integer which are used for determine if this proposal is more relevant than another proposal.
+ *             This value can only be used for compare relevance. A proposal is more relevant than another if his relevance
+ *             value is higher.
+ *
+ * NOTE - All package and type names are presented in their readable form:
+ *    Package names are in the form "a.b.c".
+ *    Base types are in the form "int" or "boolean".
+ *    Array types are in the qualified form "M[]" or "int[]".
+ *    Nested type names are in the qualified form "A.M".
+ *    The default package is represented by an empty array.
+ *
+ * NOTE: parameter names can be retrieved from the source model after the user selects a specific method.
+ */
+void acceptMethodDeclaration(
+       char[] declaringTypePackageName,
+       char[] declaringTypeName,
+       char[] selector,
+       char[][] parameterPackageNames,
+       char[][] parameterTypeNames,
+       char[][] parameterNames,
+       char[] returnTypePackageName,
+       char[] returnTypeName,
+       char[] completionName,
+       int modifiers,
+       int completionStart,
+       int completionEnd,
+       int relevance);
+/**
+ * Code assist notification of a modifier completion.
+ * 
+ * @param modifierName The new modifier.
+ * @param completionStart The start position of insertion of the name of this new modifier.
+ * @param completionEnd The end position of insertion of the name of this new modifier.
+ * @param relevance The relevance of the completion proposal
+ *             It is a positive integer which are used for determine if this proposal is more relevant than another proposal.
+ *             This value can only be used for compare relevance. A proposal is more relevant than another if his relevance
+ *             value is higher.
+ */
+void acceptModifier(char[] modifierName, int completionStart, int completionEnd, int relevance);
+/**
+ * Code assist notification of a package completion.
+ * 
+ * @param packageName The package name.
+ * @param completionName The completion for the package. Can include '.*;' for imports.
+ * @param completionStart The start position of insertion of the name of this new package.
+ * @param completionEnd The end position of insertion of the name of this new package.
+ * @param relevance The relevance of the completion proposal
+ *             It is a positive integer which are used for determine if this proposal is more relevant than another proposal.
+ *             This value can only be used for compare relevance. A proposal is more relevant than another if his relevance
+ *             value is higher.
+ *
+ * NOTE - All package names are presented in their readable form:
+ *    Package names are in the form "a.b.c".
+ *    The default package is represented by an empty array.
+ */
+void acceptPackage(
+       char[] packageName,
+       char[] completionName,
+       int completionStart,
+       int completionEnd,
+       int relevance);
+/**
+ * Code assist notification of a type completion.
+ * 
+ * @param packageName Declaring package name of the type.
+ * @param typeName Name of the type.
+ * @param completionName The completion for the type. Can include ';' for imported types.
+ * @param completionStart The start position of insertion of the name of the type.
+ * @param completionEnd The end position of insertion of the name of the type.
+ * @param relevance The relevance of the completion proposal
+ *             It is a positive integer which are used for determine if this proposal is more relevant than another proposal.
+ *             This value can only be used for compare relevance. A proposal is more relevant than another if his relevance
+ *             value is higher.
+ *
+ * NOTE - All package and type names are presented in their readable form:
+ *    Package names are in the form "a.b.c".
+ *    Nested type names are in the qualified form "A.M".
+ *    The default package is represented by an empty array.
+ */
+void acceptType(
+       char[] packageName,
+       char[] typeName,
+       char[] completionName,
+       int completionStart,
+       int completionEnd,
+       int relevance);
+       
+/**
+ * Code assist notification of a variable name completion.
+ * 
+ * @param typePackageName Name of the package in which the type of this variable is declared.
+ * @param typeName Name of the type of this variable.
+ * @param name Name of the variable.
+ * @param completionName The completion for the variable.
+ * @param completionStart The start position of insertion of the name of this variable.
+ * @param completionEnd The end position of insertion of the name of this variable.
+ * @param relevance The relevance of the completion proposal
+ *             It is a positive integer which are used for determine if this proposal is more relevant than another proposal.
+ *             This value can only be used for compare relevance. A proposal is more relevant than another if his relevance
+ *             value is higher.
+ *
+ * NOTE - All package and type names are presented in their readable form:
+ *    Package names are in the form "a.b.c".
+ *    Base types are in the form "int" or "boolean".
+ *    Array types are in the qualified form "M[]" or "int[]".
+ *    Nested type names are in the qualified form "A.M".
+ *    The default package is represented by an empty array.
+ */
+void acceptVariableName(
+       char[] typePackageName,
+       char[] typeName,
+       char[] name,
+       char[] completionName,
+       int completionStart,
+       int completionEnd,
+       int relevance);
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IField.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IField.java
new file mode 100644 (file)
index 0000000..51facdc
--- /dev/null
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.core;
+
+/**
+ * Represents a field declared in a type.
+ * <p>
+ * This interface is not intended to be implemented by clients.
+ * </p>
+ */
+public interface IField extends IMember {
+/**
+ * Returns the constant value associated with this field
+ * or <code>null</code> if this field has none.
+ * Returns either a subclass of <code>Number</code>, or a <code>String</code>,
+ * depending on the type of the field.
+ * For example, if the field is of type <code>short</code>, this returns
+ * a <code>Short</code>.
+ *
+ * @return  the constant value associated with this field or <code>null</code> if this field has none.
+ * @exception JavaModelException if this element does not exist or if an
+ *      exception occurs while accessing its corresponding resource
+ */
+public Object getConstant() throws JavaModelException;
+/**
+ * Returns the simple name of this field.
+ * @return the simple name of this field.
+ */
+String getElementName();
+/**
+ * Returns the type signature of this field.
+ *
+ * @see Signature
+ * @return the type signature of this field.
+ * @exception JavaModelException if this element does not exist or if an
+ *      exception occurs while accessing its corresponding resource
+ */
+String getTypeSignature() throws JavaModelException;
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IInitializer.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IInitializer.java
new file mode 100644 (file)
index 0000000..5614f8d
--- /dev/null
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.core;
+
+/**
+ * Represents a stand-alone instance or class (static) initializer in a type.
+ * <p>
+ * This interface is not intended to be implemented by clients.
+ * </p>
+ */
+public interface IInitializer extends IMember {
+}
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 (file)
index 0000000..ef4851d
--- /dev/null
@@ -0,0 +1,275 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     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.
+ * <p>
+ * Methods annotated as "handle-only" do not require underlying elements to exist. 
+ * Methods that require underlying elements to exist throw
+ * a <code>JavaModelException</code> when an underlying element is missing.
+ * <code>JavaModelException.isDoesNotExist</code> can be used to recognize
+ * this common special case.
+ * </p>
+ * <p>
+ * This interface is not intended to be implemented by clients.
+ * </p>
+ */
+public interface IJavaElement extends IAdaptable {
+
+       /**
+        * Constant representing a Java model (workspace level object).
+        * A Java element with this type can be safely cast to <code>IJavaModel</code>.
+        */
+       public static final int JAVA_MODEL = 1;
+
+       /**
+        * Constant representing a Java project.
+        * A Java element with this type can be safely cast to <code>IJavaProject</code>.
+        */
+       public static final int JAVA_PROJECT = 2;
+
+       /**
+        * Constant representing a package fragment root.
+        * A Java element with this type can be safely cast to <code>IPackageFragmentRoot</code>.
+        */
+       public static final int PACKAGE_FRAGMENT_ROOT = 3;
+
+       /**
+        * Constant representing a package fragment.
+        * A Java element with this type can be safely cast to <code>IPackageFragment</code>.
+        */
+       public static final int PACKAGE_FRAGMENT = 4;
+
+       /**
+        * Constant representing a Java compilation unit.
+        * A Java element with this type can be safely cast to <code>ICompilationUnit</code>.
+        */
+       public static final int COMPILATION_UNIT = 5;
+
+       /**
+        * Constant representing a class file.
+        * A Java element with this type can be safely cast to <code>IClassFile</code>.
+        */
+       public static final int CLASS_FILE = 6;
+
+       /**
+        * Constant representing a type (a class or interface).
+        * A Java element with this type can be safely cast to <code>IType</code>.
+        */
+       public static final int TYPE = 7;
+
+       /**
+        * Constant representing a field.
+        * A Java element with this type can be safely cast to <code>IField</code>.
+        */
+       public static final int FIELD = 8;
+
+       /**
+        * Constant representing a method or constructor.
+        * A Java element with this type can be safely cast to <code>IMethod</code>.
+        */
+       public static final int METHOD = 9;
+
+       /**
+        * Constant representing a stand-alone instance or class initializer.
+        * A Java element with this type can be safely cast to <code>IInitializer</code>.
+        */
+       public static final int INITIALIZER = 10;
+
+       /**
+        * Constant representing a package declaration within a compilation unit.
+        * A Java element with this type can be safely cast to <code>IPackageDeclaration</code>.
+        */
+       public static final int PACKAGE_DECLARATION = 11;
+
+       /**
+        * Constant representing all import declarations within a compilation unit.
+        * A Java element with this type can be safely cast to <code>IImportContainer</code>.
+        */
+       public static final int IMPORT_CONTAINER = 12;
+
+       /**
+        * Constant representing an import declaration within a compilation unit.
+        * A Java element with this type can be safely cast to <code>IImportDeclaration</code>.
+        */
+       public static final int IMPORT_DECLARATION = 13;
+
+/**
+ * Returns whether this Java element exists in the model.
+ *
+ * @return <code>true</code> if this element exists in the Java model
+ */
+boolean exists();
+/**
+ * Returns the first ancestor of this Java element that has the given type.
+ * Returns <code>null</code> 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 <code>null</code> if there is no resource that corresponds to
+ * this element.
+ * <p>
+ * For example, the corresponding resource for an <code>ICompilationUnit</code>
+ * is its underlying <code>IFile</code>. The corresponding resource for
+ * an <code>IPackageFragment</code> that is not contained in an archive 
+ * is its underlying <code>IFolder</code>. An <code>IPackageFragment</code>
+ * contained in an archive has no corresponding resource. Similarly, there
+ * are no corresponding resources for <code>IMethods</code>,
+ * <code>IFields</code>, etc.
+ * <p>
+ *
+ * @return the corresponding resource, or <code>null</code> 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
+ *   <code>IJavaElement</code>
+ * @see IJavaElement
+ */
+public 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 
+ * <code>JavaCore.create(String)</code> 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 <code>null</code> if this element is not contained in any Java project
+ * (for instance, the <code>IJavaModel</code> is not contained in any Java 
+ * project).
+ * This is a handle-only method.
+ *
+ * @return the containing Java project, or <code>null</code> 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 <code>null</code> if this element doesn't have
+ * an openable parent.
+ * This is a handle-only method.
+ * 
+ * @return the first openable parent or <code>null</code> if this element doesn't have
+ * an openable parent.
+ * @since 2.0
+ */
+IOpenable getOpenable();
+/**
+ * Returns the element directly containing this element,
+ * or <code>null</code> if this element has no parent.
+ * This is a handle-only method.
+ *
+ * @return the parent element, or <code>null</code> 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, <code>null</code>
+ * is returned.
+ * If this element is a working copy, <code>null</code> is returned.
+ * This is a handle-only method.
+ * 
+ * @return the innermost resource enclosing this element, <code>null</code> 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 <code>null</code> if this element is not contained
+ * in a resource.
+ *
+ * @return the underlying resource, or <code>null</code> 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. 
+ * <p>
+ * 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.
+ * <p>
+ * This is a handle-only method.
+ *
+ * @return <code>true</code> 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, <code>false</code> is returned.
+ * If the structure of an element is unknown, navigations will return reasonable
+ * defaults. For example, <code>getChildren</code> will return an empty collection.
+ * <p>
+ * Note: This does not imply anything about consistency with the
+ * underlying resource/buffer contents.
+ * </p>
+ *
+ * @return <code>true</code> 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 (file)
index 0000000..a9858d4
--- /dev/null
@@ -0,0 +1,221 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.core;
+
+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
+ * <em>the</em> 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 <code>IJavaProject</code>s.
+ * <p>
+ * This interface provides methods for performing copy, move, rename, and
+ * delete operations on multiple Java elements.
+ * </p>
+ * <p>
+ * This interface is not intended to be implemented by clients. An instance
+ * of one of these handles can be created via
+ * <code>JavaCore.create(workspace.getRoot())</code>.
+ * </p>
+ *
+ * @see JavaCore#create(org.eclipse.core.resources.IWorkspaceRoot)
+ */
+public interface IJavaModel extends IJavaElement, IOpenable, IParent {
+/**
+ * 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.
+ * <p>
+ * Optionally, each copy can positioned before a sibling
+ * element. If <code>null</code> is specified for a given sibling, the copy
+ * is inserted as the last child of its associated container.
+ * </p>
+ * <p>
+ * Optionally, each copy can be renamed. If 
+ * <code>null</code> is specified for the new name, the copy
+ * is not renamed. 
+ * </p>
+ * <p>
+ * Optionally, any existing child in the destination container with
+ * the same name can be replaced by specifying <code>true</code> for
+ * force. Otherwise an exception is thrown in the event that a name
+ * collision occurs.
+ * </p>
+ *
+ * @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
+ *   <code>null</code>; or <code>null</code>
+ * @param renamings the list of new names any of which may be
+ *   <code>null</code>; or <code>null</code>
+ * @param replace <code>true</code> if any existing child in a target container
+ *   with the target name should be replaced, and <code>false</code> 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:
+ * <ul>
+ * <li> A specified element, container, or sibling does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+ * <li> A <code>CoreException</code> occurred while updating an underlying resource
+ * <li> A container is of an incompatible type (<code>INVALID_DESTINATION</code>)
+ * <li> A sibling is not a child of it associated container (<code>INVALID_SIBLING</code>)
+ * <li> A new name is invalid (<code>INVALID_NAME</code>)
+ * <li> A child in its associated container already exists with the same
+ *             name and <code>replace</code> has been specified as <code>false</code> (<code>NAME_COLLISION</code>)
+ * <li> A container or element is read-only (<code>READ_ONLY</code>) 
+ * </ul>
+ */
+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:
+ * <ul>
+ * <li> A specified element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+ * <li> A <code>CoreException</code> occurred while updating an underlying resource
+ * <li> An element is read-only (<code>READ_ONLY</code>) 
+ * </ul>
+ */
+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 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.
+ * <p>
+ * Optionally, each element can positioned before a sibling
+ * element. If <code>null</code> is specified for sibling, the element
+ * is inserted as the last child of its associated container.
+ * </p>
+ * <p>
+ * Optionally, each element can be renamed. If 
+ * <code>null</code> is specified for the new name, the element
+ * is not renamed. 
+ * </p>
+ * <p>
+ * Optionally, any existing child in the destination container with
+ * the same name can be replaced by specifying <code>true</code> for
+ * force. Otherwise an exception is thrown in the event that a name
+ * collision occurs.
+ * </p>
+ *
+ * @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
+ *   <code>null</code>; or <code>null</code>
+ * @param renamings the list of new names any of which may be
+ *   <code>null</code>; or <code>null</code>
+ * @param replace <code>true</code> if any existing child in a target container
+ *   with the target name should be replaced, and <code>false</code> 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:
+ * <ul>
+ * <li> A specified element, container, or sibling does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+ * <li> A <code>CoreException</code> occurred while updating an underlying resource
+ * <li> A container is of an incompatible type (<code>INVALID_DESTINATION</code>)
+ * <li> A sibling is not a child of it associated container (<code>INVALID_SIBLING</code>)
+ * <li> A new name is invalid (<code>INVALID_NAME</code>)
+ * <li> A child in its associated container already exists with the same
+ *             name and <code>replace</code> has been specified as <code>false</code> (<code>NAME_COLLISION</code>)
+ * <li> A container or element is read-only (<code>READ_ONLY</code>) 
+ * </ul>
+ *
+ * @exception IllegalArgumentException any element or container is <code>null</code>
+ */
+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 <code>null</code> along is equivalent to refreshing the entire mode). 
+ * The elements can be:
+ * <ul>
+ * <li> package fragment roots corresponding to external archives
+ * <li> Java projects, which referenced external archives will be refreshed
+ * <li> Java model, all referenced external archives will be refreshed.
+ * </ul>
+ * <p> 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.
+ * <p>
+ * @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:
+ * <ul>
+ *    <li> an exception occurs while accessing project resources </li>
+ * </ul>
+ * 
+ * @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 <code>true</code> if an existing child in a target container
+ *   with the target name should be replaced, and <code>false</code> 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:
+ * <ul>
+ * <li> A specified element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+ * <li> A <code>CoreException</code> occurred while updating an underlying resource
+ * <li> A new name is invalid (<code>INVALID_NAME</code>)
+ * <li> A child already exists with the same name and <code>replace</code> has been specified as <code>false</code> (<code>NAME_COLLISION</code>)
+ * <li> An element is read-only (<code>READ_ONLY</code>) 
+ * </ul>
+ */
+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 (file)
index 0000000..27a8452
--- /dev/null
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     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 <code>JavaModelException</code> objects to indicate what went
+ * wrong.
+ * <p>
+ * Java model status object are distinguished by their plug-in id:
+ * <code>getPlugin</code> returns <code>"net.sourceforge.phpdt.core"</code>.
+ * <code>getCode</code> returns one of the status codes declared in
+ * <code>IJavaModelStatusConstants</code>.
+ * </p>
+ * <p>
+ * A Java model status may also carry additional information (that is, in 
+ * addition to the information defined in <code>IStatus</code>):
+ * <ul>
+ *   <li>elements - optional handles to Java elements associated with the failure</li>
+ *   <li>string - optional string associated with the failure</li>
+ * </ul>
+ * <p>
+ * This interface is not intended to be implemented by clients.
+ * </p>
+ *
+ * @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
+ */
+IJavaElement[] getElements();
+/**
+ * Returns the path associated with the failure (see specification
+ * of the status code), or <code>null</code> if the failure is not 
+ * one of <code>DEVICE_PATH</code>, <code>INVALID_PATH</code>, 
+ * <code>PATH_OUTSIDE_PROJECT</code>, or <code>RELATIVE_PATH</code>.
+ *
+ * @return the path that caused the failure, or <code>null</code> 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 <code>null</code> if no string is related to this
+ * particular status code.
+ *
+ * @return the string culprit, or <code>null</code> if none
+ * @see IJavaModelStatusConstants
+ */
+String getString();
+/**
+ * Returns whether this status indicates that a Java model element does not exist.
+ * This convenience method is equivalent to
+ * <code>getCode() == IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST</code>.
+ *
+ * @return <code>true</code> 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 (file)
index 0000000..7eea239
--- /dev/null
@@ -0,0 +1,252 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.core;
+
+/**
+ * Status codes used with Java model status objects.
+ * <p>
+ * This interface declares constants only; it is not intended to be implemented
+ * or extended.
+ * </p>
+ *
+ * @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 <code>getException</code> to retrieve a <code>CoreException</code>.
+        */
+       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 <code>getElements</code> 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 <code>getElements</code> on the status object.
+        *
+        * @see IJavaModelStatus#isDoesNotExist
+        */
+       public static final int ELEMENT_DOES_NOT_EXIST = 969;
+
+       /**
+        * Status constant indicating that a <code>null</code> 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 
+        * <code>getPath</code> 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 <code>getPath</code> 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 <code>getPath</code> on the
+        * status object.
+        */
+       public static final int DEVICE_PATH = 973;
+    
+       /**
+        * Status constant indicating that a string
+        * was supplied to the operation that was <code>null</code>.
+        */
+       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 <code>getElements</code> 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 <code>getElements</code> 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 <code>getPath</code> 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 <code>null</code> 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 <code>getString</code>.
+        */
+       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 <code>java.io.IOException</code>
+        * occurred. 
+        */
+       public static final int IO_EXCEPTION = 985;
+
+       /**
+        * Status constant indicating that a <code>DOMException</code>
+        * occurred. 
+        */
+       public static final int DOM_EXCEPTION = 986;
+
+       /**
+        * Status constant indicating that a <code>TargetException</code>
+        * 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 <code>ICompilationUnit</code>
+        * does not correspond to the <code>IPackageFragment</code> it belongs to.
+        * The <code>getString</code> method of the associated status object
+        * gives the name of the package in which the <code>ICompilationUnit</code> 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;
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IJavaProject.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IJavaProject.java
new file mode 100644 (file)
index 0000000..c9e71e7
--- /dev/null
@@ -0,0 +1,503 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.core;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IPath;
+
+//import net.sourceforge.phpdt.core.eval.IEvaluationContext;
+
+/**
+ * A Java project represents a view of a project resource in terms of Java 
+ * elements such as package fragments, types, methods and fields.
+ * A project may contain several package roots, which contain package fragments. 
+ * A package root corresponds to an underlying folder or JAR.
+ * <p>
+ * Each Java project has a classpath, defining which folders contain source code and
+ * where required libraries are located. Each Java project also has an output location,
+ * defining where the builder writes <code>.class</code> files. A project that
+ * references packages in another project can access the packages by including
+ * the required project in a classpath entry. The Java model will present the
+ * source elements in the required project, and when building, the compiler will
+ * use the binaries from that project (that is, the output location of the 
+ * required project is used as a library). The classpath format is a sequence 
+ * of classpath entries describing the location and contents of package fragment
+ * roots.
+ * </p>
+ * Java project elements need to be opened before they can be navigated or manipulated.
+ * The children of a Java project are the package fragment roots that are 
+ * defined by the classpath and contained in this project (in other words, it
+ * does not include package fragment roots for other projects).
+ * </p>
+ * <p>
+ * This interface is not intended to be implemented by clients. An instance
+ * of one of these handles can be created via 
+ * <code>JavaCore.create(project)</code>.
+ * </p>
+ *
+ * @see JavaCore#create(org.eclipse.core.resources.IProject)
+ * @see IClasspathEntry
+ */
+public interface IJavaProject extends IParent, IJavaElement, IOpenable {
+
+  /**
+   * Returns the <code>IJavaElement</code> corresponding to the given
+   * classpath-relative path, or <code>null</code> if no such 
+   * <code>IJavaElement</code> is found. The result is one of an
+   * <code>ICompilationUnit</code>, <code>IClassFile</code>, or
+   * <code>IPackageFragment</code>. 
+   * <p>
+   * When looking for a package fragment, there might be several potential
+   * matches; only one of them is returned.
+   *
+   * <p>For example, the path "java/lang/Object.java", would result in the
+   * <code>ICompilationUnit</code> or <code>IClassFile</code> corresponding to
+   * "java.lang.Object". The path "java/lang" would result in the
+   * <code>IPackageFragment</code> for "java.lang".
+   * @param path the given classpath-relative path
+   * @exception JavaModelException if the given path is <code>null</code>
+   *  or absolute
+   * @return the <code>IJavaElement</code> corresponding to the given
+   * classpath-relative path, or <code>null</code> if no such 
+   * <code>IJavaElement</code> is found
+   */
+  IJavaElement findElement(IPath path) throws JavaModelException;
+
+  /**
+   * Returns the first existing package fragment on this project's classpath
+   * whose path matches the given (absolute) path, or <code>null</code> if none
+   * exist.
+   * The path can be:
+   *   - internal to the workbench: "/Project/src"
+   *  - external to the workbench: "c:/jdk/classes.zip/java/lang"
+   * @param path the given absolute path
+   * @exception JavaModelException if this element does not exist or if an
+   *           exception occurs while accessing its corresponding resource
+   * @return the first existing package fragment on this project's classpath
+   * whose path matches the given (absolute) path, or <code>null</code> if none
+   * exist
+   */
+  //IPackageFragment findPackageFragment(IPath path) throws JavaModelException;
+
+  /**
+   * Returns the existing package fragment root on this project's classpath
+   * whose path matches the given (absolute) path, or <code>null</code> if
+   * one does not exist.
+   * The path can be:
+   *   - internal to the workbench: "/Compiler/src"
+   *   - external to the workbench: "c:/jdk/classes.zip"
+   * @param path the given absolute path
+   * @exception JavaModelException if this element does not exist or if an
+   *           exception occurs while accessing its corresponding resource
+   * @return the existing package fragment root on this project's classpath
+   * whose path matches the given (absolute) path, or <code>null</code> if
+   * one does not exist
+   */
+  //   IPackageFragmentRoot findPackageFragmentRoot(IPath path)
+  //           throws JavaModelException;
+  /**
+   * Returns the first type found following this project's classpath 
+   * with the given fully qualified name or <code>null</code> if none is found.
+   * The fully qualified name is a dot-separated name. For example,
+   * a class B defined as a member type of a class A in package x.y should have a 
+   * the fully qualified name "x.y.A.B".
+   * 
+   * @param fullyQualifiedName the given fully qualified name
+   * @exception JavaModelException if this element does not exist or if an
+   *           exception occurs while accessing its corresponding resource
+   * @return the first type found following this project's classpath 
+   * with the given fully qualified name or <code>null</code> if none is found
+   * @see IType#getFullyQualifiedName(char)
+   * @since 2.0
+   */
+  IType findType(String fullyQualifiedName) throws JavaModelException;
+  /**
+   * Returns the first type found following this project's classpath 
+   * with the given package name and type qualified name
+   * or <code>null</code> if none is found.
+   * The package name is a dot-separated name.
+   * The type qualified name is also a dot-separated name. For example,
+   * a class B defined as a member type of a class A should have the 
+   * type qualified name "A.B".
+   * 
+   * @param packageName the given package name
+   * @param typeQualifiedName the given type qualified name
+   * @exception JavaModelException if this element does not exist or if an
+   *           exception occurs while accessing its corresponding resource
+   * @return the first type found following this project's classpath 
+   * with the given package name and type qualified name
+   * or <code>null</code> if none is found
+   * @see IType#getTypeQualifiedName(char)
+   * @since 2.0
+   */
+  IType findType(String packageName, String typeQualifiedName) throws JavaModelException;
+
+  /**
+   * Returns all of the existing package fragment roots that exist
+   * on the classpath, in the order they are defined by the classpath.
+   *
+   * @return all of the existing package fragment roots that exist
+   * on the classpath
+   * @exception JavaModelException if this element does not exist or if an
+   *           exception occurs while accessing its corresponding resource
+   */
+  // IPackageFragmentRoot[] getAllPackageFragmentRoots() throws JavaModelException;
+
+  /**
+   * Returns an array of non-Java resources directly contained in this project.
+   * It does not transitively answer non-Java resources contained in folders;
+   * these would have to be explicitly iterated over.
+   * @return an array of non-Java resources directly contained in this project
+   */
+  Object[] getNonJavaResources() throws JavaModelException;
+
+  /**
+   * Returns the full path to the location where the builder writes 
+   * <code>.class</code> files.
+   *
+   * @exception JavaModelException if this element does not exist or if an
+   *           exception occurs while accessing its corresponding resource
+   * @return the full path to the location where the builder writes 
+   * <code>.class</code> files
+   */
+  IPath getOutputLocation() throws JavaModelException;
+
+  /**
+   * Returns a package fragment root for the JAR at the specified file system path.
+   * This is a handle-only method.  The underlying <code>java.io.File</code>
+   * may or may not exist. No resource is associated with this local JAR
+   * package fragment root.
+   * 
+   * @param jarPath the jars's file system path
+   * @return a package fragment root for the JAR at the specified file system path
+   */
+  // IPackageFragmentRoot getPackageFragmentRoot(String jarPath);
+
+  /**
+   * Returns a package fragment root for the given resource, which
+   * must either be a folder representing the top of a package hierarchy,
+   * or a <code>.jar</code> or <code>.zip</code> file.
+   * This is a handle-only method.  The underlying resource may or may not exist. 
+   * 
+   * @param resource the given resource
+   * @return a package fragment root for the given resource, which
+   * must either be a folder representing the top of a package hierarchy,
+   * or a <code>.jar</code> or <code>.zip</code> file
+   */
+  // IPackageFragmentRoot getPackageFragmentRoot(IResource resource);
+
+  /**
+   * Returns all of the  package fragment roots contained in this
+   * project, identified on this project's resolved classpath. The result
+   * does not include package fragment roots in other projects referenced
+   * on this project's classpath.
+   *
+   * <p>NOTE: This is equivalent to <code>getChildren()</code>.
+   *
+   * @return all of the  package fragment roots contained in this
+   * project, identified on this project's resolved classpath
+   * @exception JavaModelException if this element does not exist or if an
+   *           exception occurs while accessing its corresponding resource
+   */
+  // IPackageFragmentRoot[] getPackageFragmentRoots() throws JavaModelException;
+
+  /**
+   * Returns the existing package fragment roots identified by the given entry.
+   * Note that a classpath entry that refers to another project may
+   * have more than one root (if that project has more than on root
+   * containing source), and classpath entries within the current
+   * project identify a single root.
+   * <p>
+   * If the classpath entry denotes a variable, it will be resolved and return
+   * the roots of the target entry (empty if not resolvable).
+   * <p>
+   * If the classpath entry denotes a container, it will be resolved and return
+   * the roots corresponding to the set of container entries (empty if not resolvable).
+   * 
+   * @param entry the given entry
+   * @return the existing package fragment roots identified by the given entry
+   * @see IClasspathContainer
+   */
+  // IPackageFragmentRoot[] getPackageFragmentRoots(IClasspathEntry entry);
+
+  /**
+   * Returns all package fragments in all package fragment roots contained
+   * in this project. This is a convenience method.
+   *
+   * Note that the package fragment roots corresponds to the resolved
+   * classpath of the project.
+   *
+   * @return all package fragments in all package fragment roots contained
+   * in this project
+   * @exception JavaModelException if this element does not exist or if an
+   *           exception occurs while accessing its corresponding resource
+   */
+  // IPackageFragment[] getPackageFragments() throws JavaModelException;
+
+  /**
+   * Returns the <code>IProject</code> on which this <code>IJavaProject</code>
+   * was created. This is handle-only method.
+   * 
+   * @return the <code>IProject</code> on which this <code>IJavaProject</code>
+   * was created
+   */
+  IProject getProject();
+
+  /**
+   * This is a helper method returning the resolved classpath for the project, as a list of classpath entries, 
+   * where all classpath variable entries have been resolved and substituted with their final target entries.
+   * <p>
+   * A resolved classpath corresponds to a particular instance of the raw classpath bound in the context of 
+   * the current values of the referred variables, and thus should not be persisted.
+   * <p>
+   * A classpath variable provides an indirection level for better sharing a classpath. As an example, it allows
+   * a classpath to no longer refer directly to external JARs located in some user specific location. The classpath
+   * can simply refer to some variables defining the proper locations of these external JARs.
+   * <p>
+   * The boolean argument <code>ignoreUnresolvedVariable</code> allows to specify how to handle unresolvable variables,
+   * when set to <code>true</code>, missing variables are simply ignored, the resulting path is then only formed of the
+   * resolvable entries, without any indication about which variable(s) was ignored. When set to <code>false</code>, a
+   * JavaModelException will be thrown for the first unresolved variable (from left to right).
+   * 
+   * @exception JavaModelException in one of the corresponding situation:
+   * <ul>
+   *    <li> this element does not exist </li>
+   *    <li> an exception occurs while accessing its corresponding resource </li>
+   *    <li> a classpath variable was not resolvable and <code>ignoreUnresolvedVariable</code> was set to <code>false</code>. </li>
+   * </ul>
+   * @return 
+   * @see IClasspathEntry 
+   */
+  //   IClasspathEntry[] getExpandedClasspath(boolean ignoreUnresolvedVariable)
+  //           throws JavaModelException;
+
+  /**
+   * Returns the raw classpath for the project, as a list of classpath entries. This corresponds to the exact set
+   * of entries which were assigned using <code>setRawClasspath</code>, in particular such a classpath may contain
+   * classpath variable entries. Classpath variable entries can be resolved individually (see <code>JavaCore#getClasspathVariable</code>),
+   * or the full classpath can be resolved at once using the helper method <code>getResolvedClasspath</code>.
+   * <p>
+   * A classpath variable provides an indirection level for better sharing a classpath. As an example, it allows
+   * a classpath to no longer refer directly to external JARs located in some user specific location. The classpath
+   * can simply refer to some variables defining the proper locations of these external JARs.
+   *  <p>
+   * Note that in case the project isn't yet opened, the classpath will directly be read from the associated <tt>.classpath</tt> file.
+   * <p>
+   * 
+   * @return the raw classpath for the project, as a list of classpath entries
+   * @exception JavaModelException if this element does not exist or if an
+   *           exception occurs while accessing its corresponding resource
+   * @see IClasspathEntry
+   */
+  // IClasspathEntry[] getRawClasspath() throws JavaModelException;
+
+  /**
+   * Returns the names of the projects that are directly required by this
+   * project. A project is required if it is in its classpath.
+   *
+   * @return the names of the projects that are directly required by this
+   * project
+   * @exception JavaModelException if this element does not exist or if an
+   *           exception occurs while accessing its corresponding resource
+   */
+  String[] getRequiredProjectNames() throws JavaModelException;
+
+  /**
+   * This is a helper method returning the resolved classpath for the project, as a list of classpath entries, 
+   * where all classpath variable entries have been resolved and substituted with their final target entries.
+   * <p>
+   * A resolved classpath corresponds to a particular instance of the raw classpath bound in the context of 
+   * the current values of the referred variables, and thus should not be persisted.
+   * <p>
+   * A classpath variable provides an indirection level for better sharing a classpath. As an example, it allows
+   * a classpath to no longer refer directly to external JARs located in some user specific location. The classpath
+   * can simply refer to some variables defining the proper locations of these external JARs.
+   * <p>
+   * The boolean argument <code>ignoreUnresolvedVariable</code> allows to specify how to handle unresolvable variables,
+   * when set to <code>true</code>, missing variables are simply ignored, the resulting path is then only formed of the
+   * resolvable entries, without any indication about which variable(s) was ignored. When set to <code>false</code>, a
+   * JavaModelException will be thrown for the first unresolved variable (from left to right).
+   * 
+   * @param ignoreUnresolvedVariable specify how to handle unresolvable variables
+   * @return the resolved classpath for the project, as a list of classpath entries, 
+   * where all classpath variable entries have been resolved and substituted with their final target entries
+   * @exception JavaModelException in one of the corresponding situation:
+   * <ul>
+   *    <li> this element does not exist </li>
+   *    <li> an exception occurs while accessing its corresponding resource </li>
+   *    <li> a classpath variable was not resolvable and <code>ignoreUnresolvedVariable</code> was set to <code>false</code>. </li>
+   * </ul>
+   * @see IClasspathEntry 
+   */
+  // IClasspathEntry[] getResolvedClasspath(boolean ignoreUnresolvedVariable) throws JavaModelException;
+
+  /**
+   * Returns whether this project has been built at least once and thus whether it has a build state.
+   * @return true if this project has been built at least once, false otherwise
+   */
+  boolean hasBuildState();
+
+  /**
+   * Returns whether setting this project's classpath to the given classpath entries
+   * would result in a cycle.
+   *
+   * If the set of entries contains some variables, those are resolved in order to determine
+   * cycles.
+   * 
+   * @param entries the given classpath entries
+   * @return true if the given classpath entries would result in a cycle, false otherwise
+   */
+  // boolean hasClasspathCycle(IClasspathEntry[] entries);
+  /**
+   * Returns whether the given element is on the classpath of this project.
+   * 
+   * @param element the given element
+   * @exception JavaModelException if this element does not exist or if an
+   *           exception occurs while accessing its corresponding resource
+   * @return true if the given element is on the classpath of this project, false otherwise
+   * @since 2.0
+   */
+  boolean isOnClasspath(IJavaElement element) throws JavaModelException;
+
+  /**
+   * Creates a new evaluation context.
+   * @return a new evaluation context.
+   */
+  // IEvaluationContext newEvaluationContext();
+
+  /**
+   * Creates and returns a type hierarchy for all types in the given
+   * region, considering subtypes within that region.
+   *
+   * @param monitor the given progress monitor
+   * @param region the given region
+   * @exception JavaModelException if this element does not exist or if an
+   *           exception occurs while accessing its corresponding resource
+   * @exception IllegalArgumentException if region is <code>null</code>
+   * @return a type hierarchy for all types in the given
+   * region, considering subtypes within that region
+   */
+  //   ITypeHierarchy newTypeHierarchy(IRegion region, IProgressMonitor monitor)
+  //           throws JavaModelException;
+
+  /**
+   * Creates and returns a type hierarchy for the given type considering
+   * subtypes in the specified region.
+   * 
+   * @param monitor the given monitor
+   * @param region the given region
+   * @param type the given type
+   * 
+   * @exception JavaModelException if this element does not exist or if an
+   *           exception occurs while accessing its corresponding resource
+   *
+   * @exception IllegalArgumentException if type or region is <code>null</code>
+   * @return a type hierarchy for the given type considering
+   * subtypes in the specified region
+   */
+  //   ITypeHierarchy newTypeHierarchy(
+  //           IType type,
+  //           IRegion region,
+  //           IProgressMonitor monitor)
+  //           throws JavaModelException;
+
+  /**
+   * Sets the output location of this project to the location
+   * described by the given absolute path.
+   * <p>
+   *
+   * @param path the given absolute path
+   * @param monitor the given progress monitor
+   * 
+   * @exception JavaModelException if the classpath could not be set. Reasons include:
+   * <ul>
+   *  <li>This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+   *   <li>The path refers to a location not contained in this project (<code>PATH_OUTSIDE_PROJECT</code>)
+   *   <li>The path is not an absolute path (<code>RELATIVE_PATH</code>)
+   *  <li>The path is nested inside a package fragment root of this project (<code>INVALID_PATH</code>)
+   *  <li> The output location is being modified during resource change event notification (CORE_EXCEPTION)     
+   * </ul>
+   */
+  void setOutputLocation(IPath path, IProgressMonitor monitor) throws JavaModelException;
+
+  /**
+   * Sets the classpath of this project using a list of classpath entries. In particular such a classpath may contain
+   * classpath variable entries. Classpath variable entries can be resolved individually (see <code>JavaCore#getClasspathVariable</code>),
+   * or the full classpath can be resolved at once using the helper method <code>getResolvedClasspath</code>.
+   * <p>
+   * A classpath variable provides an indirection level for better sharing a classpath. As an example, it allows
+   * a classpath to no longer refer directly to external JARs located in some user specific location. The classpath
+   * can simply refer to some variables defining the proper locations of these external JARs.
+   * <p>
+   * Setting the classpath to <code>null</code> specifies a default classpath
+   * (the project root). Setting the classpath to an empty array specifies an
+   * empty classpath.
+   * <p>
+   * If a cycle is detected while setting this classpath, an error marker will be added
+   * to the project closing the cycle.
+   * To avoid this problem, use <code>hasClasspathCycle(IClasspathEntry[] entries)</code>
+   * before setting the classpath.
+   *
+   * @param entries a list of classpath entries
+   * @param monitor the given progress monitor
+   * @exception JavaModelException if the classpath could not be set. Reasons include:
+   * <ul>
+   * <li> This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+   * <li> The classpath is being modified during resource change event notification (CORE_EXCEPTION)
+   * <li> The classpath failed the validation check as defined by <code>JavaConventions#validateClasspath</code>
+   * </ul>
+   * @see IClasspathEntry
+   */
+  //   void setRawClasspath(IClasspathEntry[] entries, IProgressMonitor monitor)
+  //           throws JavaModelException;
+
+  /**
+   * Sets the both the classpath of this project and its output location at once.
+   * The classpath is defined using a list of classpath entries. In particular such a classpath may contain
+   * classpath variable entries. Classpath variable entries can be resolved individually (see <code>JavaCore#getClasspathVariable</code>),
+   * or the full classpath can be resolved at once using the helper method <code>getResolvedClasspath</code>.
+   * <p>
+   * A classpath variable provides an indirection level for better sharing a classpath. As an example, it allows
+   * a classpath to no longer refer directly to external JARs located in some user specific location. The classpath
+   * can simply refer to some variables defining the proper locations of these external JARs.
+   * <p>
+   * Setting the classpath to <code>null</code> specifies a default classpath
+   * (the project root). Setting the classpath to an empty array specifies an
+   * empty classpath.
+   * <p>
+   * If a cycle is detected while setting this classpath, an error marker will be added
+   * to the project closing the cycle.
+   * To avoid this problem, use <code>hasClasspathCycle(IClasspathEntry[] entries)</code>
+   * before setting the classpath.
+   *
+   * @param entries a list of classpath entries
+   * @param monitor the given progress monitor
+   * @param outputLocation the given output location
+   * 
+   * @exception JavaModelException if the classpath could not be set. Reasons include:
+   * <ul>
+   * <li> This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+   * <li> Two or more entries specify source roots with the same or overlapping paths (NAME_COLLISION)
+   * <li> A entry of kind <code>CPE_PROJECT</code> refers to this project (INVALID_PATH)
+   *  <li>This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+   *   <li>The output location path refers to a location not contained in this project (<code>PATH_OUTSIDE_PROJECT</code>)
+   *   <li>The output location path is not an absolute path (<code>RELATIVE_PATH</code>)
+   *  <li>The output location path is nested inside a package fragment root of this project (<code>INVALID_PATH</code>)
+   * <li> The classpath is being modified during resource change event notification (CORE_EXCEPTION)
+   * </ul>
+   * @see IClasspathEntry
+   * @since 2.0
+   */
+  //   void setRawClasspath(IClasspathEntry[] entries, IPath outputLocation, IProgressMonitor monitor)
+  //           throws JavaModelException;
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IMember.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IMember.java
new file mode 100644 (file)
index 0000000..7e532ec
--- /dev/null
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.core;
+
+/**
+ * Common protocol for Java elements that can be members of types.
+ * This set consists of <code>IType</code>, <code>IMethod</code>, 
+ * <code>IField</code>, and <code>IInitializer</code>.
+ * <p>
+ * This interface is not intended to be implemented by clients.
+ * </p>
+ */
+public interface IMember extends IJavaElement, ISourceReference, ISourceManipulation {
+/**
+ * Returns the class file in which this member is declared, or <code>null</code>
+ * if this member is not declared in a class file (for example, a source type).
+ * This is a handle-only method.
+ * 
+ * @return the class file in which this member is declared, or <code>null</code>
+ * if this member is not declared in a class file (for example, a source type)
+ */
+// IClassFile getClassFile();
+/**
+ * Returns the compilation unit in which this member is declared, or <code>null</code>
+ * if this member is not declared in a compilation unit (for example, a binary type).
+ * This is a handle-only method.
+ * 
+ * @return the compilation unit in which this member is declared, or <code>null</code>
+ * if this member is not declared in a compilation unit (for example, a binary type)
+ */
+ICompilationUnit getCompilationUnit();
+/**
+ * Returns the type in which this member is declared, or <code>null</code>
+ * if this member is not declared in a type (for example, a top-level type).
+ * This is a handle-only method.
+ * 
+ * @return the type in which this member is declared, or <code>null</code>
+ * if this member is not declared in a type (for example, a top-level type)
+ */
+IType getDeclaringType();
+/**
+ * Returns the modifier flags for this member. The flags can be examined using class
+ * <code>Flags</code>.
+ *
+ * @exception JavaModelException if this element does not exist or if an
+ *      exception occurs while accessing its corresponding resource.
+ * @return the modifier flags for this member
+ * @see Flags
+ */
+int getFlags() throws JavaModelException;
+/**
+ * Returns the source range of this member's simple name,
+ * or <code>null</code> if this member does not have a name
+ * (for example, an initializer), or if this member does not have
+ * associated source code (for example, a binary type).
+ *
+ * @exception JavaModelException if this element does not exist or if an
+ *      exception occurs while accessing its corresponding resource.
+ * @return the source range of this member's simple name,
+ * or <code>null</code> if this member does not have a name
+ * (for example, an initializer), or if this member does not have
+ * associated source code (for example, a binary type)
+ */
+ISourceRange getNameRange() throws JavaModelException;
+/**
+ * Returns whether this member is from a class file.
+ * This is a handle-only method.
+ *
+ * @return <code>true</code> if from a class file, and <code>false</code> if
+ *   from a compilation unit
+ */
+boolean isBinary();
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IMethod.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IMethod.java
new file mode 100644 (file)
index 0000000..2dd7cc3
--- /dev/null
@@ -0,0 +1,145 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.core;
+
+/**
+ * Represents a method (or constructor) declared in a type.
+ * <p>
+ * This interface is not intended to be implemented by clients.
+ * </p>
+ */
+public interface IMethod extends IMember {
+/**
+ * Returns the simple name of this method.
+ * For a constructor, this returns the simple name of the declaring type.
+ * Note: This holds whether the constructor appears in a source or binary type
+ * (even though class files internally define constructor names to be <code>"&lt;init&gt;"</code>).
+ * For the class initialization methods in binary types, this returns
+ * the special name <code>"&lt;clinit&gt;"</code>.
+ * This is a handle-only method.
+ */
+String getElementName();
+/**
+ * Returns the type signatures of the exceptions this method throws,
+ * in the order declared in the source. Returns an empty array
+ * if this method throws no exceptions.
+ *
+ * <p>For example, a source method declaring <code>"throws IOException"</code>,
+ * would return the array <code>{"QIOException;"}</code>.
+ *
+ * @exception JavaModelException if this element does not exist or if an
+ *      exception occurs while accessing its corresponding resource.
+ * @return the type signatures of the exceptions this method throws,
+ * in the order declared in the source, an empty array if this method throws no exceptions
+ * @see Signature
+ */
+String[] getExceptionTypes() throws JavaModelException;
+/**
+ * Returns the number of parameters of this method.
+ * This is a handle-only method.
+ * 
+ * @return the number of parameters of this method
+ */
+int getNumberOfParameters();
+/**
+ * Returns the names of parameters in this method.
+ * For binary types, these names are invented as "arg"+i, where i starts at 1 
+ * (even if source is associated with the binary).
+ * Returns an empty array if this method has no parameters.
+ *
+ * <p>For example, a method declared as <code>public void foo(String text, int length)</code>
+ * would return the array <code>{"text","length"}</code>.
+ *
+ * @exception JavaModelException if this element does not exist or if an
+ *      exception occurs while accessing its corresponding resource.
+ * @return the names of parameters in this method, an empty array if this method has no parameters
+ */
+String[] getParameterNames() throws JavaModelException;
+/**
+ * Returns the type signatures for the parameters of this method.
+ * Returns an empty array if this method has no parameters.
+ * This is a handle-only method.
+ *
+ * <p>For example, a source method declared as <code>public void foo(String text, int length)</code>
+ * would return the array <code>{"QString;","I"}</code>.
+ * 
+ * @return the type signatures for the parameters of this method, an empty array if this method has no parameters
+ * @see Signature
+ */
+String[] getParameterTypes();
+/**
+ * Returns the type signature of the return value of this method.
+ * For constructors, this returns the signature for void.
+ *
+ * <p>For example, a source method declared as <code>public String getName()</code>
+ * would return <code>"QString;"</code>.
+ *
+ * @exception JavaModelException if this element does not exist or if an
+ *      exception occurs while accessing its corresponding resource.
+ * @return the type signature of the return value of this method, void  for constructors
+ * @see Signature
+ */
+String getReturnType() throws JavaModelException;
+/**
+ * Returns the signature of the method. This includes the signatures for the parameter
+ * types and return type, but does not include the method name or exception types.
+ *
+ * <p>For example, a source method declared as <code>public void foo(String text, int length)</code>
+ * would return <code>"(QString;I)V"</code>.
+ *
+ * @exception JavaModelException if this element does not exist or if an
+ *      exception occurs while accessing its corresponding resource.
+ *
+ * @see Signature
+ */
+String getSignature() throws JavaModelException;
+/**
+ * Returns whether this method is a constructor.
+ *
+ * @exception JavaModelException if this element does not exist or if an
+ *      exception occurs while accessing its corresponding resource.
+ * 
+ * @return true if this method is a constructor, false otherwise
+ */
+boolean isConstructor() throws JavaModelException;
+/**
+ * Returns whether this method is a main method.
+ * It is a main method if:
+ * <ul>
+ * <li>its name is equal to <code>"main"</code></li>
+ * <li>its return type is <code>void</code></li>
+ * <li>it is <code>static</code> and <code>public</code></li>
+ * <li>it defines one parameter whose type's simple name is </code>String[]</code></li>
+ * </ul>
+ * 
+ * @exception JavaModelException if this element does not exist or if an
+ *      exception occurs while accessing its corresponding resource.
+ * @since 2.0
+ * @return true if this method is a main method, false otherwise
+ */
+boolean isMainMethod() throws JavaModelException;
+/**
+ * Returns whether this method is similar to the given method.
+ * Two methods are similar if:
+ * <ul>
+ * <li>their element names are equal</li>
+ * <li>they have the same number of parameters</li>
+ * <li>the simple names of their parameter types are equal</li>
+ * </ul>
+ * This is a handle-only method.
+ * 
+ * @param method the given method
+ * @return true if this method is similar to the given method.
+ * @see Signature#getSimpleName
+ * @since 2.0
+ */
+boolean isSimilar(IMethod method);
+}
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 (file)
index 0000000..e0e17e3
--- /dev/null
@@ -0,0 +1,168 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     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 <code>isConsistent</code> and <code>makeConsistent(IProgressMonitor)</code>.
+ * <p>
+ * 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.
+ * </p>
+ * <p>
+ * 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 <code>IOpenable</code>.
+ * 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.
+ * </p>
+ * <p>
+ * This interface is not intended to be implemented by clients.
+ * </p>
+ */
+public interface IOpenable {
+
+/**
+ * Closes this element and its buffer (if any).
+ * Closing an element which is not open has no effect.
+ *
+ * <p>Note: although <code>close</code> 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 <code>null</code>
+ * 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 <code>null</code>
+ * if this element does not have a buffer
+ */
+public IBuffer getBuffer() throws JavaModelException;
+/**
+ * Returns <code>true</code> if this element is open and:
+ * <ul>
+ * <li>its buffer has unsaved changes, or
+ * <li>one of its descendants has unsaved changes, or
+ * <li>a working copy has been created on one of this
+ * element's children and has not yet destroyed
+ * </ul>
+ *
+ * @exception JavaModelException if this element does not exist or if an
+ *             exception occurs while accessing its corresponding resource.
+ * @return <code>true</code> if this element is open and:
+ * <ul>
+ * <li>its buffer has unsaved changes, or
+ * <li>one of its descendants has unsaved changes, or
+ * <li>a working copy has been created on one of this
+ * element's children and has not yet destroyed
+ * </ul>
+ */
+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.
+ *
+ * <p>NOTE: Child consistency is not considered. For example, a package fragment
+ * responds <code>true</code> 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:
+ * <ul>
+ *  <li>This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+ * </ul>
+ * @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.
+ *
+ * <p>Note: although <code>open</code> 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:
+ * <ul>
+ *  <li>This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+ * </ul>
+ */
+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.
+ * <p>
+ * The <code>force</code> parameter controls how this method deals with
+ * cases where the workbench is not completely in sync with the local file system.
+ * If <code>false</code> is specified, this method will only attempt
+ * to overwrite a corresponding file in the local file system provided
+ * it is in sync with the workbench. This option ensures there is no 
+ * unintended data loss; it is the recommended setting.
+ * However, if <code>true</code> is specified, an attempt will be made
+ * to write a corresponding file in the local file system, 
+ * overwriting any existing one if need be.
+ * In either case, if this method succeeds, the resource will be marked 
+ * as being local (even if it wasn't before).
+ * <p>
+ * 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:
+ * <ul>
+ *  <li>This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+ *  <li>This Java element is read-only (READ_ONLY)</li>
+ * </ul>
+ */
+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 (file)
index 0000000..cb37b5d
--- /dev/null
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.core;
+
+/**
+ * Common protocol for Java elements that contain other Java elements.
+ * <p>
+ * This interface is not intended to be implemented by clients.
+ * </p>
+ */
+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 <code>getChildren</code> 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/IProblemRequestor.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IProblemRequestor.java
new file mode 100644 (file)
index 0000000..5f3fff2
--- /dev/null
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.core;
+
+import net.sourceforge.phpdt.core.compiler.IProblem;
+
+/**
+ * A callback interface for receiving java problem as they are discovered
+ * by some Java operation.
+ * 
+ * @see IProblem
+ * @since 2.0
+ */
+public interface IProblemRequestor {
+       
+       /**
+        * Notification of a Java problem.
+        * 
+        * @param problem IProblem - The discovered Java problem.
+        */     
+       void acceptProblem(IProblem problem);
+
+       /**
+        * Notification sent before starting the problem detection process.
+        * Typically, this would tell a problem collector to clear previously recorded problems.
+        */
+       void beginReporting();
+
+       /**
+        * Notification sent after having completed problem detection process.
+        * Typically, this would tell a problem collector that no more problems should be expected in this
+        * iteration.
+        */
+       void endReporting();
+
+       /**
+        * Predicate allowing the problem requestor to signal whether or not it is currently
+        * interested by problem reports. When answering <code>false</false>, problem will
+        * not be discovered any more until the next iteration.
+        * 
+        * This  predicate will be invoked once prior to each problem detection iteration.
+        * 
+        * @return boolean - indicates whether the requestor is currently interested by problems.
+        */
+       boolean isActive();
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/ISourceManipulation.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/ISourceManipulation.java
new file mode 100644 (file)
index 0000000..e829cfe
--- /dev/null
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.core;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+
+/**
+ * Common protocol for Java elements that support source code manipulations such
+ * as copy, move, rename, and delete.
+ * <p>
+ * This interface is not intended to be implemented by clients.
+ * </p>
+ */
+public interface ISourceManipulation {
+/**
+ * Copies this element to the given container.
+ *
+ * @param container the container
+ * @param sibling the sibling element before which the copy should be inserted,
+ *   or <code>null</code> if the copy should be inserted as the last child of
+ *   the container
+ * @param rename the new name for the element, or <code>null</code> if the copy
+ *   retains the name of this element
+ * @param replace <code>true</code> if any existing child in the container with
+ *   the target name should be replaced, and <code>false</code> to throw an
+ *   exception in the event of a name collision
+ * @param monitor a progress monitor
+ * @exception JavaModelException if this element could not be copied. Reasons include:
+ * <ul>
+ * <li> This Java element, container element, or sibling does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+ * <li> A <code>CoreException</code> occurred while updating an underlying resource
+ * <li> The container is of an incompatible type (INVALID_DESTINATION)
+ * <li> The sibling is not a child of the given container (INVALID_SIBLING)
+ * <li> The new name is invalid (INVALID_NAME)
+ * <li> A child in the container already exists with the same name (NAME_COLLISION)
+ *             and <code>replace</code> has been specified as <code>false</code>
+ * <li> The container or this element is read-only (READ_ONLY) 
+ * </ul>
+ *
+ * @exception IllegalArgumentException if container is <code>null</code>
+ */
+void copy(IJavaElement container, IJavaElement sibling, String rename, boolean replace, IProgressMonitor monitor) throws JavaModelException;
+/**
+ * Deletes this element, forcing if specified and necessary.
+ *
+ * @param force a flag controlling whether underlying resources that are not
+ *    in sync with the local file system will be tolerated (same as the force flag
+ *       in IResource operations).
+ * @param monitor a progress monitor
+ * @exception JavaModelException if this element could not be deleted. Reasons include:
+ * <ul>
+ * <li> This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+ * <li> A <code>CoreException</code> occurred while updating an underlying resource (CORE_EXCEPTION)</li>
+ * <li> This element is read-only (READ_ONLY)</li>
+ * </ul>
+ */
+void delete(boolean force, IProgressMonitor monitor) throws JavaModelException;
+/**
+ * Moves this element to the given container.
+ *
+ * @param container the container
+ * @param sibling the sibling element before which the element should be inserted,
+ *   or <code>null</code> if the element should be inserted as the last child of
+ *   the container
+ * @param rename the new name for the element, or <code>null</code> if the
+ *   element retains its name
+ * @param replace <code>true</code> if any existing child in the container with
+ *   the target name should be replaced, and <code>false</code> to throw an
+ *   exception in the event of a name collision
+ * @param monitor a progress monitor
+ * @exception JavaModelException if this element could not be moved. Reasons include:
+ * <ul>
+ * <li> This Java element, container element, or sibling does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+ * <li> A <code>CoreException</code> occurred while updating an underlying resource
+ * <li> The container is of an incompatible type (INVALID_DESTINATION)
+ * <li> The sibling is not a child of the given container (INVALID_SIBLING)
+ * <li> The new name is invalid (INVALID_NAME)
+ * <li> A child in the container already exists with the same name (NAME_COLLISION)
+ *             and <code>replace</code> has been specified as <code>false</code>
+ * <li> The container or this element is read-only (READ_ONLY) 
+ * </ul>
+ *
+ * @exception IllegalArgumentException if container is <code>null</code>
+ */
+void move(IJavaElement container, IJavaElement sibling, String rename, boolean replace, IProgressMonitor monitor) throws JavaModelException;
+/**
+ * Renames this element to the given name.
+ *
+ * @param name the new name for the element
+ * @param replace <code>true</code> if any existing element with the target name
+ *   should be replaced, and <code>false</code> to throw an exception in the
+ *   event of a name collision
+ * @param monitor a progress monitor
+ * @exception JavaModelException if this element could not be renamed. Reasons include:
+ * <ul>
+ * <li> This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+ * <li> A <code>CoreException</code> occurred while updating an underlying resource
+ * <li> The new name is invalid (INVALID_NAME)
+ * <li> A child in the container already exists with the same name (NAME_COLLISION)
+ *             and <code>replace</code> has been specified as <code>false</code>
+ * <li> This element is read-only (READ_ONLY) 
+ * </ul>
+ */
+void rename(String name, boolean replace, IProgressMonitor monitor) throws JavaModelException;
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/ISourceRange.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/ISourceRange.java
new file mode 100644 (file)
index 0000000..02d4da8
--- /dev/null
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.core;
+
+/**
+ * A source range defines an element's source coordinates relative to
+ * its source buffer.
+ * <p>
+ * This interface is not intended to be implemented by clients.
+ * </p>
+ */
+public interface ISourceRange {
+
+/**
+ * Returns the number of characters of the source code for this element,
+ * relative to the source buffer in which this element is contained.
+ * 
+ * @return the number of characters of the source code for this element,
+ * relative to the source buffer in which this element is contained
+ */
+int getLength();
+/**
+ * Returns the 0-based index of the first character of the source code for this element,
+ * relative to the source buffer in which this element is contained.
+ * 
+ * @return the 0-based index of the first character of the source code for this element,
+ * relative to the source buffer in which this element is contained
+ */
+int getOffset();
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/ISourceReference.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/ISourceReference.java
new file mode 100644 (file)
index 0000000..09ef815
--- /dev/null
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.core;
+
+/**
+ * Common protocol for Java elements that have associated source code.
+ * This set consists of <code>IClassFile</code>, <code>ICompilationUnit</code>,
+ * <code>IPackageDeclaration</code>, <code>IImportDeclaration</code>,
+ * <code>IImportContainer</code>, <code>IType</code>, <code>IField</code>,
+ * <code>IMethod</code>, and <code>IInitializer</code>.
+ * </ul>
+ * <p>
+ * Note: For <code>IClassFile</code>, <code>IType</code> and other members
+ * derived from a binary type, the implementation returns source iff the
+ * element has attached source code.
+ * </p>
+ * <p>
+ * Source reference elements may be working copies if they were created from
+ * a compilation unit that is a working copy.
+ * </p>
+ * <p>
+ * This interface is not intended to be implemented by clients.
+ * </p>
+ *
+ * @see IPackageFragmentRoot#attachSource
+ */
+public interface ISourceReference {
+/**
+ * Returns whether this element exists in the model.
+ *
+ * @return <code>true</code> if this element exists in the Java model
+ * @since 2.0
+ */
+boolean exists();
+       
+/**
+ * Returns the source code associated with this element.
+ * This extracts the substring from the source buffer containing this source
+ * element. This corresponds to the source range that would be returned by
+ * <code>getSourceRange</code>.
+ * <p>
+ * For class files, this returns the source of the entire compilation unit 
+ * associated with the class file (if there is one).
+ * </p>
+ *
+ * @return the source code, or <code>null</code> if this element has no 
+ *   associated source code
+ * @exception JavaModelException if this element does not exist or if an
+ *      exception occurs while accessing its corresponding resource
+ */
+String getSource() throws JavaModelException;
+/**
+ * Returns the source range associated with this element.
+ * <p>
+ * For class files, this returns the range of the entire compilation unit 
+ * associated with the class file (if there is one).
+ * </p>
+ *
+ * @return the source range, or <code>null</code> if this element has no 
+ *   associated source code
+ * @exception JavaModelException if this element does not exist or if an
+ *      exception occurs while accessing its corresponding resource
+ */
+ISourceRange getSourceRange() throws JavaModelException;
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IType.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IType.java
new file mode 100644 (file)
index 0000000..1a69299
--- /dev/null
@@ -0,0 +1,569 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.core;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+
+/**
+ * Represents either a source type in a compilation unit (either a top-level
+ * type or a member type) or a binary type in a class file.
+ * <p>
+ * If a binary type cannot be parsed, its structure remains unknown.
+ * Use <code>IJavaElement.isStructureKnown</code> to determine whether this
+ * is the case.
+ * </p>
+ * <p>
+ * The children are of type <code>IMember</code>, which includes <code>IField</code>,
+ * <code>IMethod</code>, <code>IInitializer</code> and <code>IType</code>.
+ * The children are listed in the order in which they appear in the source or class file.
+ * </p>
+ * <p>
+ * This interface is not intended to be implemented by clients.
+ * </p>
+ */
+public interface IType extends IMember, IParent {
+       /**
+        * Do code completion inside a code snippet in the context of the current type.
+        * 
+        * If the type can access to his source code and the insertion position is valid,
+        * then completion is performed against source. Otherwise the completion is performed
+        * against type structure and given locals variables.
+        * 
+        * @param snippet the code snippet
+        * @param insertion the position with in source where the snippet
+        * is inserted. This position must not be in comments.
+        * A possible value is -1, if the position is not known.
+        * @param position the position with in snippet where the user 
+        * is performing code assist.
+        * @param localVariableTypesNames an array (possibly empty) of fully qualified 
+        * type names of local variables visible at the current scope
+        * @param localVariableNames an array (possibly empty) of local variable names 
+        * that are visible at the current scope
+        * @param localVariableModifiers an array (possible empty) of modifiers for 
+        * local variables
+        * @param isStatic whether the current scope is in a static context
+        * @param requestor the completion requestor
+        * @since 2.0
+        */
+       void codeComplete(
+               char[] snippet,
+               int insertion,
+               int position,
+               char[][] localVariableTypeNames,
+               char[][] localVariableNames,
+               int[] localVariableModifiers,
+               boolean isStatic,
+               ICompletionRequestor requestor)
+               throws JavaModelException;
+
+       /**
+        * Creates and returns a field in this type with the
+        * given contents.
+        * <p>
+        * Optionally, the new element can be positioned before the specified
+        * sibling. If no sibling is specified, the element will be inserted
+        * as the last field declaration in this type.</p>
+        *
+        * <p>It is possible that a field with the same name already exists in this type.
+        * The value of the <code>force</code> parameter effects the resolution of
+        * such a conflict:<ul>
+        * <li> <code>true</code> - in this case the field is created with the new contents</li>
+        * <li> <code>false</code> - in this case a <code>JavaModelException</code> is thrown</li>
+        * </ul></p>
+        *
+        * @param contents the given contents
+        * @param sibling the given sibling
+        * @param force a flag in case the same name already exists in this type
+        * @param monitor the given progress monitor
+        * @exception JavaModelException if the element could not be created. Reasons include:
+        * <ul>
+        * <li> This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+        * <li> A <code>CoreException</code> occurred while updating an underlying resource
+        * <li> The specified sibling is not a child of this type (INVALID_SIBLING)
+        * <li> The contents could not be recognized as a field declaration (INVALID_CONTENTS)
+        * <li> This type is read-only (binary) (READ_ONLY)
+        * <li> There was a naming collision with an existing field (NAME_COLLISION)
+        * </ul>
+        * @return a field in this type with the given contents
+        */
+       IField createField(String contents, IJavaElement sibling, boolean force, IProgressMonitor monitor)
+               throws JavaModelException;
+               
+       /**
+        * Creates and returns a static initializer in this type with the
+        * given contents.
+        * <p>
+        * Optionally, the new element can be positioned before the specified
+        * sibling. If no sibling is specified, the new initializer is positioned
+        * after the last existing initializer declaration, or as the first member
+        * in the type if there are no initializers.</p>
+        *
+        * @param contents the given contents
+        * @param sibling the given sibling
+        * @param monitor the given progress monitor
+        * @exception JavaModelException if the element could not be created. Reasons include:
+        * <ul>
+        * <li> This element does not exist
+        * <li> A <code>CoreException</code> occurred while updating an underlying resource
+        * <li> The specified sibling is not a child of this type (INVALID_SIBLING)
+        * <li> The contents could not be recognized as an initializer declaration (INVALID_CONTENTS)
+        * <li> This type is read-only (binary) (READ_ONLY)
+        * </ul>
+        * @return a static initializer in this type with the given contents
+        */
+       IInitializer createInitializer(String contents, IJavaElement sibling, IProgressMonitor monitor)
+               throws JavaModelException;
+               
+       /**
+        * Creates and returns a method or constructor in this type with the
+        * given contents.
+        * <p>
+        * Optionally, the new element can be positioned before the specified
+        * sibling. If no sibling is specified, the element will be appended
+        * to this type.
+        *
+        * <p>It is possible that a method with the same signature already exists in this type.
+        * The value of the <code>force</code> parameter effects the resolution of
+        * such a conflict:<ul>
+        * <li> <code>true</code> - in this case the method is created with the new contents</li>
+        * <li> <code>false</code> - in this case a <code>JavaModelException</code> is thrown</li>
+        * </ul></p>
+        *
+        * @param contents the given contents
+        * @param sibling the given sibling
+        * @param force a flag in case the same name already exists in this type
+        * @param monitor the given progress monitor
+        * @exception JavaModelException if the element could not be created. Reasons include:
+        * <ul>
+        * <li> This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+        * <li> A <code>CoreException</code> occurred while updating an underlying resource
+        * <li> The specified sibling is not a child of this type (INVALID_SIBLING)
+        * <li> The contents could not be recognized as a method or constructor
+        *              declaration (INVALID_CONTENTS)
+        * <li> This type is read-only (binary) (READ_ONLY)
+        * <li> There was a naming collision with an existing method (NAME_COLLISION)
+        * </ul>
+        * @return a method or constructor in this type with the given contents
+        */
+       IMethod createMethod(String contents, IJavaElement sibling, boolean force, IProgressMonitor monitor)
+               throws JavaModelException;
+               
+       /**
+        * Creates and returns a type in this type with the
+        * given contents.
+        * <p>
+        * Optionally, the new type can be positioned before the specified
+        * sibling. If no sibling is specified, the type will be appended
+        * to this type.
+        *
+        * <p>It is possible that a type with the same name already exists in this type.
+        * The value of the <code>force</code> parameter effects the resolution of
+        * such a conflict:<ul>
+        * <li> <code>true</code> - in this case the type is created with the new contents</li>
+        * <li> <code>false</code> - in this case a <code>JavaModelException</code> is thrown</li>
+        * </ul></p>
+        *
+        * @param contents the given contents
+        * @param sibling the given sibling
+        * @param force a flag in case the same name already exists in this type
+        * @param monitor the given progress monitor
+        * @exception JavaModelException if the element could not be created. Reasons include:
+        * <ul>
+        * <li> This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+        * <li> A <code>CoreException</code> occurred while updating an underlying resource
+        * <li> The specified sibling is not a child of this type (INVALID_SIBLING)
+        * <li> The contents could not be recognized as a type declaration (INVALID_CONTENTS)
+        * <li> This type is read-only (binary) (READ_ONLY)
+        * <li> There was a naming collision with an existing field (NAME_COLLISION)
+        * </ul>
+        * @return a type in this type with the given contents
+        */
+       IType createType(String contents, IJavaElement sibling, boolean force, IProgressMonitor monitor)
+               throws JavaModelException;
+               
+       /** 
+        * Finds the methods in this type that correspond to
+        * the given method.
+        * A method m1 corresponds to another method m2 if:
+        * <ul>
+        * <li>m1 has the same element name as m2.
+        * <li>m1 has the same number of arguments as m2 and
+        *     the simple names of the argument types must be equals.
+        * <li>m1 exists.
+        * </ul>
+        * @param method the given method
+        * @return the found method or <code>null</code> if no such methods can be found.
+        * 
+        * @since 2.0 
+        */
+       IMethod[] findMethods(IMethod method);
+       
+       /**
+        * Returns the simple name of this type, unqualified by package or enclosing type.
+        * This is a handle-only method.
+        * 
+        * @return the simple name of this type
+        */
+       String getElementName();
+       
+       /**
+        * Returns the field with the specified name
+        * in this type (for example, <code>"bar"</code>).
+        * This is a handle-only method.  The field may or may not exist.
+        * 
+        * @param name the given name
+        * @return the field with the specified name in this type
+        */
+       IField getField(String name);
+       
+       /**
+        * Returns the fields declared by this type.
+        * If this is a source type, the results are listed in the order
+        * in which they appear in the source, otherwise, the results are
+        * in no particular order.  For binary types, this includes synthetic fields.
+        *
+        * @exception JavaModelException if this element does not exist or if an
+        *              exception occurs while accessing its corresponding resource.
+        * @return the fields declared by this type
+        */
+       IField[] getFields() throws JavaModelException;
+       
+       /**
+        * Returns the fully qualified name of this type, 
+        * including qualification for any containing types and packages.
+        * This is the name of the package, followed by <code>'.'</code>,
+        * followed by the type-qualified name.
+        * This is a handle-only method.
+        *
+        * @see IType#getTypeQualifiedName()
+        * @return the fully qualified name of this type
+        */
+       String getFullyQualifiedName();
+       
+       /**
+        * Returns the fully qualified name of this type, 
+        * including qualification for any containing types and packages.
+        * This is the name of the package, followed by <code>'.'</code>,
+        * followed by the type-qualified name using the <code>enclosingTypeSeparator</code>.
+        * 
+        * For example:
+        * <ul>
+        * <li>the fully qualified name of a class B defined as a member of a class A in a compilation unit A.java 
+        *     in a package x.y using the '.' separator is "x.y.A.B"</li>
+        * <li>the fully qualified name of a class B defined as a member of a class A in a compilation unit A.java 
+        *     in a package x.y using the '$' separator is "x.y.A$B"</li>
+        * <li>the fully qualified name of a binary type whose class file is x/y/A$B.class
+        *     using the '.' separator is "x.y.A.B"</li>
+        * <li>the fully qualified name of a binary type whose class file is x/y/A$B.class
+        *     using the '$' separator is "x.y.A$B"</li>
+        * <li>the fully qualified name of an anonymous binary type whose class file is x/y/A$1.class
+        *     using the '.' separator is "x.y.A$1"</li>
+        * </ul>
+        * 
+        * This is a handle-only method.
+        *
+        * @param enclosingTypeSeparator the given enclosing type separator
+        * @return the fully qualified name of this type, including qualification for any containing types and packages
+        * @see IType#getTypeQualifiedName(char)
+        * @since 2.0
+        */
+       String getFullyQualifiedName(char enclosingTypeSeparator);
+       
+       /**
+        * Returns the initializer with the specified position relative to
+        * the order they are defined in the source.
+        * Numbering starts at 1 (i.e. the first occurrence is occurrence 1, not occurrence 0).
+        * This is a handle-only method.  The initializer may or may not be present.
+        * 
+        * @param occurrenceCount the specified position
+        * @return the initializer with the specified position relative to the order they are defined in the source
+        */
+       IInitializer getInitializer(int occurrenceCount);
+       
+       /**
+        * Returns the initializers declared by this type.
+        * For binary types this is an empty collection.
+        * If this is a source type, the results are listed in the order
+        * in which they appear in the source.
+        *
+        * @exception JavaModelException if this element does not exist or if an
+        *              exception occurs while accessing its corresponding resource.
+        * @return the initializers declared by this type
+        */
+       IInitializer[] getInitializers() throws JavaModelException;
+       
+       /**
+        * Returns the method with the specified name and parameter types
+        * in this type (for example, <code>"foo", {"I", "QString;"}</code>). To get the
+        * handle for a constructor, the name specified must be the simple
+        * name of the enclosing type.
+        * This is a handle-only method.  The method may or may not be present.
+        * 
+        * @param name the given name
+        * @param parameterTypeSignatures the given parameter types
+        * @return the method with the specified name and parameter types in this type
+        */
+       IMethod getMethod(String name, String[] parameterTypeSignatures);
+       
+       /**
+        * Returns the methods and constructors declared by this type.
+        * For binary types, this may include the special <code>&lt;clinit&gt</code>; method 
+        * and synthetic methods.
+        * If this is a source type, the results are listed in the order
+        * in which they appear in the source, otherwise, the results 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 methods and constructors declared by this type
+        */
+       IMethod[] getMethods() throws JavaModelException;
+       
+       /**
+        * Returns the package fragment in which this element is defined.
+        * This is a handle-only method.
+        * 
+        * @return the package fragment in which this element is defined
+        */
+       //IPackageFragment getPackageFragment();
+       
+       /**
+        * Returns the name of this type's superclass, or <code>null</code>
+        * for source types that do not specify a superclass.
+        * For interfaces, the superclass name is always <code>"java.lang.Object"</code>.
+        * For source types, the name as declared is returned, for binary types,
+        * the resolved, qualified name is returned.
+        *
+        * @exception JavaModelException if this element does not exist or if an
+        *              exception occurs while accessing its corresponding resource.
+        * @return the name of this type's superclass, or <code>null</code> for source types that do not specify a superclass
+        */
+       String getSuperclassName() throws JavaModelException;
+       
+       /**
+        * Returns the names of interfaces that this type implements or extends,
+        * in the order in which they are listed in the source.
+        * For classes, this gives the interfaces that this class implements.
+        * For interfaces, this gives the interfaces that this interface extends.
+        * An empty collection is returned if this type does not implement or
+        * extend any interfaces. For source types, simples name are returned,
+        * for binary types, qualified names are returned.
+        *
+        * @exception JavaModelException if this element does not exist or if an
+        *              exception occurs while accessing its corresponding resource.
+        * @return  the names of interfaces that this type implements or extends, in the order in which they are listed in the source, 
+        * an empty collection if none
+        */
+       String[] getSuperInterfaceNames() throws JavaModelException;
+       
+       /**
+        * Returns the member type declared in this type with the given simple name.
+        * This is a handle-only method. The type may or may not exist.
+        * 
+        * @param the given simple name
+        * @return the member type declared in this type with the given simple name
+        */
+       IType getType(String name);
+       
+       /**
+        * Returns the type-qualified name of this type, 
+        * including qualification for any enclosing types,
+        * but not including package qualification.
+        * For source types, this consists of the simple names of
+        * any enclosing types, separated by <code>"$"</code>, followed by the simple name of this type.
+        * For binary types, this is the name of the class file without the ".class" suffix.
+        * This is a handle-only method.
+        * 
+        * @return the type-qualified name of this type
+        */
+       String getTypeQualifiedName();
+       
+       /**
+        * Returns the type-qualified name of this type, 
+        * including qualification for any enclosing types,
+        * but not including package qualification.
+        * This consists of the simple names of any enclosing types, 
+        * separated by the <code>enclosingTypeSeparator</code>, 
+        * followed by the simple name of this type.
+        * 
+        * For example:
+        * <ul>
+        * <li>the type qualified name of a class B defined as a member of a class A
+        *     using the '.' separator is "A.B"</li>
+        * <li>the type qualified name of a class B defined as a member of a class A
+        *     using the '$' separator is "A$B"</li>
+        * <li>the type qualified name of a binary type whose class file is A$B.class
+        *     using the '.' separator is "A.B"</li>
+        * <li>the type qualified name of a binary type whose class file is A$B.class
+        *     using the '$' separator is "A$B"</li>
+        * <li>the type qualified name of an anonymous binary type whose class file is A$1.class
+        *     using the '.' separator is "A$1"</li>
+        * </ul>
+        *
+        * This is a handle-only method.
+        * 
+        * @param enclosingTypeSeparator the specified enclosing type separator
+        * @return the type-qualified name of this type
+        * @since 2.0
+        */
+       String getTypeQualifiedName(char enclosingTypeSeparator);
+       
+       /**
+        * Returns the immediate member types declared by this type.
+        * The results are listed in the order in which they appear in the source or class file.
+        *
+        * @exception JavaModelException if this element does not exist or if an
+        *              exception occurs while accessing its corresponding resource.
+        * @return the immediate member types declared by this type
+        */
+       IType[] getTypes() throws JavaModelException;
+       
+       /**
+        * Returns whether this type represents an anonymous type.
+        *
+        * @exception JavaModelException if this element does not exist or if an
+        *              exception occurs while accessing its corresponding resource.
+        * @return true if this type represents an anonymous type, false otherwise
+        * @since 2.0
+        */
+       boolean isAnonymous() throws JavaModelException;
+
+       /**
+        * Returns whether this type represents a class.
+        *
+        * @exception JavaModelException if this element does not exist or if an
+        *              exception occurs while accessing its corresponding resource.
+        * @return true if this type represents a class, false otherwise
+        */
+       boolean isClass() throws JavaModelException;
+       
+       /**
+        * Returns whether this type represents an interface.
+        *
+        * @exception JavaModelException if this element does not exist or if an
+        *              exception occurs while accessing its corresponding resource.
+        * @return true if this type represents an interface, false otherwise
+        */
+       boolean isInterface() throws JavaModelException;
+       
+       /**
+        * Returns whether this type represents a local type.
+        *
+        * @exception JavaModelException if this element does not exist or if an
+        *              exception occurs while accessing its corresponding resource.
+        * @return true if this type represents a local type, false otherwise
+        * @since 2.0
+        */
+       boolean isLocal() throws JavaModelException;
+
+       /**
+        * Returns whether this type represents a member type.
+        *
+        * @exception JavaModelException if this element does not exist or if an
+        *              exception occurs while accessing its corresponding resource.
+        * @return true if this type represents a member type, false otherwise
+        * @since 2.0
+        */
+       boolean isMember() throws JavaModelException;
+
+       /**
+        * Creates and returns a type hierarchy for this type containing
+        * this type and all of its supertypes.
+        *
+        * @exception JavaModelException if this element does not exist or if an
+        *              exception occurs while accessing its corresponding resource.
+        * @param monitor the given progress monitor
+        * @return a type hierarchy for this type containing this type and all of its supertypes
+        */
+       //ITypeHierarchy newSupertypeHierarchy(IProgressMonitor monitor) throws JavaModelException;
+       
+       /**
+        * Creates and returns a type hierarchy for this type containing
+        * this type and all of its supertypes, considering types in the given 
+        * working copies. In other words, the list of working copies will take 
+        * precedence over their original compilation units in the workspace.
+        * <p>
+        * Note that passing an empty working copy will be as if the original compilation
+        * unit had been deleted.
+        *
+        * @param workingCopies the working copies that take precedence over their original compilation units
+        * @param monitor the given progress monitor
+        * @return a type hierarchy for this type containing this type and all of its supertypes
+        * @exception JavaModelException if this element does not exist or if an
+        *              exception occurs while accessing its corresponding resource.
+        * @since 2.0
+        */
+//     ITypeHierarchy newSupertypeHierarchy(IWorkingCopy[] workingCopies, IProgressMonitor monitor)
+//             throws JavaModelException;
+//             
+       /**
+        * Creates and returns a type hierarchy for this type containing
+        * this type, all of its supertypes, and all its subtypes in the workspace.
+        *
+        * @exception JavaModelException if this element does not exist or if an
+        *              exception occurs while accessing its corresponding resource.
+        * @param monitor the given progress monitor
+        * @return a type hierarchy for this type containing
+        * this type, all of its supertypes, and all its subtypes in the workspace
+        */
+//     ITypeHierarchy newTypeHierarchy(IProgressMonitor monitor) throws JavaModelException;
+       
+       /**
+        * Creates and returns a type hierarchy for this type containing
+        * this type, all of its supertypes, and all its subtypes in the workspace, 
+        * considering types in the given working copies. In other words, the list of working 
+        * copies that will take precedence over their original compilation units in the workspace.
+        * <p>
+        * Note that passing an empty working copy will be as if the original compilation
+        * unit had been deleted.
+        *
+        * @param workingCopies the working copies that take precedence over their original compilation units
+        * @param monitor the given progress monitor
+        * @return a type hierarchy for this type containing
+        * this type, all of its supertypes, and all its subtypes in the workspace
+        * @exception JavaModelException if this element does not exist or if an
+        *              exception occurs while accessing its corresponding resource.
+        * @since 2.0
+        */
+       // ITypeHierarchy newTypeHierarchy(IWorkingCopy[] workingCopies, IProgressMonitor monitor) throws JavaModelException;
+       
+       /**
+        * Creates and returns a type hierarchy for this type containing
+        * this type, all of its supertypes, and all its subtypes 
+        * in the context of the given project.
+        *
+        * @param project the given project
+        * @param monitor the given progress monitor
+        * @exception JavaModelException if this element does not exist or if an
+        *              exception occurs while accessing its corresponding resource.
+        * @return a type hierarchy for this type containing
+        * this type, all of its supertypes, and all its subtypes 
+        * in the context of the given project
+        */
+//     ITypeHierarchy newTypeHierarchy(IJavaProject project, IProgressMonitor monitor) throws JavaModelException;
+       
+       /**
+        * Resolves the given type name within the context of this type (depending on the type hierarchy 
+        * and its imports). Multiple answers might be found in case there are ambiguous matches.
+        *
+        * Each matching type name is decomposed as an array of two strings, the first denoting the package
+        * name (dot-separated) and the second being the type name.
+        * Returns <code>null</code> if unable to find any matching type.
+        *
+        * For example, resolution of <code>"Object"</code> would typically return
+        * <code>{{"java.lang", "Object"}}</code>.
+        * 
+        * @param typeName the given type name
+        * @exception JavaModelException if code resolve could not be performed. 
+        * @return the resolved type names or <code>null</code> if unable to find any matching type
+        */
+       String[][] resolveType(String typeName) throws JavaModelException;
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IWorkingCopy.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/IWorkingCopy.java
new file mode 100644 (file)
index 0000000..da5c9d5
--- /dev/null
@@ -0,0 +1,349 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *    IBM Corporation - initial API
+ *    IBM Corporation, 2002/03/01- added notion of shared working copy
+ *    IBM Corporation, 2002/26/01- added notion of IProblemRequestor
+ ******************************************************************************/
+package net.sourceforge.phpdt.core;
+
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+/**
+ * Common protocol for Java elements that support working copies.
+ * <p>
+ * A working copy of a Java element acts just like a regular element (handle),
+ * except it is not attached to an underlying resource. A working copy is not
+ * visible to the rest of the Java model. Changes in a working copy's
+ * buffer are not realized in a resource. To bring the Java model up-to-date with a working
+ * copy's contents, an explicit commit must be performed on the working copy. 
+ * Other operations performed on a working copy update the
+ * contents of the working copy's buffer but do not commit the contents
+ * of the working copy.
+ * </p>
+ * <p>
+ * Note: The contents of a working copy is determined when a working
+ * copy is created, based on the current content of the element the working
+ * copy is created from. If a working copy is an <code>IOpenable</code> and is explicitly
+ * closed, the working copy's buffer will be thrown away. However, clients should not
+ * explicitly open and close working copies.
+ * </p>
+ * <p>
+ * The client that creates a working copy is responsible for
+ * destroying the working copy. The Java model will never automatically
+ * destroy or close a working copy. (Note that destroying a working copy
+ * does not commit it to the model, it only frees up the memory occupied by
+ * the element). After a working copy is destroyed, the working copy cannot
+ * be accessed again. Non-handle methods will throw a 
+ * <code>JavaModelException</code> indicating the Java element does not exist.
+ * </p>
+ * <p>
+ * A working copy cannot be created from another working copy.
+ * Calling <code>getWorkingCopy</code> on a working copy returns the receiver.
+ * </p>
+ * <p>
+ * This interface is not intended to be implemented by clients.
+ * </p>
+ */
+public interface IWorkingCopy {
+       
+       /**
+        * Commits the contents of this working copy to its original element
+        * and underlying resource, bringing the Java model up-to-date with
+        * the current contents of the working copy.
+        *
+        * <p>It is possible that the contents of the original resource have changed
+        * since this working copy was created, in which case there is an update conflict.
+        * The value of the <code>force</code> parameter effects the resolution of
+        * such a conflict:<ul>
+        * <li> <code>true</code> - in this case the contents of this working copy are applied to
+        *      the underlying resource even though this working copy was created before
+        *      a subsequent change in the resource</li>
+        * <li> <code>false</code> - in this case a <code>JavaModelException</code> is thrown</li>
+        * </ul>
+        *
+        * @param force a flag to handle the cases when the contents of the original resource have changed
+        * since this working copy was created
+        * @param monitor the given progress monitor
+        * @exception JavaModelException if this working copy could not commit. Reasons include:
+        * <ul>
+        * <li> The original Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+        * <li> A <code>CoreException</code> occurred while updating an underlying resource
+        * <li> This element is not a working copy (INVALID_ELEMENT_TYPES)
+        * <li> A update conflict (described above) (UPDATE_CONFLICT)
+        * </ul>
+        */
+       void commit(boolean force, IProgressMonitor monitor) throws JavaModelException;
+       
+       /**
+        * Destroys this working copy, closing its buffer and discarding
+        * its structure. Subsequent attempts to access non-handle information
+        * for this working copy will result in <code>IJavaModelException</code>s. Has
+        * no effect if this element is not a working copy.
+        * <p>
+        * If this working copy is shared, it is destroyed only when the number of calls to
+        * <code>destroy()</code> is the same as the number of calls to <code>
+        * getSharedWorkingCopy(IProgressMonitor, IBufferFactory)</code>. 
+        * A REMOVED IJavaElementDelta is then reported on this working copy.
+        */
+       void destroy();
+       
+       /**
+        * Finds the shared working copy for this element, given a <code>IBuffer</code> factory. 
+        * If no working copy has been created for this element associated with this
+        * buffer factory, returns <code>null</code>.
+        * <p>
+        * Users of this method must not destroy the resulting working copy. 
+        * 
+        * @param bufferFactory the given <code>IBuffer</code> factory
+        * @return the found shared working copy for this element, <code>null</code> if none
+        * @see IBufferFactory
+        * @since 2.0
+        */
+       IJavaElement findSharedWorkingCopy(IBufferFactory bufferFactory);
+
+       /**
+        * Returns the original element the specified working copy element was created from,
+        * or <code>null</code> if this is not a working copy element.  This is a handle
+        * only method, the returned element may or may not exist.
+        * 
+        * @return the original element the specified working copy element was created from,
+        * or <code>null</code> if this is not a working copy element
+        */
+       IJavaElement getOriginal(IJavaElement workingCopyElement);
+       
+       /**
+        * Returns the original element this working copy was created from,
+        * or <code>null</code> if this is not a working copy.
+        * 
+        * @return the original element this working copy was created from,
+        * or <code>null</code> if this is not a working copy
+        */
+       IJavaElement getOriginalElement();
+       
+       /** 
+        * Finds the elements in this compilation unit that correspond to
+        * the given element.
+        * An element A corresponds to an element B if:
+        * <ul>
+        * <li>A has the same element name as B.
+        * <li>If A is a method, A must have the same number of arguments as
+        *     B and the simple names of the argument types must be equals.
+        * <li>The parent of A corresponds to the parent of B recursively up to
+        *     their respective compilation units.
+        * <li>A exists.
+        * </ul>
+        * Returns <code>null</code> if no such java elements can be found
+        * or if the given element is not included in a compilation unit.
+        * 
+        * @param element the given element
+        * @return the found elements in this compilation unit that correspond to the given element
+        * @since 2.0 
+        */
+       IJavaElement[] findElements(IJavaElement element);
+       
+       /**
+        * Finds the primary type of this compilation unit (i.e.&nbsp;the type with the same name as the
+        * compilation unit), or <code>null</code> if no such a type exists.
+        * 
+        * @return the found primary type of this compilation unit, or <code>null</code> if no such a type exists
+        * @since 2.0
+        */
+       IType findPrimaryType();
+       
+       /**
+        * Returns a shared working copy on this element using the given factory to create
+        * the buffer, or this element if this element is already a working copy.
+        * This API can only answer an already existing working copy if it is based on the same
+        * original compilation unit AND was using the same buffer factory (i.e. as defined by <code>Object#equals</code>).      
+        * <p>
+        * The life time of a shared working copy is as follows:
+        * <ul>
+        * <li>The first call to <code>getSharedWorkingCopy(...)</code> creates a new working copy for this
+        *     element</li>
+        * <li>Subsequent calls increment an internal counter.</li>
+        * <li>A call to <code>destroy()</code> decrements the internal counter.</li>
+        * <li>When this counter is 0, the working copy is destroyed.
+        * </ul>
+        * So users of this method must destroy exactly once the working copy.
+        * <p>
+        * Note that the buffer factory will be used for the life time of this working copy, i.e. if the 
+        * working copy is closed then reopened, this factory will be used.
+        * The buffer will be automatically initialized with the original's compilation unit content
+        * upon creation.
+        * <p>
+        * When the shared working copy instance is created, an ADDED IJavaElementDelta is reported on this
+        * working copy.
+        *
+        * @param monitor a progress monitor used to report progress while opening this compilation unit
+        *                 or <code>null</code> if no progress should be reported 
+        * @param factory the factory that creates a buffer that is used to get the content of the working copy
+        *                 or <code>null</code> if the internal factory should be used
+        * @param problemRequestor a requestor which will get notified of problems detected during
+        *      reconciling as they are discovered. The requestor can be set to <code>null</code> indicating
+        *      that the client is not interested in problems.
+        * @exception JavaModelException if the contents of this element can
+        *   not be determined. Reasons include:
+        * <ul>
+        * <li> This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+        * </ul>
+        * @return a shared working copy on this element using the given factory to create
+        * the buffer, or this element if this element is already a working copy
+        * @see IBufferFactory
+        * @see IProblemRequestor
+        * @since 2.0
+        */
+       IJavaElement getSharedWorkingCopy(
+               IProgressMonitor monitor,
+               IBufferFactory factory,
+               IProblemRequestor problemRequestor)
+               throws JavaModelException;
+               
+       /**
+        * Returns a new working copy of this element if this element is not
+        * a working copy, or this element if this element is already a working copy.
+        *
+        * Note: if intending to share a working copy amongst several clients, then 
+        * <code>#getSharedWorkingCopy</code> should be used instead.
+        * 
+        * @exception JavaModelException if the contents of this element can
+        *   not be determined. Reasons include:
+        * <ul>
+        * <li> This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+        * </ul>
+        * @return a new working copy of this element if this element is not
+        * a working copy, or this element if this element is already a working copy
+        */
+       IJavaElement getWorkingCopy() throws JavaModelException;
+       
+       /**
+        * Returns a new working copy of this element using the given factory to create
+        * the buffer, or this element if this element is already a working copy.
+        * Note that this factory will be used for the life time of this working copy, i.e. if the 
+        * working copy is closed then reopened, this factory will be reused.
+        * The buffer will be automatically initialized with the original's compilation unit content
+        * upon creation.
+        *
+        * Note: if intending to share a working copy amongst several clients, then 
+        * <code>#getSharedWorkingCopy</code> should be used instead.
+        *
+        * @param monitor a progress monitor used to report progress while opening this compilation unit
+        *                 or <code>null</code> if no progress should be reported 
+        * @param factory the factory that creates a buffer that is used to get the content of the working copy
+        *                 or <code>null</code> if the internal factory should be used
+        * @param problemRequestor a requestor which will get notified of problems detected during
+        *      reconciling as they are discovered. The requestor can be set to <code>null</code> indicating
+        *      that the client is not interested in problems.
+        * @exception JavaModelException if the contents of this element can
+        *   not be determined. Reasons include:
+        * <ul>
+        * <li> This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+        * </ul>
+        * @return a new working copy of this element using the given factory to create
+        * the buffer, or this element if this element is already a working copy
+        * @since 2.0
+        */
+       IJavaElement getWorkingCopy(
+               IProgressMonitor monitor,
+               IBufferFactory factory,
+               IProblemRequestor problemRequestor)
+               throws JavaModelException;
+               
+       /**
+        * Returns whether this working copy's original element's content
+        * has not changed since the inception of this working copy.
+        * 
+        * @return true if this working copy's original element's content
+        * has not changed since the inception of this working copy, false otherwise
+        */
+       boolean isBasedOn(IResource resource);
+       
+       /**
+        * Returns whether this element is a working copy.
+        * 
+        * @return true if this element is a working copy, false otherwise
+        */
+       boolean isWorkingCopy();
+       
+       /**
+        * Reconciles the contents of this working copy.
+        * It performs the reconciliation by locally caching the contents of 
+        * the working copy, updating the contents, then creating a delta 
+        * over the cached contents and the new contents, and finally firing
+        * this delta.
+        * <p>
+        * If the working copy hasn't changed, then no problem will be detected,
+        * this is equivalent to <code>IWorkingCopy#reconcile(false, null)</code>.
+        * <p>
+        * Compilation problems found in the new contents are notified through the
+        * <code>IProblemRequestor</code> interface which was passed at
+        * creation, and no longer as transient markers. Therefore this API will
+        * return <code>null</code>.
+        * <p>
+        * Note: It has been assumed that added inner types should
+        * not generate change deltas.  The implementation has been
+        * modified to reflect this assumption.
+        *
+        * @exception JavaModelException if the contents of the original element
+        *              cannot be accessed. Reasons include:
+        * <ul>
+        * <li> The original Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+        * </ul>
+        * @return <code>null</code>
+        */
+       IMarker[] reconcile() throws JavaModelException;
+       
+       /**
+        * Reconciles the contents of this working copy.
+        * It performs the reconciliation by locally caching the contents of 
+        * the working copy, updating the contents, then creating a delta 
+        * over the cached contents and the new contents, and finally firing
+        * this delta.
+        * <p>
+        * The boolean argument allows to force problem detection even if the
+        * working copy is already consistent.
+        * <p>
+        * Compilation problems found in the new contents are notified through the
+        * <code>IProblemRequestor</code> interface which was passed at
+        * creation, and no longer as transient markers. Therefore this API answers
+        * nothing.
+        * <p>
+        * Note: It has been assumed that added inner types should
+        * not generate change deltas.  The implementation has been
+        * modified to reflect this assumption.
+        *
+        * @param forceProblemDetection boolean indicating whether problem should be recomputed
+        *   even if the source hasn't changed.
+        * @param monitor a progress monitor
+        * @exception JavaModelException if the contents of the original element
+        *              cannot be accessed. Reasons include:
+        * <ul>
+        * <li> The original Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+        * </ul>
+        * @since 2.0
+        */
+       void reconcile(boolean forceProblemDetection, IProgressMonitor monitor) throws JavaModelException;
+
+       /**
+        * Restores the contents of this working copy to the current contents of
+        * this working copy's original element. Has no effect if this element
+        * is not a working copy.
+        *
+        * <p>Note: This is the inverse of committing the content of the
+        * working copy to the original element with <code>commit(boolean, IProgressMonitor)</code>.
+        *
+        * @exception JavaModelException if the contents of the original element
+        *              cannot be accessed.  Reasons include:
+        * <ul>
+        * <li> The original Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+        * </ul>
+        */
+       void restore() throws JavaModelException;
+}
\ No newline at end of file
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 (file)
index 0000000..7417c88
--- /dev/null
@@ -0,0 +1,132 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.core;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+
+import net.sourceforge.phpdt.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.
+ * <p>
+ * 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.
+ * </p>
+ *
+ * @see IJavaModelStatus
+ * @see IJavaModelStatusConstants
+ */
+public class JavaModelException extends CoreException {
+       CoreException nestedCoreException;
+/**
+ * Creates a Java model exception that wrappers the given <code>Throwable</code>.
+ * The exception contains a Java-specific status object with severity
+ * <code>IStatus.ERROR</code> and the given status code.
+ *
+ * @param exception the <code>Throwable</code>
+ * @param code one of the Java-specific status codes declared in
+ *   <code>IJavaModelStatusConstants</code>
+ * @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 <code>CoreException</code>.
+ * Equivalent to 
+ * <code>JavaModelException(exception,IJavaModelStatusConstants.CORE_EXCEPTION</code>.
+ *
+ * @param exception the <code>CoreException</code>
+ */
+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 <code>Throwable</code> that caused the failure.
+ *
+ * @return the wrappered <code>Throwable</code>, or <code>null</code> 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 <code>(IJavaModelStatus) getStatus()</code>.
+ *
+ * @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
+ * <code>IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST</code>.
+ * This is a convenience method.
+ *
+ * @return <code>true</code> 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/Signature.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/Signature.java
new file mode 100644 (file)
index 0000000..18d3336
--- /dev/null
@@ -0,0 +1,1384 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.core;
+
+import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
+import net.sourceforge.phpdt.core.compiler.InvalidInputException;
+import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
+import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
+
+/**
+ * Provides methods for encoding and decoding type and method signature strings.
+ * <p>
+ * The syntax for a type signature is:
+ * <pre>
+ * typeSignature ::=
+ *     "B"  // byte
+ *   | "C"  // char
+ *   | "D"  // double
+ *   | "F"  // float
+ *   | "I"  // int
+ *   | "J"  // long
+ *   | "S"  // short
+ *   | "V"  // void
+ *   | "Z"  // boolean
+ *   | "L" + binaryTypeName + ";"  // resolved named type (i.e., in compiled code)
+ *   | "Q" + sourceTypeName + ";"  // unresolved named type (i.e., in source code)
+ *   | "[" + typeSignature  // array of type denoted by typeSignature
+ * </pre>
+ * </p>
+ * <p>
+ * Examples:
+ * <ul>
+ *   <li><code>"[[I"</code> denotes <code>int[][]</code></li>
+ *   <li><code>"Ljava.lang.String;"</code> denotes <code>java.lang.String</code> in compiled code</li>
+ *   <li><code>"QString"</code> denotes <code>String</code> in source code</li>
+ *   <li><code>"Qjava.lang.String"</code> denotes <code>java.lang.String</code> in source code</li>
+ *   <li><code>"[QString"</code> denotes <code>String[]</code> in source code</li>
+ * </ul>
+ * </p>
+ * <p>
+ * The syntax for a method signature is:
+ * <pre>
+ * methodSignature ::= "(" + paramTypeSignature* + ")" + returnTypeSignature
+ * paramTypeSignature ::= typeSignature
+ * returnTypeSignature ::= typeSignature
+ * </pre>
+ * <p>
+ * Examples:
+ * <ul>
+ *   <li><code>"()I"</code> denotes <code>int foo()</code></li>
+ *   <li><code>"([Ljava.lang.String;)V"</code> denotes <code>void foo(java.lang.String[])</code> in compiled code</li>
+ *   <li><code>"(QString;)QObject;"</code> denotes <code>Object foo(String)</code> in source code</li>
+ * </ul>
+ * </p>
+ * <p>
+ * This class provides static methods and constants only; it is not intended to be
+ * instantiated or subclassed by clients.
+ * </p>
+ */
+public final class Signature {
+
+       /**
+        * Character constant indicating the primitive type boolean in a signature.
+        * Value is <code>'Z'</code>.
+        */
+       public static final char C_BOOLEAN              = 'Z';
+
+       /**
+        * Character constant indicating the primitive type byte in a signature.
+        * Value is <code>'B'</code>.
+        */
+       public static final char C_BYTE                 = 'B';
+
+       /**
+        * Character constant indicating the primitive type char in a signature.
+        * Value is <code>'C'</code>.
+        */
+       public static final char C_CHAR                 = 'C';
+
+       /**
+        * Character constant indicating the primitive type double in a signature.
+        * Value is <code>'D'</code>.
+        */
+       public static final char C_DOUBLE               = 'D';
+
+       /**
+        * Character constant indicating the primitive type float in a signature.
+        * Value is <code>'F'</code>.
+        */
+       public static final char C_FLOAT                = 'F';
+
+       /**
+        * Character constant indicating the primitive type int in a signature.
+        * Value is <code>'I'</code>.
+        */
+       public static final char C_INT                  = 'I';
+       
+       /**
+        * Character constant indicating the semicolon in a signature.
+        * Value is <code>';'</code>.
+        */
+       public static final char C_SEMICOLON                    = ';';
+
+       /**
+        * Character constant indicating the primitive type long in a signature.
+        * Value is <code>'J'</code>.
+        */
+       public static final char C_LONG                 = 'J';
+       
+       /**
+        * Character constant indicating the primitive type short in a signature.
+        * Value is <code>'S'</code>.
+        */
+       public static final char C_SHORT                = 'S';
+       
+       /**
+        * Character constant indicating result type void in a signature.
+        * Value is <code>'V'</code>.
+        */
+       public static final char C_VOID                 = 'V';
+       
+       /** 
+        * Character constant indicating the dot in a signature. 
+        * Value is <code>'.'</code>.
+        */
+       public static final char C_DOT                  = '.';
+       
+       /** 
+        * Character constant indicating the dollar in a signature.
+        * Value is <code>'$'</code>.
+        */
+       public static final char C_DOLLAR                       = '$';
+
+       /** 
+        * Character constant indicating an array type in a signature.
+        * Value is <code>'['</code>.
+        */
+       public static final char C_ARRAY                = '[';
+
+       /** 
+        * Character constant indicating the start of a resolved, named type in a 
+        * signature. Value is <code>'L'</code>.
+        */
+       public static final char C_RESOLVED             = 'L';
+
+       /** 
+        * Character constant indicating the start of an unresolved, named type in a
+        * signature. Value is <code>'Q'</code>.
+        */
+       public static final char C_UNRESOLVED   = 'Q';
+
+       /**
+        * Character constant indicating the end of a named type in a signature. 
+        * Value is <code>';'</code>.
+        */
+       public static final char C_NAME_END             = ';';
+
+       /**
+        * Character constant indicating the start of a parameter type list in a
+        * signature. Value is <code>'('</code>.
+        */
+       public static final char C_PARAM_START  = '(';
+
+       /**
+        * Character constant indicating the end of a parameter type list in a 
+        * signature. Value is <code>')'</code>.
+        */
+       public static final char C_PARAM_END    = ')';
+
+       /**
+        * String constant for the signature of the primitive type boolean.
+        * Value is <code>"Z"</code>.
+        */
+       public static final String SIG_BOOLEAN          = "Z"; //$NON-NLS-1$
+
+       /**
+        * String constant for the signature of the primitive type byte. 
+        * Value is <code>"B"</code>.
+        */
+       public static final String SIG_BYTE             = "B"; //$NON-NLS-1$
+
+       /**
+        * String constant for the signature of the primitive type char.
+        * Value is <code>"C"</code>.
+        */
+       public static final String SIG_CHAR             = "C"; //$NON-NLS-1$
+
+       /**
+        * String constant for the signature of the primitive type double.
+        * Value is <code>"D"</code>.
+        */
+       public static final String SIG_DOUBLE           = "D"; //$NON-NLS-1$
+
+       /**
+        * String constant for the signature of the primitive type float.
+        * Value is <code>"F"</code>.
+        */
+       public static final String SIG_FLOAT            = "F"; //$NON-NLS-1$
+
+       /**
+        * String constant for the signature of the primitive type int.
+        * Value is <code>"I"</code>.
+        */
+       public static final String SIG_INT                      = "I"; //$NON-NLS-1$
+
+       /**
+        * String constant for the signature of the primitive type long.
+        * Value is <code>"J"</code>.
+        */
+       public static final String SIG_LONG                     = "J"; //$NON-NLS-1$
+
+       /**
+        * String constant for the signature of the primitive type short.
+        * Value is <code>"S"</code>.
+        */
+       public static final String SIG_SHORT            = "S"; //$NON-NLS-1$
+
+       /** String constant for the signature of result type void.
+        * Value is <code>"V"</code>.
+        */
+       public static final String SIG_VOID                     = "V"; //$NON-NLS-1$
+       
+       private static final char[] NO_CHAR = new char[0];
+       private static final char[][] NO_CHAR_CHAR = new char[0][];
+       private static final char[] BOOLEAN = {'b', 'o', 'o', 'l', 'e', 'a', 'n'};
+       private static final char[] BYTE = {'b', 'y', 't', 'e'};
+       private static final char[] CHAR = {'c', 'h', 'a', 'r'};
+       private static final char[] DOUBLE = {'d', 'o', 'u', 'b', 'l', 'e'};
+       private static final char[] FLOAT = {'f', 'l', 'o', 'a', 't'};
+       private static final char[] INT = {'i', 'n', 't'};
+       private static final char[] LONG = {'l', 'o', 'n', 'g'};
+       private static final char[] SHORT = {'s', 'h', 'o', 'r', 't'};
+       private static final char[] VOID = {'v', 'o', 'i', 'd'};
+       
+       
+/**
+ * Not instantiable.
+ */
+private Signature() {}
+
+private static long copyType(char[] signature, int sigPos, char[] dest, int index, boolean fullyQualifyTypeNames) {
+       int arrayCount = 0;
+       loop: while (true) {
+               switch (signature[sigPos++]) {
+                       case C_ARRAY :
+                               arrayCount++;
+                               break;
+                       case C_BOOLEAN :
+                               int length = BOOLEAN.length;
+                               System.arraycopy(BOOLEAN, 0, dest, index, length);
+                               index += length;
+                               break loop;
+                       case C_BYTE :
+                               length = BYTE.length;
+                               System.arraycopy(BYTE, 0, dest, index, length);
+                               index += length;
+                               break loop;
+                       case C_CHAR :
+                               length = CHAR.length;
+                               System.arraycopy(CHAR, 0, dest, index, length);
+                               index += length;
+                               break loop;
+                       case C_DOUBLE :
+                               length = DOUBLE.length;
+                               System.arraycopy(DOUBLE, 0, dest, index, length);
+                               index += length;
+                               break loop;
+                       case C_FLOAT :
+                               length = FLOAT.length;
+                               System.arraycopy(FLOAT, 0, dest, index, length);
+                               index += length;
+                               break loop;
+                       case C_INT :
+                               length = INT.length;
+                               System.arraycopy(INT, 0, dest, index, length);
+                               index += length;
+                               break loop;
+                       case C_LONG :
+                               length = LONG.length;
+                               System.arraycopy(LONG, 0, dest, index, length);
+                               index += length;
+                               break loop;
+                       case C_SHORT :
+                               length = SHORT.length;
+                               System.arraycopy(SHORT, 0, dest, index, length);
+                               index += length;
+                               break loop;
+                       case C_VOID :
+                               length = VOID.length;
+                               System.arraycopy(VOID, 0, dest, index, length);
+                               index += length;
+                               break loop;
+                       case C_RESOLVED :
+                       case C_UNRESOLVED :
+                               int end = CharOperation.indexOf(C_SEMICOLON, signature, sigPos);
+                               if (end == -1) throw new IllegalArgumentException();
+                               int start;
+                               if (fullyQualifyTypeNames) {
+                                       start = sigPos;
+                               } else {
+                                       start = CharOperation.lastIndexOf(C_DOT, signature, sigPos, end)+1;
+                                       if (start == 0) start = sigPos;
+                               } 
+                               length = end-start;
+                               System.arraycopy(signature, start, dest, index, length);
+                               sigPos = end+1;
+                               index += length;
+                               break loop;
+               }
+       }
+       while (arrayCount-- > 0) {
+               dest[index++] = '[';
+               dest[index++] = ']';
+       }
+       return (((long) index) << 32) + sigPos;
+}
+/**
+ * Creates a new type signature with the given amount of array nesting added 
+ * to the given type signature.
+ *
+ * @param typeSignature the type signature
+ * @param arrayCount the desired number of levels of array nesting
+ * @return the encoded array type signature
+ * 
+ * @since 2.0
+ */
+public static char[] createArraySignature(char[] typeSignature, int arrayCount) {
+       if (arrayCount == 0) return typeSignature;
+       int sigLength = typeSignature.length;
+       char[] result = new char[arrayCount + sigLength];
+       for (int i = 0; i < arrayCount; i++) {
+               result[i] = C_ARRAY;
+       }
+       System.arraycopy(typeSignature, 0, result, arrayCount, sigLength);
+       return result;
+}
+/**
+ * Creates a new type signature with the given amount of array nesting added 
+ * to the given type signature.
+ *
+ * @param typeSignature the type signature
+ * @param arrayCount the desired number of levels of array nesting
+ * @return the encoded array type signature
+ */
+public static String createArraySignature(String typeSignature, int arrayCount) {
+       return new String(createArraySignature(typeSignature.toCharArray(), arrayCount));
+}
+/**
+ * Creates a method signature from the given parameter and return type 
+ * signatures. The encoded method signature is dot-based.
+ *
+ * @param parameterTypes the list of parameter type signatures
+ * @param returnType the return type signature
+ * @return the encoded method signature
+ * 
+ * @since 2.0
+ */
+public static char[] createMethodSignature(char[][] parameterTypes, char[] returnType) {
+       int parameterTypesLength = parameterTypes.length;
+       int parameterLength = 0;
+       for (int i = 0; i < parameterTypesLength; i++) {
+               parameterLength += parameterTypes[i].length;
+               
+       }
+       int returnTypeLength = returnType.length;
+       char[] result = new char[1 + parameterLength + 1 + returnTypeLength];
+       result[0] = C_PARAM_START;
+       int index = 1;
+       for (int i = 0; i < parameterTypesLength; i++) {
+               char[] parameterType = parameterTypes[i];
+               int length = parameterType.length;
+               System.arraycopy(parameterType, 0, result, index, length);
+               index += length;
+       }
+       result[index] = C_PARAM_END;
+       System.arraycopy(returnType, 0, result, index+1, returnTypeLength);
+       return result;
+}
+/**
+ * Creates a method signature from the given parameter and return type 
+ * signatures. The encoded method signature is dot-based.
+ *
+ * @param parameterTypes the list of parameter type signatures
+ * @param returnType the return type signature
+ * @return the encoded method signature
+ */
+public static String createMethodSignature(String[] parameterTypes, String returnType) {
+       int parameterTypesLenth = parameterTypes.length;
+       char[][] parameters = new char[parameterTypesLenth][];
+       for (int i = 0; i < parameterTypesLenth; i++) {
+               parameters[i] = parameterTypes[i].toCharArray();
+       }
+       return new String(createMethodSignature(parameters, returnType.toCharArray()));
+}
+/**
+ * Creates a new type signature from the given type name encoded as a character
+ * array. This method is equivalent to
+ * <code>createTypeSignature(new String(typeName),isResolved)</code>, although
+ * more efficient for callers with character arrays rather than strings. If the 
+ * type name is qualified, then it is expected to be dot-based.
+ *
+ * @param typeName the possibly qualified type name
+ * @param isResolved <code>true</code> if the type name is to be considered
+ *   resolved (for example, a type name from a binary class file), and 
+ *   <code>false</code> if the type name is to be considered unresolved
+ *   (for example, a type name found in source code)
+ * @return the encoded type signature
+ * @see #createTypeSignature(java.lang.String,boolean)
+ */
+public static String createTypeSignature(char[] typeName, boolean isResolved) {
+       return new String(createCharArrayTypeSignature(typeName, isResolved));
+}
+/**
+ * Creates a new type signature from the given type name encoded as a character
+ * array. This method is equivalent to
+ * <code>createTypeSignature(new String(typeName),isResolved).toCharArray()</code>, although
+ * more efficient for callers with character arrays rather than strings. If the 
+ * type name is qualified, then it is expected to be dot-based.
+ *
+ * @param typeName the possibly qualified type name
+ * @param isResolved <code>true</code> if the type name is to be considered
+ *   resolved (for example, a type name from a binary class file), and 
+ *   <code>false</code> if the type name is to be considered unresolved
+ *   (for example, a type name found in source code)
+ * @return the encoded type signature
+ * @see #createTypeSignature(java.lang.String,boolean)
+ * 
+ * @since 2.0
+ */
+public static char[] createCharArrayTypeSignature(char[] typeName, boolean isResolved) {
+       try {
+               Scanner scanner = new Scanner();
+               scanner.setSource(typeName);
+               int token = scanner.getNextToken();
+               boolean primitive = true;
+               char primitiveSig = ' ';
+               StringBuffer sig = null;
+               int arrayCount = 0;
+               switch (token) {
+                       case ITerminalSymbols.TokenNameIdentifier :
+                               char[] idSource = scanner.getCurrentIdentifierSource();
+                               sig = new StringBuffer(idSource.length);
+                               sig.append(idSource);
+                               primitive = false;
+                               break;
+//                     case ITerminalSymbols.TokenNameboolean :
+//                             primitiveSig = Signature.C_BOOLEAN;
+//                             break;
+//                     case ITerminalSymbols.TokenNamebyte :
+//                             primitiveSig = Signature.C_BYTE;
+//                             break;
+//                     case ITerminalSymbols.TokenNamechar :
+//                             primitiveSig = Signature.C_CHAR;
+//                             break;
+//                     case ITerminalSymbols.TokenNamedouble :
+//                             primitiveSig = Signature.C_DOUBLE;
+//                             break;
+//                     case ITerminalSymbols.TokenNamefloat :
+//                             primitiveSig = Signature.C_FLOAT;
+//                             break;
+//                     case ITerminalSymbols.TokenNameint :
+//                             primitiveSig = Signature.C_INT;
+//                             break;
+//                     case ITerminalSymbols.TokenNamelong :
+//                             primitiveSig = Signature.C_LONG;
+//                             break;
+//                     case ITerminalSymbols.TokenNameshort :
+//                             primitiveSig = Signature.C_SHORT;
+//                             break;
+//                     case ITerminalSymbols.TokenNamevoid :
+//                             primitiveSig = Signature.C_VOID;
+//                             break;
+                       default :
+                               throw new IllegalArgumentException();
+               }
+               token = scanner.getNextToken();
+               while (!primitive && token == ITerminalSymbols.TokenNameDOT) {
+                       sig.append(scanner.getCurrentIdentifierSource());
+                       token = scanner.getNextToken();
+                       if (token == ITerminalSymbols.TokenNameIdentifier) {
+                               sig.append(scanner.getCurrentIdentifierSource());
+                               token = scanner.getNextToken();
+                       } else {
+                               throw new IllegalArgumentException();
+                       }
+               }
+               while (token == ITerminalSymbols.TokenNameLBRACKET) {
+                       token = scanner.getNextToken();
+                       if (token != ITerminalSymbols.TokenNameRBRACKET)
+                               throw new IllegalArgumentException();
+                       arrayCount++;
+                       token = scanner.getNextToken();
+               }
+               if (token != ITerminalSymbols.TokenNameEOF)
+                       throw new IllegalArgumentException();
+               char[] result;
+               if (primitive) {
+                       result = new char[arrayCount+1];
+                       result[arrayCount] = primitiveSig;
+               } else {
+                       int sigLength = sig.length(); 
+                       int resultLength = arrayCount + 1 + sigLength + 1; // e.g. '[[[Ljava.lang.String;'
+                       result = new char[resultLength];
+                       sig.getChars(0, sigLength, result, arrayCount + 1);
+                       result[arrayCount] = isResolved ? C_RESOLVED : C_UNRESOLVED;
+                       result[resultLength-1] = C_NAME_END;
+               }
+               for (int i = 0; i < arrayCount; i++) {
+                       result[i] = C_ARRAY;
+               }
+               return result;
+       } catch (InvalidInputException e) {
+               throw new IllegalArgumentException();
+       }
+}
+/**
+ * Creates a new type signature from the given type name. If the type name is qualified,
+ * then it is expected to be dot-based.
+ * <p>
+ * For example:
+ * <pre>
+ * <code>
+ * createTypeSignature("int", hucairz) -> "I"
+ * createTypeSignature("java.lang.String", true) -> "Ljava.lang.String;"
+ * createTypeSignature("String", false) -> "QString;"
+ * createTypeSignature("java.lang.String", false) -> "Qjava.lang.String;"
+ * createTypeSignature("int []", false) -> "[I"
+ * </code>
+ * </pre>
+ * </p>
+ *
+ * @param typeName the possibly qualified type name
+ * @param isResolved <code>true</code> if the type name is to be considered
+ *   resolved (for example, a type name from a binary class file), and 
+ *   <code>false</code> if the type name is to be considered unresolved
+ *   (for example, a type name found in source code)
+ * @return the encoded type signature
+ */
+public static String createTypeSignature(String typeName, boolean isResolved) {
+       return createTypeSignature(typeName.toCharArray(), isResolved);
+}
+/**
+ * Returns the array count (array nesting depth) of the given type signature.
+ *
+ * @param typeSignature the type signature
+ * @return the array nesting depth, or 0 if not an array
+ * @exception IllegalArgumentException if the signature is not syntactically
+ *   correct
+ * 
+ * @since 2.0
+ */
+public static int getArrayCount(char[] typeSignature) throws IllegalArgumentException {        
+       try {
+               int count = 0;
+               while (typeSignature[count] == C_ARRAY) {
+                       ++count;
+               }
+               return count;
+       } catch (ArrayIndexOutOfBoundsException e) { // signature is syntactically incorrect if last character is C_ARRAY
+               throw new IllegalArgumentException();
+       }
+}
+/**
+ * Returns the array count (array nesting depth) of the given type signature.
+ *
+ * @param typeSignature the type signature
+ * @return the array nesting depth, or 0 if not an array
+ * @exception IllegalArgumentException if the signature is not syntactically
+ *   correct
+ */
+public static int getArrayCount(String typeSignature) throws IllegalArgumentException {
+       return getArrayCount(typeSignature.toCharArray());
+}
+/**
+ * Returns the type signature without any array nesting.
+ * <p>
+ * For example:
+ * <pre>
+ * <code>
+ * getElementType({'[', '[', 'I'}) --> {'I'}.
+ * </code>
+ * </pre>
+ * </p>
+ * 
+ * @param typeSignature the type signature
+ * @return the type signature without arrays
+ * @exception IllegalArgumentException if the signature is not syntactically
+ *   correct
+ * 
+ * @since 2.0
+ */
+public static char[] getElementType(char[] typeSignature) throws IllegalArgumentException {
+       int count = getArrayCount(typeSignature);
+       if (count == 0) return typeSignature;
+       int length = typeSignature.length;
+       char[] result = new char[length-count];
+       System.arraycopy(typeSignature, count, result, 0, length-count);
+       return result;
+}
+/**
+ * Returns the type signature without any array nesting.
+ * <p>
+ * For example:
+ * <pre>
+ * <code>
+ * getElementType("[[I") --> "I".
+ * </code>
+ * </pre>
+ * </p>
+ * 
+ * @param typeSignature the type signature
+ * @return the type signature without arrays
+ * @exception IllegalArgumentException if the signature is not syntactically
+ *   correct
+ */
+public static String getElementType(String typeSignature) throws IllegalArgumentException {
+       return new String(getElementType(typeSignature.toCharArray()));
+}
+/**
+ * Returns the number of parameter types in the given method signature.
+ *
+ * @param methodSignature the method signature
+ * @return the number of parameters
+ * @exception IllegalArgumentException if the signature is not syntactically
+ *   correct
+ * @since 2.0
+ */
+public static int getParameterCount(char[] methodSignature) throws IllegalArgumentException {
+       try {
+               int count = 0;
+               int i = CharOperation.indexOf(C_PARAM_START, methodSignature) + 1;
+               if (i == 0)
+                       throw new IllegalArgumentException();
+               for (;;) {
+                       char c = methodSignature[i++];
+                       switch (c) {
+                               case C_ARRAY :
+                                       break;
+                               case C_BOOLEAN :
+                               case C_BYTE :
+                               case C_CHAR :
+                               case C_DOUBLE :
+                               case C_FLOAT :
+                               case C_INT :
+                               case C_LONG :
+                               case C_SHORT :
+                               case C_VOID :
+                                       ++count;
+                                       break;
+                               case C_RESOLVED :
+                               case C_UNRESOLVED :
+                                       i = CharOperation.indexOf(C_SEMICOLON, methodSignature, i) + 1;
+                                       if (i == 0)
+                                               throw new IllegalArgumentException();
+                                       ++count;
+                                       break;
+                               case C_PARAM_END :
+                                       return count;
+                               default :
+                                       throw new IllegalArgumentException();
+                       }
+               }
+       } catch (ArrayIndexOutOfBoundsException e) {
+               throw new IllegalArgumentException();
+       }
+}
+/**
+ * Returns the number of parameter types in the given method signature.
+ *
+ * @param methodSignature the method signature
+ * @return the number of parameters
+ * @exception IllegalArgumentException if the signature is not syntactically
+ *   correct
+ */
+public static int getParameterCount(String methodSignature) throws IllegalArgumentException {
+       return getParameterCount(methodSignature.toCharArray());
+}
+/**
+ * Extracts the parameter type signatures from the given method signature. 
+ * The method signature is expected to be dot-based.
+ *
+ * @param methodSignature the method signature
+ * @return the list of parameter type signatures
+ * @exception IllegalArgumentException if the signature is syntactically
+ *   incorrect
+ * 
+ * @since 2.0
+ */
+public static char[][] getParameterTypes(char[] methodSignature) throws IllegalArgumentException {
+       try {
+               int count = getParameterCount(methodSignature);
+               char[][] result = new char[count][];
+               if (count == 0)
+                       return result;
+               int i = CharOperation.indexOf(C_PARAM_START, methodSignature) + 1;
+               count = 0;
+               int start = i;
+               for (;;) {
+                       char c = methodSignature[i++];
+                       switch (c) {
+                               case C_ARRAY :
+                                       // array depth is i - start;
+                                       break;
+                               case C_BOOLEAN :
+                               case C_BYTE :
+                               case C_CHAR :
+                               case C_DOUBLE :
+                               case C_FLOAT :
+                               case C_INT :
+                               case C_LONG :
+                               case C_SHORT :
+                               case C_VOID :
+                                       // common case of base types
+                                       if (i - start == 1) {
+                                               switch (c) {
+                                                       case C_BOOLEAN :
+                                                               result[count++] = new char[] {C_BOOLEAN};
+                                                               break;
+                                                       case C_BYTE :
+                                                               result[count++] = new char[] {C_BYTE};
+                                                               break;
+                                                       case C_CHAR :
+                                                               result[count++] = new char[] {C_CHAR};
+                                                               break;
+                                                       case C_DOUBLE :
+                                                               result[count++] = new char[] {C_DOUBLE};
+                                                               break;
+                                                       case C_FLOAT :
+                                                               result[count++] = new char[] {C_FLOAT};
+                                                               break;
+                                                       case C_INT :
+                                                               result[count++] = new char[] {C_INT};
+                                                               break;
+                                                       case C_LONG :
+                                                               result[count++] = new char[] {C_LONG};
+                                                               break;
+                                                       case C_SHORT :
+                                                               result[count++] = new char[] {C_SHORT};
+                                                               break;
+                                                       case C_VOID :
+                                                               result[count++] = new char[] {C_VOID};
+                                                               break;
+                                               }
+                                       } else {
+                                               result[count++] = CharOperation.subarray(methodSignature, start, i);
+                                       }
+                                       start = i;
+                                       break;
+                               case C_RESOLVED :
+                               case C_UNRESOLVED :
+                                       i = CharOperation.indexOf(C_SEMICOLON, methodSignature, i) + 1;
+                                       if (i == 0)
+                                               throw new IllegalArgumentException();
+                                       result[count++] = CharOperation.subarray(methodSignature, start, i);
+                                       start = i;
+                                       break;
+                               case C_PARAM_END:
+                                       return result;
+                               default :
+                                       throw new IllegalArgumentException();
+                       }
+               }
+       } catch (ArrayIndexOutOfBoundsException e) {
+               throw new IllegalArgumentException();
+       }
+}
+/**
+ * Extracts the parameter type signatures from the given method signature. 
+ * The method signature is expected to be dot-based.
+ *
+ * @param methodSignature the method signature
+ * @return the list of parameter type signatures
+ * @exception IllegalArgumentException if the signature is syntactically
+ *   incorrect
+ */
+public static String[] getParameterTypes(String methodSignature) throws IllegalArgumentException {
+       char[][] parameterTypes = getParameterTypes(methodSignature.toCharArray());
+       int length = parameterTypes.length;
+       String[] result = new String[length];
+       for (int i = 0; i < length; i++) {
+               result[i] = new String(parameterTypes[i]);
+       }
+       return result;
+}
+/**
+ * Returns a char array containing all but the last segment of the given 
+ * dot-separated qualified name. Returns the empty char array if it is not qualified.
+ * <p>
+ * For example:
+ * <pre>
+ * <code>
+ * getQualifier({'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'O', 'b', 'j', 'e', 'c', 't'}) -> {'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g'}
+ * getQualifier({'O', 'u', 't', 'e', 'r', '.', 'I', 'n', 'n', 'e', 'r'}) -> {'O', 'u', 't', 'e', 'r'}
+ * </code>
+ * </pre>
+ * </p>
+ *
+ * @param name the name
+ * @return the qualifier prefix, or the empty char array if the name contains no
+ *   dots
+ * 
+ * @since 2.0
+ */
+public static char[] getQualifier(char[] name) {
+       int lastDot = CharOperation.lastIndexOf(C_DOT, name);
+       if (lastDot == -1) {
+               return NO_CHAR; //$NON-NLS-1$
+       }
+       return CharOperation.subarray(name, 0, lastDot);
+}
+/**
+ * Returns a string containing all but the last segment of the given 
+ * dot-separated qualified name. Returns the empty string if it is not qualified.
+ * <p>
+ * For example:
+ * <pre>
+ * <code>
+ * getQualifier("java.lang.Object") -> "java.lang"
+ * getQualifier("Outer.Inner") -> "Outer"
+ * </code>
+ * </pre>
+ * </p>
+ *
+ * @param name the name
+ * @return the qualifier prefix, or the empty string if the name contains no
+ *   dots
+ */
+public static String getQualifier(String name) {
+       return new String(getQualifier(name.toCharArray()));
+}
+/**
+ * Extracts the return type from the given method signature. The method signature is 
+ * expected to be dot-based.
+ *
+ * @param methodSignature the method signature
+ * @return the type signature of the return type
+ * @exception IllegalArgumentException if the signature is syntactically
+ *   incorrect
+ * 
+ * @since 2.0
+ */
+public static char[] getReturnType(char[] methodSignature) throws IllegalArgumentException {
+       int i = CharOperation.lastIndexOf(C_PARAM_END, methodSignature);
+       if (i == -1) {
+               throw new IllegalArgumentException();
+       }
+       return CharOperation.subarray(methodSignature, i + 1, methodSignature.length);
+}
+/**
+ * Extracts the return type from the given method signature. The method signature is 
+ * expected to be dot-based.
+ *
+ * @param methodSignature the method signature
+ * @return the type signature of the return type
+ * @exception IllegalArgumentException if the signature is syntactically
+ *   incorrect
+ */
+public static String getReturnType(String methodSignature) throws IllegalArgumentException {
+       return new String(getReturnType(methodSignature.toCharArray()));
+}
+/**
+ * Returns the last segment of the given dot-separated qualified name.
+ * Returns the given name if it is not qualified.
+ * <p>
+ * For example:
+ * <pre>
+ * <code>
+ * getSimpleName({'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'O', 'b', 'j', 'e', 'c', 't'}) -> {'O', 'b', 'j', 'e', 'c', 't'}
+ * </code>
+ * </pre>
+ * </p>
+ *
+ * @param name the name
+ * @return the last segment of the qualified name
+ * 
+ * @since 2.0
+ */
+public static char[] getSimpleName(char[] name) {
+       int lastDot = CharOperation.lastIndexOf(C_DOT, name);
+       if (lastDot == -1) {
+               return name;
+       }
+       return CharOperation.subarray(name, lastDot + 1, name.length);
+}
+/**
+ * Returns the last segment of the given dot-separated qualified name.
+ * Returns the given name if it is not qualified.
+ * <p>
+ * For example:
+ * <pre>
+ * <code>
+ * getSimpleName("java.lang.Object") -> "Object"
+ * </code>
+ * </pre>
+ * </p>
+ *
+ * @param name the name
+ * @return the last segment of the qualified name
+ */
+public static String getSimpleName(String name) {
+       return new String(getSimpleName(name.toCharArray()));
+}
+/**
+ * Returns all segments of the given dot-separated qualified name.
+ * Returns an array with only the given name if it is not qualified.
+ * Returns an empty array if the name is empty.
+ * <p>
+ * For example:
+ * <pre>
+ * <code>
+ * getSimpleNames({'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'O', 'b', 'j', 'e', 'c', 't'}) -> {{'j', 'a', 'v', 'a'}, {'l', 'a', 'n', 'g'}, {'O', 'b', 'j', 'e', 'c', 't'}}
+ * getSimpleNames({'O', 'b', 'j', 'e', 'c', 't'}) -> {{'O', 'b', 'j', 'e', 'c', 't'}}
+ * getSimpleNames("") -> {}
+ * </code>
+ * </pre>
+ *
+ * @param name the name
+ * @return the list of simple names, possibly empty
+ * 
+ * @since 2.0
+ */
+public static char[][] getSimpleNames(char[] name) {
+       if (name.length == 0) {
+               return NO_CHAR_CHAR;
+       }
+       int dot = CharOperation.indexOf(C_DOT, name);
+       if (dot == -1) {
+               return new char[][] {name};
+       }
+       int n = 1;
+       while ((dot = CharOperation.indexOf(C_DOT, name, dot + 1)) != -1) {
+               ++n;
+       }
+       char[][] result = new char[n + 1][];
+       int segStart = 0;
+       for (int i = 0; i < n; ++i) {
+               dot = CharOperation.indexOf(C_DOT, name, segStart);
+               result[i] = CharOperation.subarray(name, segStart, dot);
+               segStart = dot + 1;
+       }
+       result[n] = CharOperation.subarray(name, segStart, name.length);
+       return result;
+}
+/**
+ * Returns all segments of the given dot-separated qualified name.
+ * Returns an array with only the given name if it is not qualified.
+ * Returns an empty array if the name is empty.
+ * <p>
+ * For example:
+ * <pre>
+ * <code>
+ * getSimpleNames("java.lang.Object") -> {"java", "lang", "Object"}
+ * getSimpleNames("Object") -> {"Object"}
+ * getSimpleNames("") -> {}
+ * </code>
+ * </pre>
+ *
+ * @param name the name
+ * @return the list of simple names, possibly empty
+ */
+public static String[] getSimpleNames(String name) {
+       char[][] simpleNames = getSimpleNames(name.toCharArray());
+       int length = simpleNames.length;
+       String[] result = new String[length];
+       for (int i = 0; i < length; i++) {
+               result[i] = new String(simpleNames[i]);
+       }
+       return result;
+}
+/**
+ * Converts the given method signature to a readable form. The method signature is expected to
+ * be dot-based.
+ * <p>
+ * For example:
+ * <pre>
+ * <code>
+ * toString("([Ljava.lang.String;)V", "main", new String[] {"args"}, false, true) -> "void main(String[] args)"
+ * </code>
+ * </pre>
+ * </p>
+ * 
+ * @param methodSignature the method signature to convert
+ * @param methodName the name of the method to insert in the result, or 
+ *   <code>null</code> if no method name is to be included
+ * @param parameterNames the parameter names to insert in the result, or 
+ *   <code>null</code> if no parameter names are to be included; if supplied,
+ *   the number of parameter names must match that of the method signature
+ * @param fullyQualifyTypeNames <code>true</code> if type names should be fully
+ *   qualified, and <code>false</code> to use only simple names
+ * @param includeReturnType <code>true</code> if the return type is to be
+ *   included
+ * @return the char array representation of the method signature
+ * 
+ * @since 2.0
+ */
+public static char[] toCharArray(char[] methodSignature, char[] methodName, char[][] parameterNames, boolean fullyQualifyTypeNames, boolean includeReturnType) {
+       try {
+               int firstParen = CharOperation.indexOf(C_PARAM_START, methodSignature);
+               if (firstParen == -1) throw new IllegalArgumentException();
+               
+               int sigLength = methodSignature.length;
+               
+               // compute result length
+               
+               // method signature
+               int paramCount = 0;
+               int lastParen = -1;
+               int resultLength = 0;
+               signature: for (int i = firstParen; i < sigLength; i++) {
+                       switch (methodSignature[i]) {
+                               case C_ARRAY :
+                                       resultLength += 2; // []
+                                       continue signature;
+                               case C_BOOLEAN :
+                                       resultLength += BOOLEAN.length;
+                                       break;
+                               case C_BYTE :
+                                       resultLength += BYTE.length;
+                                       break;
+                               case C_CHAR :
+                                       resultLength += CHAR.length;
+                                       break;
+                               case C_DOUBLE :
+                                       resultLength += DOUBLE.length;
+                                       break;
+                               case C_FLOAT :
+                                       resultLength += FLOAT.length;
+                                       break;
+                               case C_INT :
+                                       resultLength += INT.length;
+                                       break;
+                               case C_LONG :
+                                       resultLength += LONG.length;
+                                       break;
+                               case C_SHORT :
+                                       resultLength += SHORT.length;
+                                       break;
+                               case C_VOID :
+                                       resultLength += VOID.length;
+                                       break;
+                               case C_RESOLVED :
+                               case C_UNRESOLVED :
+                                       int end = CharOperation.indexOf(C_SEMICOLON, methodSignature, i);
+                                       if (end == -1) throw new IllegalArgumentException();
+                                       int start;
+                                       if (fullyQualifyTypeNames) {
+                                               start = i+1;
+                                       } else {
+                                               start = CharOperation.lastIndexOf(C_DOT, methodSignature, i, end) + 1;
+                                               if (start == 0) start = i+1;
+                                       } 
+                                       resultLength += end-start;
+                                       i = end;
+                                       break;
+                               case C_PARAM_START :
+                                       // add space for "("
+                                       resultLength++;
+                                       continue signature;
+                               case C_PARAM_END :
+                                       lastParen = i;
+                                       if (includeReturnType) {
+                                               if (paramCount > 0) {
+                                                       // remove space for ", " that was added with last parameter and remove space that is going to be added for ", " after return type 
+                                                       // and add space for ") "
+                                                       resultLength -= 2;
+                                               } //else
+                                                       // remove space that is going to be added for ", " after return type 
+                                                       // and add space for ") "
+                                                       // -> noop
+                                               
+                                               // decrement param count because it is going to be added for return type
+                                               paramCount--;
+                                               continue signature;
+                                       } else {
+                                               if (paramCount > 0) {
+                                                       // remove space for ", " that was added with last parameter and add space for ")"
+                                                       resultLength--;
+                                               } else {
+                                                       // add space for ")"
+                                                       resultLength++;
+                                               }
+                                               break signature;
+                                       }
+                               default :
+                                       throw new IllegalArgumentException();
+                       }
+                       resultLength += 2; // add space for ", "
+                       paramCount++;
+               }
+               
+               // parameter names
+               int parameterNamesLength = parameterNames == null ? 0 : parameterNames.length;
+               for (int i = 0; i <parameterNamesLength; i++) {
+                       resultLength += parameterNames[i].length + 1; // parameter name + space
+               }
+               
+               // selector
+               int selectorLength = methodName == null ? 0 : methodName.length;
+               resultLength += selectorLength;
+               
+               // create resulting char array
+               char[] result = new char[resultLength];
+               
+               // returned type
+               int index = 0;
+               if (includeReturnType) {
+                       long pos = copyType(methodSignature, lastParen+1, result, index, fullyQualifyTypeNames);
+                       index = (int) (pos >>> 32);
+                       result[index++] = ' ';
+               }
+               
+               // selector
+               if (methodName != null) {
+                       System.arraycopy(methodName, 0, result, index, selectorLength);
+                       index += selectorLength;
+               }
+               
+               // parameters
+               result[index++] = C_PARAM_START;
+               int sigPos = firstParen+1;
+               for (int i = 0; i < paramCount; i++) {
+                       long pos = copyType(methodSignature, sigPos, result, index, fullyQualifyTypeNames);
+                       index = (int) (pos >>> 32);
+                       sigPos = (int)pos;
+                       if (parameterNames != null) {
+                               result[index++] = ' ';
+                               char[] parameterName = parameterNames[i];
+                               int paramLength = parameterName.length;
+                               System.arraycopy(parameterName, 0, result, index, paramLength);
+                               index += paramLength;
+                       }
+                       if (i != paramCount-1) {
+                               result[index++] = ',';
+                               result[index++] = ' ';
+                       }
+               }
+               if (sigPos >= sigLength) {
+                       throw new IllegalArgumentException(); // should be on last paren
+               }
+               result[index++] = C_PARAM_END;
+               
+               return result;
+       } catch (ArrayIndexOutOfBoundsException e) {
+               throw new IllegalArgumentException();
+       }               
+}
+/**
+ * Converts the given type signature to a readable string. The signature is expected to
+ * be dot-based.
+ * 
+ * <p>
+ * For example:
+ * <pre>
+ * <code>
+ * toString({'[', 'L', 'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'S', 't', 'r', 'i', 'n', 'g', ';'}) -> {'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'S', 't', 'r', 'i', 'n', 'g', '[', ']'}
+ * toString({'I'}) -> {'i', 'n', 't'}
+ * </code>
+ * </pre>
+ * </p>
+ * <p>
+ * Note: This method assumes that a type signature containing a <code>'$'</code>
+ * is an inner type signature. While this is correct in most cases, someone could 
+ * define a non-inner type name containing a <code>'$'</code>. Handling this 
+ * correctly in all cases would have required resolving the signature, which 
+ * generally not feasible.
+ * </p>
+ *
+ * @param signature the type signature
+ * @return the string representation of the type
+ * @exception IllegalArgumentException if the signature is not syntactically
+ *   correct
+ * 
+ * @since 2.0
+ */
+public static char[] toCharArray(char[] signature) throws IllegalArgumentException {
+       try {
+               int sigLength = signature.length;
+
+               if (sigLength == 0 || signature[0] == C_PARAM_START) {
+                       return toCharArray(signature, NO_CHAR, null, true, true);
+               }
+               
+               // compute result length
+               int resultLength = 0;
+               int index = -1;
+               while (signature[++index] == C_ARRAY) {
+                       resultLength += 2; // []
+               }
+               switch (signature[index]) {
+                       case C_BOOLEAN :
+                               resultLength += BOOLEAN.length;
+                               break;
+                       case C_BYTE :
+                               resultLength += BYTE.length;
+                               break;
+                       case C_CHAR :
+                               resultLength += CHAR.length;
+                               break;
+                       case C_DOUBLE :
+                               resultLength += DOUBLE.length;
+                               break;
+                       case C_FLOAT :
+                               resultLength += FLOAT.length;
+                               break;
+                       case C_INT :
+                               resultLength += INT.length;
+                               break;
+                       case C_LONG :
+                               resultLength += LONG.length;
+                               break;
+                       case C_SHORT :
+                               resultLength += SHORT.length;
+                               break;
+                       case C_VOID :
+                               resultLength += VOID.length;
+                               break;
+                       case C_RESOLVED :
+                       case C_UNRESOLVED :
+                               int end = CharOperation.indexOf(C_SEMICOLON, signature, index);
+                               if (end == -1) throw new IllegalArgumentException();
+                               int start = index + 1;
+                               resultLength += end-start;
+                               break;
+                       default :
+                               throw new IllegalArgumentException();
+               }
+               
+               char[] result = new char[resultLength];
+               copyType(signature, 0, result, 0, true);
+
+               /**
+                * Converts '$' separated type signatures into '.' separated type signature.
+                * NOTE: This assumes that the type signature is an inner type signature.
+                *       This is true in most cases, but someone can define a non-inner type 
+                *       name containing a '$'. However to tell the difference, we would have
+                *       to resolve the signature, which cannot be done at this point.
+                */
+               CharOperation.replace(result, C_DOLLAR, C_DOT);
+
+               return result;
+       } catch (ArrayIndexOutOfBoundsException e) {
+               throw new IllegalArgumentException();
+       }       
+}
+/**
+ * Converts the given array of qualified name segments to a qualified name.
+ * <p>
+ * For example:
+ * <pre>
+ * <code>
+ * toQualifiedName({{'j', 'a', 'v', 'a'}, {'l', 'a', 'n', 'g'}, {'O', 'b', 'j', 'e', 'c', 't'}}) -> {'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'O', 'b', 'j', 'e', 'c', 't'}
+ * toQualifiedName({{'O', 'b', 'j', 'e', 'c', 't'}}) -> {'O', 'b', 'j', 'e', 'c', 't'}
+ * toQualifiedName({{}}) -> {}
+ * </code>
+ * </pre>
+ * </p>
+ *
+ * @param segments the list of name segments, possibly empty
+ * @return the dot-separated qualified name, or the empty string
+ * 
+ * @since 2.0
+ */
+public static char[] toQualifiedName(char[][] segments) {
+       int length = segments.length;
+       if (length == 0) return NO_CHAR;
+       if (length == 1) return segments[0];
+       
+       int resultLength = 0;
+       for (int i = 0; i < length; i++) {
+               resultLength += segments[i].length+1;
+       }
+       resultLength--;
+       char[] result = new char[resultLength];
+       int index = 0;
+       for (int i = 0; i < length; i++) {
+               char[] segment = segments[i];
+               int segmentLength = segment.length;
+               System.arraycopy(segment, 0, result, index, segmentLength);
+               index += segmentLength;
+               if (i != length-1) {
+                       result[index++] = C_DOT;
+               }
+       }
+       return result;
+}
+/**
+ * Converts the given array of qualified name segments to a qualified name.
+ * <p>
+ * For example:
+ * <pre>
+ * <code>
+ * toQualifiedName(new String[] {"java", "lang", "Object"}) -> "java.lang.Object"
+ * toQualifiedName(new String[] {"Object"}) -> "Object"
+ * toQualifiedName(new String[0]) -> ""
+ * </code>
+ * </pre>
+ * </p>
+ *
+ * @param segments the list of name segments, possibly empty
+ * @return the dot-separated qualified name, or the empty string
+ */
+public static String toQualifiedName(String[] segments) {
+       int length = segments.length;
+       char[][] charArrays = new char[length][];
+       for (int i = 0; i < length; i++) {
+               charArrays[i] = segments[i].toCharArray();
+       }
+       return new String(toQualifiedName(charArrays));
+}
+/**
+ * Converts the given type signature to a readable string. The signature is expected to
+ * be dot-based.
+ * 
+ * <p>
+ * For example:
+ * <pre>
+ * <code>
+ * toString("[Ljava.lang.String;") -> "java.lang.String[]"
+ * toString("I") -> "int"
+ * </code>
+ * </pre>
+ * </p>
+ * <p>
+ * Note: This method assumes that a type signature containing a <code>'$'</code>
+ * is an inner type signature. While this is correct in most cases, someone could 
+ * define a non-inner type name containing a <code>'$'</code>. Handling this 
+ * correctly in all cases would have required resolving the signature, which 
+ * generally not feasible.
+ * </p>
+ *
+ * @param signature the type signature
+ * @return the string representation of the type
+ * @exception IllegalArgumentException if the signature is not syntactically
+ *   correct
+ */
+public static String toString(String signature) throws IllegalArgumentException {
+       return new String(toCharArray(signature.toCharArray()));
+}
+/**
+ * Converts the given method signature to a readable string. The method signature is expected to
+ * be dot-based.
+ * <p>
+ * For example:
+ * <pre>
+ * <code>
+ * toString("([Ljava.lang.String;)V", "main", new String[] {"args"}, false, true) -> "void main(String[] args)"
+ * </code>
+ * </pre>
+ * </p>
+ * 
+ * @param methodSignature the method signature to convert
+ * @param methodName the name of the method to insert in the result, or 
+ *   <code>null</code> if no method name is to be included
+ * @param parameterNames the parameter names to insert in the result, or 
+ *   <code>null</code> if no parameter names are to be included; if supplied,
+ *   the number of parameter names must match that of the method signature
+ * @param fullyQualifyTypeNames <code>true</code> if type names should be fully
+ *   qualified, and <code>false</code> to use only simple names
+ * @param includeReturnType <code>true</code> if the return type is to be
+ *   included
+ * @return the string representation of the method signature
+ */
+public static String toString(String methodSignature, String methodName, String[] parameterNames, boolean fullyQualifyTypeNames, boolean includeReturnType) {
+       char[][] params;
+       if (parameterNames == null) {
+               params = null;
+       } else {
+               int paramLength = parameterNames.length;
+               params = new char[paramLength][];
+               for (int i = 0; i < paramLength; i++) {
+                       params[i] = parameterNames[i].toCharArray();
+               }
+       }
+       return new String(toCharArray(methodSignature.toCharArray(), methodName == null ? null : methodName.toCharArray(), params, fullyQualifyTypeNames, includeReturnType));
+}
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/CompletionEngine.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/CompletionEngine.java
new file mode 100644 (file)
index 0000000..8d4ed79
--- /dev/null
@@ -0,0 +1,2702 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist;
+
+import java.util.*;
+
+import net.sourceforge.phpdt.core.compiler.InvalidInputException;
+import net.sourceforge.phpdt.internal.compiler.*;
+import net.sourceforge.phpdt.internal.compiler.env.*;
+
+import net.sourceforge.phpdt.internal.codeassist.impl.*;
+import net.sourceforge.phpdt.core.ICompletionRequestor;
+import net.sourceforge.phpdt.core.IType;
+//import net.sourceforge.phpdt.core.JavaCore;
+//import net.sourceforge.phpdt.core.JavaModelException;
+import net.sourceforge.phpdt.core.compiler.*;
+import net.sourceforge.phpdt.core.compiler.IProblem;
+import net.sourceforge.phpdt.internal.codeassist.complete.*;
+
+import net.sourceforge.phpdt.internal.compiler.ast.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+import net.sourceforge.phpdt.internal.compiler.parser.*;
+import net.sourceforge.phpdt.internal.compiler.problem.*;
+import net.sourceforge.phpdt.internal.compiler.util.*;
+import net.sourceforge.phpdt.internal.core.BasicCompilationUnit;
+import net.sourceforge.phpdt.internal.core.TypeConverter;
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+
+/**
+ * This class is the entry point for source completions.
+ * It contains two public APIs used to call CodeAssist on a given source with
+ * a given environment, assisting position and storage (and possibly options).
+ */
+public final class CompletionEngine
+       extends Engine
+       implements ISearchRequestor, TypeConstants , ITerminalSymbols , RelevanceConstants {
+       
+       public static boolean DEBUG = false;
+
+       private final static char[] ERROR_PATTERN = "*error*".toCharArray();  //$NON-NLS-1$
+       private final static char[] EXCEPTION_PATTERN = "*exception*".toCharArray();  //$NON-NLS-1$
+       private final static char[] SEMICOLON = new char[] { ';' };
+       TypeBinding[] expectedTypes;
+       
+       boolean assistNodeIsClass;
+       boolean assistNodeIsException;
+       boolean assistNodeIsInterface;
+       
+       CompletionParser parser;
+       ICompletionRequestor requestor;
+       ProblemReporter problemReporter;
+       char[] source;
+       char[] token;
+       boolean resolvingImports = false;
+       boolean insideQualifiedReference = false;
+       int startPosition, actualCompletionPosition, endPosition, offset;
+       HashtableOfObject knownPkgs = new HashtableOfObject(10);
+       HashtableOfObject knownTypes = new HashtableOfObject(10);
+       Scanner nameScanner;
+
+       /*
+               static final char[][] mainDeclarations =
+                       new char[][] {
+                               "package".toCharArray(),
+                               "import".toCharArray(),
+                               "abstract".toCharArray(),
+                               "final".toCharArray(),
+                               "public".toCharArray(),
+                               "class".toCharArray(),
+                               "interface".toCharArray()};
+       
+               static final char[][] modifiers = // may want field, method, type & member type modifiers
+                       new char[][] {
+                               "abstract".toCharArray(),
+                               "final".toCharArray(),
+                               "native".toCharArray(),
+                               "public".toCharArray(),
+                               "protected".toCharArray(),
+                               "private".toCharArray(),
+                               "static".toCharArray(),
+                               "strictfp".toCharArray(),
+                               "synchronized".toCharArray(),
+                               "transient".toCharArray(),
+                               "volatile".toCharArray()};
+       */
+       static final char[][] baseTypes = new char[][] { 
+               "boolean".toCharArray(), //$NON-NLS-1$
+               "byte".toCharArray(), //$NON-NLS-1$
+               "char".toCharArray(), //$NON-NLS-1$
+               "double".toCharArray(), //$NON-NLS-1$
+               "float".toCharArray(), //$NON-NLS-1$
+               "int".toCharArray(), //$NON-NLS-1$
+               "long".toCharArray(), //$NON-NLS-1$
+               "short".toCharArray(), //$NON-NLS-1$
+               "void".toCharArray(), //$NON-NLS-1$
+       };
+               
+       static final char[] classField = "class".toCharArray();  //$NON-NLS-1$
+       static final char[] lengthField = "length".toCharArray();  //$NON-NLS-1$
+       static final char[] THIS = "this".toCharArray();  //$NON-NLS-1$
+       static final char[] THROWS = "throws".toCharArray();  //$NON-NLS-1$
+       
+       static InvocationSite FakeInvocationSite = new InvocationSite(){
+               public boolean isSuperAccess(){ return false; }
+               public boolean isTypeAccess(){ return false; }
+               public void setActualReceiverType(ReferenceBinding receiverType) {}
+               public void setDepth(int depth){}
+               public void setFieldIndex(int depth){}
+       };
+
+       /**
+        * The CompletionEngine is responsible for computing source completions.
+        *
+        * It requires a searchable name environment, which supports some
+        * specific search APIs, and a requestor to feed back the results to a UI.
+        *
+        *  @param nameEnvironment net.sourceforge.phpdt.internal.codeassist.ISearchableNameEnvironment
+        *      used to resolve type/package references and search for types/packages
+        *      based on partial names.
+        *
+        *  @param requestor net.sourceforge.phpdt.internal.codeassist.ICompletionRequestor
+        *      since the engine might produce answers of various forms, the engine 
+        *      is associated with a requestor able to accept all possible completions.
+        *
+        *  @param settings java.util.Map
+        *              set of options used to configure the code assist engine.
+        */
+       public CompletionEngine(
+               ISearchableNameEnvironment nameEnvironment,
+               ICompletionRequestor requestor,
+               Map settings) {
+
+               super(settings);
+               this.requestor = requestor;
+               this.nameEnvironment = nameEnvironment;
+
+               problemReporter = new ProblemReporter(
+                               DefaultErrorHandlingPolicies.proceedWithAllProblems(),
+                               this.compilerOptions,
+                               new DefaultProblemFactory(Locale.getDefault()) {
+                                       public void record(IProblem problem, CompilationResult unitResult, ReferenceContext referenceContext) {
+                                               if (problem.isError() && (problem.getID() & IProblem.Syntax) != 0) {
+                                                       CompletionEngine.this.requestor.acceptError(problem);
+                                               }
+                                       }
+                               });
+               this.parser =
+                       new CompletionParser(problemReporter, this.compilerOptions.assertMode);
+               this.lookupEnvironment =
+                       new LookupEnvironment(this, this.compilerOptions, problemReporter, nameEnvironment);
+               this.nameScanner =
+                       new Scanner(false, false, false, this.compilerOptions.assertMode);
+       }
+
+       /**
+        * One result of the search consists of a new class.
+        *
+        * NOTE - All package and type names are presented in their readable form:
+        *    Package names are in the form "a.b.c".
+        *    Nested type names are in the qualified form "A.M".
+        *    The default package is represented by an empty array.
+        */
+       public void acceptClass(char[] packageName, char[] className, int modifiers) {
+
+               char[] fullyQualifiedName = CharOperation.concat(packageName, className, '.');
+               char[] completionName = fullyQualifiedName;
+               
+               if (this.knownTypes.containsKey(completionName)) return;
+
+               this.knownTypes.put(completionName, this);
+               
+               int relevance = R_DEFAULT;
+               if (resolvingImports) {
+                       completionName = CharOperation.concat(completionName, SEMICOLON);
+                       relevance += computeRelevanceForCaseMatching(token, fullyQualifiedName);
+               } else {
+                       if (!insideQualifiedReference) {
+                               if (mustQualifyType(packageName, className)) {
+                                       if (packageName == null || packageName.length == 0)
+                                               if (unitScope != null && unitScope.fPackage.compoundName != NoCharChar)
+                                                       return; // ignore types from the default package from outside it
+                               } else {
+                                       completionName = className;
+                               }
+                       }
+                       relevance += computeRelevanceForCaseMatching(token, className);
+                       relevance += computeRelevanceForExpectingType(packageName, className);
+                       relevance += computeRelevanceForClass();
+                       relevance += computeRelevanceForException(className);
+               }
+
+               requestor.acceptClass(
+                       packageName,
+                       className,
+                       completionName,
+                       modifiers,
+                       startPosition - offset,
+                       endPosition - offset,
+                       relevance);
+       }
+       
+       /**
+        * One result of the search consists of a new interface.
+        *
+        * NOTE - All package and type names are presented in their readable form:
+        *    Package names are in the form "a.b.c".
+        *    Nested type names are in the qualified form "A.I".
+        *    The default package is represented by an empty array.
+        */
+       public void acceptInterface(
+               char[] packageName,
+               char[] interfaceName,
+               int modifiers) {
+
+               char[] fullyQualifiedName = CharOperation.concat(packageName, interfaceName, '.');
+               char[] completionName = fullyQualifiedName;
+
+               if (this.knownTypes.containsKey(completionName)) return;
+
+               this.knownTypes.put(completionName, this);
+
+               int relevance = R_DEFAULT;
+               if (resolvingImports) {
+                       completionName = CharOperation.concat(completionName, new char[] { ';' });
+                       relevance += computeRelevanceForCaseMatching(token, fullyQualifiedName);
+               } else {
+                       if (!insideQualifiedReference) {
+                               if (mustQualifyType(packageName, interfaceName)) {
+                                       if (packageName == null || packageName.length == 0)
+                                               if (unitScope != null && unitScope.fPackage.compoundName != NoCharChar)
+                                                       return; // ignore types from the default package from outside it
+                               } else {
+                                       completionName = interfaceName;
+                               }
+                       }
+                       relevance += computeRelevanceForCaseMatching(token, interfaceName);
+                       relevance += computeRelevanceForExpectingType(packageName, interfaceName);
+                       relevance += computeRelevanceForInterface();
+               }
+               
+               requestor.acceptInterface(
+                       packageName,
+                       interfaceName,
+                       completionName,
+                       modifiers,
+                       startPosition - offset,
+                       endPosition - offset,
+                       relevance);
+       }
+
+       /**
+        * One result of the search consists of a new package.
+        *
+        * NOTE - All package names are presented in their readable form:
+        *    Package names are in the form "a.b.c".
+        *    The default package is represented by an empty array.
+        */
+       public void acceptPackage(char[] packageName) {
+
+               if (this.knownPkgs.containsKey(packageName)) return;
+
+               this.knownPkgs.put(packageName, this);
+               
+               int relevance = R_DEFAULT;
+               relevance += computeRelevanceForCaseMatching(token, packageName);
+
+               requestor.acceptPackage(
+                       packageName,
+                       resolvingImports
+                               ? CharOperation.concat(packageName, new char[] { '.', '*', ';' })
+                               : packageName,
+                       startPosition - offset,
+                       endPosition - offset,
+                       relevance);
+       }
+
+       /**
+        * One result of the search consists of a new type.
+        *
+        * NOTE - All package and type names are presented in their readable form:
+        *    Package names are in the form "a.b.c".
+        *    Nested type names are in the qualified form "A.M".
+        *    The default package is represented by an empty array.
+        */
+       public void acceptType(char[] packageName, char[] typeName) {
+
+               char[] fullyQualifiedName = CharOperation.concat(packageName, typeName, '.');
+               char[] completionName = fullyQualifiedName;
+               
+               if (this.knownTypes.containsKey(completionName)) return;
+
+               this.knownTypes.put(completionName, this);
+
+               int relevance = R_DEFAULT;
+               if (resolvingImports) {
+                       completionName = CharOperation.concat(completionName, new char[] { ';' });
+                       relevance += computeRelevanceForCaseMatching(token, fullyQualifiedName);
+               } else {
+                       if (!insideQualifiedReference) {
+                               if (mustQualifyType(packageName, typeName)) {
+                                       if (packageName == null || packageName.length == 0)
+                                               if (unitScope != null && unitScope.fPackage.compoundName != NoCharChar)
+                                                       return; // ignore types from the default package from outside it
+                               } else {
+                                       completionName = typeName;
+                               }
+                       }
+                       relevance += computeRelevanceForCaseMatching(token, typeName);
+                       relevance += computeRelevanceForExpectingType(packageName, typeName);
+               }
+               
+               requestor.acceptType(
+                       packageName,
+                       typeName,
+                       completionName,
+                       startPosition - offset,
+                       endPosition - offset,
+                       relevance);
+       }
+
+       private void complete(AstNode astNode, Binding qualifiedBinding, Scope scope) {
+
+               setSourceRange(astNode.sourceStart, astNode.sourceEnd);
+               
+               if(parser.assistNodeParent != null) {
+                       computeExpectedTypes(parser.assistNodeParent, scope);
+               }
+
+               // defaults... some nodes will change these
+               if (astNode instanceof CompletionOnFieldType) {
+
+                       CompletionOnFieldType field = (CompletionOnFieldType) astNode;
+                       CompletionOnSingleTypeReference type = (CompletionOnSingleTypeReference) field.type;
+                       token = type.token;
+                       setSourceRange(type.sourceStart, type.sourceEnd);
+                       //              findKeywords(token, modifiers, scope); // could be the start of a field, method or member type
+                       findTypesAndPackages(token, scope);
+                       
+                       if(!field.isLocalVariable && field.modifiers == CompilerModifiers.AccDefault) {
+                               findMethods(token,null,scope.enclosingSourceType(),scope,new ObjectVector(),false,false,true,null,null,false);
+                       }
+               } else {
+                       if(astNode instanceof CompletionOnMethodReturnType) {
+                               
+                               CompletionOnMethodReturnType method = (CompletionOnMethodReturnType) astNode;
+                               SingleTypeReference type = (CompletionOnSingleTypeReference) method.returnType;
+                               token = type.token;
+                               setSourceRange(type.sourceStart, type.sourceEnd);
+                               findTypesAndPackages(token, scope);
+                               
+                               if(method.modifiers == CompilerModifiers.AccDefault) {
+                                       findMethods(token,null,scope.enclosingSourceType(),scope,new ObjectVector(),false,false,true,null,null,false);
+                               }
+                       } else {
+                               
+                               if (astNode instanceof CompletionOnSingleNameReference) {
+       
+                                       token = ((CompletionOnSingleNameReference) astNode).token;
+                                       findVariablesAndMethods(
+                                               token,
+                                               scope,
+                                               (CompletionOnSingleNameReference) astNode,
+                                               scope);
+                                       // can be the start of a qualified type name
+                                       findTypesAndPackages(token, scope);
+       
+                               } else {
+       
+                                       if (astNode instanceof CompletionOnSingleTypeReference) {
+       
+                                               token = ((CompletionOnSingleTypeReference) astNode).token;
+                                               
+                                               assistNodeIsClass = astNode instanceof CompletionOnClassReference;
+                                               assistNodeIsException = astNode instanceof CompletionOnExceptionReference;
+                                               assistNodeIsInterface = astNode instanceof CompletionOnInterfaceReference;
+       
+                                               // can be the start of a qualified type name
+                                               if (qualifiedBinding == null) {
+                                                       findTypesAndPackages(token, scope);
+                                                       } else {
+                                                               findMemberTypes(
+                                                               token,
+                                                               (ReferenceBinding) qualifiedBinding,
+                                                               scope,
+                                                               scope.enclosingSourceType());
+                                               }
+                                       } else {
+                                               
+                                               if (astNode instanceof CompletionOnQualifiedNameReference) {
+       
+                                                       insideQualifiedReference = true;
+                                                       CompletionOnQualifiedNameReference ref =
+                                                               (CompletionOnQualifiedNameReference) astNode;
+                                                       token = ref.completionIdentifier;
+                                                       long completionPosition = ref.sourcePositions[ref.sourcePositions.length - 1];
+       
+                                                       if (qualifiedBinding instanceof VariableBinding) {
+       
+                                                               setSourceRange((int) (completionPosition >>> 32), (int) completionPosition);
+                                                               TypeBinding receiverType = ((VariableBinding) qualifiedBinding).type;
+                                                               if (receiverType != null) {
+                                                                       findFieldsAndMethods(token, receiverType, scope, ref, scope,false);
+                                                               }
+       
+                                                       } else {
+       
+                                                               if (qualifiedBinding instanceof ReferenceBinding) {
+       
+                                                                       ReferenceBinding receiverType = (ReferenceBinding) qualifiedBinding;
+                                                                       setSourceRange((int) (completionPosition >>> 32), (int) completionPosition);
+       
+                                                                       findMemberTypes(token, receiverType, scope, scope.enclosingSourceType());
+       
+                                                                       findClassField(token, (TypeBinding) qualifiedBinding, scope);
+       
+                                                                       findFields(
+                                                                               token,
+                                                                               receiverType,
+                                                                               scope,
+                                                                               new ObjectVector(),
+                                                                               new ObjectVector(),
+                                                                               true,
+                                                                               ref,
+                                                                               scope,
+                                                                               false);
+       
+                                                                       findMethods(
+                                                                               token,
+                                                                               null,
+                                                                               receiverType,
+                                                                               scope,
+                                                                               new ObjectVector(),
+                                                                               true,
+                                                                               false,
+                                                                               false,
+                                                                               ref,
+                                                                               scope,
+                                                                               false);
+       
+                                                               } else {
+       
+                                                                       if (qualifiedBinding instanceof PackageBinding) {
+       
+                                                                               setSourceRange(astNode.sourceStart, (int) completionPosition);
+                                                                               // replace to the end of the completion identifier
+                                                                               findTypesAndSubpackages(token, (PackageBinding) qualifiedBinding);
+                                                                       }
+                                                               }
+                                                       }
+       
+                                               } else {
+       
+                                                               if (astNode instanceof CompletionOnQualifiedTypeReference) {
+       
+                                                               insideQualifiedReference = true;
+                                                               
+                                                               assistNodeIsClass = astNode instanceof CompletionOnQualifiedClassReference;
+                                                               assistNodeIsException = astNode instanceof CompletionOnQualifiedExceptionReference;
+                                                               assistNodeIsInterface = astNode instanceof CompletionOnQualifiedInterfaceReference;
+                                                               
+                                                               CompletionOnQualifiedTypeReference ref =
+                                                                       (CompletionOnQualifiedTypeReference) astNode;
+                                                               token = ref.completionIdentifier;
+                                                               long completionPosition = ref.sourcePositions[ref.tokens.length];
+       
+                                                               // get the source positions of the completion identifier
+                                                               if (qualifiedBinding instanceof ReferenceBinding) {
+       
+                                                                       setSourceRange((int) (completionPosition >>> 32), (int) completionPosition);
+                                                                       findMemberTypes(
+                                                                               token,
+                                                                               (ReferenceBinding) qualifiedBinding,
+                                                                               scope,
+                                                                               scope.enclosingSourceType());
+       
+                                                               } else {
+       
+                                                                       if (qualifiedBinding instanceof PackageBinding) {
+       
+                                                                               setSourceRange(astNode.sourceStart, (int) completionPosition);
+                                                                               // replace to the end of the completion identifier
+                                                                               findTypesAndSubpackages(token, (PackageBinding) qualifiedBinding);
+                                                                       }
+                                                               }
+       
+                                                       } else {
+       
+                                                               if (astNode instanceof CompletionOnMemberAccess) {
+       
+                                                                       CompletionOnMemberAccess access = (CompletionOnMemberAccess) astNode;
+                                                                       long completionPosition = access.nameSourcePosition;
+                                                                       setSourceRange((int) (completionPosition >>> 32), (int) completionPosition);
+                                       
+                                                                       token = access.token;
+       
+                                                                       findFieldsAndMethods(
+                                                                               token,
+                                                                               (TypeBinding) qualifiedBinding,
+                                                                               scope,
+                                                                               access,
+                                                                               scope,
+                                                                               false);
+       
+                                                               } else {
+       
+                                                                       if (astNode instanceof CompletionOnMessageSend) {
+       
+                                                                               CompletionOnMessageSend messageSend = (CompletionOnMessageSend) astNode;
+                                                                               TypeBinding[] argTypes =
+                                                                                       computeTypes(messageSend.arguments, (BlockScope) scope);
+                                                                               token = messageSend.selector;
+                                                                               if (qualifiedBinding == null) {
+                                                                                       
+                                                                                       findImplicitMessageSends(token, argTypes, scope, messageSend, scope);
+                                                                               } else {
+       
+                                                                                       findMethods(
+                                                                                               token,
+                                                                                               argTypes,
+                                                                                               (ReferenceBinding) qualifiedBinding,
+                                                                                               scope,
+                                                                                               new ObjectVector(),
+                                                                                               false,
+                                                                                               true,
+                                                                                               false,
+                                                                                               messageSend,
+                                                                                               scope,
+                                                                                               false);
+                                                                               }
+       
+                                                                       } else {
+       
+                                                                               if (astNode instanceof CompletionOnExplicitConstructorCall) {
+       
+                                                                                       CompletionOnExplicitConstructorCall constructorCall =
+                                                                                               (CompletionOnExplicitConstructorCall) astNode;
+                                                                                       TypeBinding[] argTypes =
+                                                                                               computeTypes(constructorCall.arguments, (BlockScope) scope);
+                                                                                       findConstructors(
+                                                                                               (ReferenceBinding) qualifiedBinding,
+                                                                                               argTypes,
+                                                                                               scope,
+                                                                                               constructorCall,
+                                                                                               false);
+       
+                                                                               } else {
+       
+                                                                                       if (astNode instanceof CompletionOnQualifiedAllocationExpression) {
+       
+                                                                                               CompletionOnQualifiedAllocationExpression allocExpression =
+                                                                                                       (CompletionOnQualifiedAllocationExpression) astNode;
+                                                                                               TypeBinding[] argTypes =
+                                                                                                       computeTypes(allocExpression.arguments, (BlockScope) scope);
+                                                                                               
+                                                                                               ReferenceBinding ref = (ReferenceBinding) qualifiedBinding;
+                                                                                               if(ref.isClass()) {
+                                                                                                       if(!ref.isAbstract()) {
+                                                                                                               findConstructors(
+                                                                                                                       ref,
+                                                                                                                       argTypes,
+                                                                                                                       scope,
+                                                                                                                       allocExpression,
+                                                                                                                       false);
+                                                                                                       }
+                                                                                               }
+                                                                                               if(!ref.isFinal()){
+                                                                                                       findAnonymousType(
+                                                                                                               ref,
+                                                                                                               argTypes,
+                                                                                                               scope,
+                                                                                                               allocExpression);
+                                                                                               }
+       
+                                                                                       } else {
+       
+                                                                                               if (astNode instanceof CompletionOnClassLiteralAccess) {
+                                                                                                       CompletionOnClassLiteralAccess access = (CompletionOnClassLiteralAccess) astNode;
+                                                                                                       setSourceRange(access.classStart, access.sourceEnd);
+                                                                       
+                                                                                                       token = access.completionIdentifier;
+                                                                       
+                                                                                                       findClassField(token, (TypeBinding) qualifiedBinding, scope);
+                                                                                               } else {
+                                                                                                       if(astNode instanceof CompletionOnMethodName) {
+                                                                                                               CompletionOnMethodName method = (CompletionOnMethodName) astNode;
+                                                                                                                       
+                                                                                                               setSourceRange(method.sourceStart, method.selectorEnd);
+                                                                                                                       
+                                                                                                               FieldBinding[] fields = scope.enclosingSourceType().fields();
+                                                                                                               char[][] excludeNames = new char[fields.length][];
+                                                                                                               for(int i = 0 ; i < fields.length ; i++){
+                                                                                                                       excludeNames[i] = fields[i].name;
+                                                                                                               }
+                                                                                                               
+                                                                                                               token = method.selector;
+                                                                                                               
+                                                                                                               findVariableNames(token, method.returnType, excludeNames);
+                                                                                                       } else {
+                                                                                                               if (astNode instanceof CompletionOnFieldName) {
+                                                                                                                       CompletionOnFieldName field = (CompletionOnFieldName) astNode;
+                                                                                                                       
+                                                                                                                       FieldBinding[] fields = scope.enclosingSourceType().fields();
+                                                                                                                       char[][] excludeNames = new char[fields.length][];
+                                                                                                                       for(int i = 0 ; i < fields.length ; i++){
+                                                                                                                               excludeNames[i] = fields[i].name;
+                                                                                                                       }
+                                                                                                                       
+                                                                                                                       token = field.realName;
+                                                                                                                       
+                                                                                                                       findVariableNames(field.realName, field.type, excludeNames);
+                                                                                                               } else {
+                                                                                                                       if (astNode instanceof CompletionOnLocalName ||
+                                                                                                                               astNode instanceof CompletionOnArgumentName){
+                                                                                                                               LocalDeclaration variable = (LocalDeclaration) astNode;
+                                                                                                                               
+                                                                                                                               LocalVariableBinding[] locals = ((BlockScope)scope).locals;
+                                                                                                                               char[][] excludeNames = new char[locals.length][];
+                                                                                                                               int localCount = 0;
+                                                                                                                               for(int i = 0 ; i < locals.length ; i++){
+                                                                                                                                       if(locals[i] != null) {
+                                                                                                                                               excludeNames[localCount++] = locals[i].name;
+                                                                                                                                       }
+                                                                                                                               }
+                                                                                                                               System.arraycopy(excludeNames, 0, excludeNames = new char[localCount][], 0, localCount);
+                                                                                                                               
+                                                                                                                               if(variable instanceof CompletionOnLocalName){
+                                                                                                                                       token = ((CompletionOnLocalName) variable).realName;
+                                                                                                                               } else {
+                                                                                                                                       token = ((CompletionOnArgumentName) variable).realName;
+                                                                                                                               }
+                                                                                                                               findVariableNames(token, variable.type, excludeNames);
+                                                                                                                       }
+                                                                                                               }
+                                                                                                       }
+                                                                                               }
+                                                                                       }
+                                                                               }
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+       
+//     public void complete(IType type, char[] snippet, int position, char[][] localVariableTypeNames, char[][] localVariableNames, int[] localVariableModifiers, boolean isStatic){   
+//             TypeConverter converter = new TypeConverter();
+//             
+//             IType topLevelType = type;
+//             while(topLevelType.getDeclaringType() != null) {
+//                     topLevelType = topLevelType.getDeclaringType();
+//             }
+//             
+//             CompilationResult compilationResult = new CompilationResult((topLevelType.getElementName() + ".java").toCharArray(), 1, 1, this.compilerOptions.maxProblemsPerUnit); //$NON-NLS-1$
+//     
+//             CompilationUnitDeclaration compilationUnit = new CompilationUnitDeclaration(problemReporter, compilationResult, 0);
+//     
+//             try {
+//                     TypeDeclaration typeDeclaration = converter.buildTypeDeclaration(type, compilationUnit, compilationResult, problemReporter);
+//             
+//                     if(typeDeclaration != null) {   
+//                             // build AST from snippet
+//                             Initializer fakeInitializer = parseSnippeInitializer(snippet, position, localVariableTypeNames, localVariableNames, localVariableModifiers, isStatic);
+//                             
+//                             // merge AST
+//                             FieldDeclaration[] oldFields = typeDeclaration.fields;
+//                             FieldDeclaration[] newFields = new FieldDeclaration[oldFields.length + 1];
+//                             System.arraycopy(oldFields, 0, newFields, 0, oldFields.length);
+//                             newFields[oldFields.length] = fakeInitializer;
+//                             typeDeclaration.fields = newFields;
+//             
+//                             if(DEBUG) {
+//                                     System.out.println("SNIPPET COMPLETION AST :"); //$NON-NLS-1$
+//                                     System.out.println(compilationUnit.toString());
+//                             }
+//                             
+//                             if (compilationUnit.types != null) {
+//                                     try {
+//                                             lookupEnvironment.buildTypeBindings(compilationUnit);
+//                             
+//                                             if ((unitScope = compilationUnit.scope) != null) {
+//                                                     lookupEnvironment.completeTypeBindings(compilationUnit, true);
+//                                                     compilationUnit.scope.faultInTypes();
+//                                                     compilationUnit.resolve();
+//                                             }
+//                                     } catch (CompletionNodeFound e) {
+//                                             //                                      completionNodeFound = true;
+//                                             if (e.astNode != null) {
+//                                                     // if null then we found a problem in the completion node
+//                                                     complete(e.astNode, e.qualifiedBinding, e.scope);
+//                                             }
+//                                     }
+//                             }
+//                     }
+//             } catch(JavaModelException e) {
+//                     // Do nothing
+//             }
+//     }
+       
+//     private Initializer parseSnippeInitializer(char[] snippet, int position, char[][] localVariableTypeNames, char[][] localVariableNames, int[] localVariableModifiers, boolean isStatic){
+//             StringBuffer prefix = new StringBuffer();
+//             prefix.append("public class FakeType {\n "); //$NON-NLS-1$
+//             if(isStatic) {
+//                     prefix.append("static "); //$NON-NLS-1$
+//             }
+//             prefix.append("{\n"); //$NON-NLS-1$
+//             for (int i = 0; i < localVariableTypeNames.length; i++) {
+//                     prefix.append(AstNode.modifiersString(localVariableModifiers[i]));
+//                     prefix.append(' ');
+//                     prefix.append(localVariableTypeNames[i]);
+//                     prefix.append(' ');
+//                     prefix.append(localVariableNames[i]);
+//                     prefix.append(';');
+//             }
+//             
+//             char[] fakeSource = CharOperation.concat(prefix.toString().toCharArray(), snippet, "}}".toCharArray());//$NON-NLS-1$ 
+//             offset = prefix.length();
+//             
+//             String encoding = JavaCore.getOption(JavaCore.CORE_ENCODING);
+//             BasicCompilationUnit fakeUnit = new BasicCompilationUnit(
+//                     fakeSource, 
+//                     null,
+//                     "FakeType.java", //$NON-NLS-1$
+//                     encoding); 
+//                     
+//             actualCompletionPosition = prefix.length() + position - 1;
+//                     
+//             CompilationResult fakeResult = new CompilationResult(fakeUnit, 1, 1, this.compilerOptions.maxProblemsPerUnit);
+//             CompilationUnitDeclaration fakeAST = parser.dietParse(fakeUnit, fakeResult, actualCompletionPosition);
+//             
+//             parseMethod(fakeAST, actualCompletionPosition);
+//             
+//             return (Initializer)fakeAST.types[0].fields[0];
+//     }
+
+       /**
+        * Ask the engine to compute a completion at the specified position
+        * of the given compilation unit.
+        *
+        *  @return void
+        *      completion results are answered through a requestor.
+        *
+        *  @param sourceUnit net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit
+        *      the source of the current compilation unit.
+        *
+        *  @param completionPosition int
+        *      a position in the source where the completion is taking place. 
+        *      This position is relative to the source provided.
+        */
+       public void complete(ICompilationUnit sourceUnit, int completionPosition, int offset) {
+
+               if(DEBUG) {
+                       System.out.print("COMPLETION IN "); //$NON-NLS-1$
+                       System.out.print(sourceUnit.getFileName());
+                       System.out.print(" AT POSITION "); //$NON-NLS-1$
+                       System.out.println(completionPosition);
+                       System.out.println("COMPLETION - Source :"); //$NON-NLS-1$
+                       System.out.println(sourceUnit.getContents());
+               }
+               try {
+                       actualCompletionPosition = completionPosition - 1;
+                       this.offset = offset;
+                       // for now until we can change the UI.
+                       CompilationResult result = new CompilationResult(sourceUnit, 1, 1, this.compilerOptions.maxProblemsPerUnit);
+                       CompilationUnitDeclaration parsedUnit = parser.dietParse(sourceUnit, result, actualCompletionPosition);
+
+                       //              boolean completionNodeFound = false;
+                       if (parsedUnit != null) {
+                               if(DEBUG) {
+                                       System.out.println("COMPLETION - Diet AST :"); //$NON-NLS-1$
+                                       System.out.println(parsedUnit.toString());
+                               }
+
+                               // scan the package & import statements first
+                               if (parsedUnit.currentPackage instanceof CompletionOnPackageReference) {
+                                       findPackages((CompletionOnPackageReference) parsedUnit.currentPackage);
+                                       return;
+                               }
+
+                               ImportReference[] imports = parsedUnit.imports;
+                               if (imports != null) {
+                                       for (int i = 0, length = imports.length; i < length; i++) {
+                                               ImportReference importReference = imports[i];
+                                               if (importReference instanceof CompletionOnImportReference) {
+                                                       findImports((CompletionOnImportReference) importReference);
+                                                       return;
+                                               }
+                                       }
+                               }
+
+                               if (parsedUnit.types != null) {
+                                       try {
+                                               lookupEnvironment.buildTypeBindings(parsedUnit);
+
+                                               if ((unitScope = parsedUnit.scope) != null) {
+                                                       source = sourceUnit.getContents();
+                                                       lookupEnvironment.completeTypeBindings(parsedUnit, true);
+                                                       parsedUnit.scope.faultInTypes();
+                                                       parseMethod(parsedUnit, actualCompletionPosition);
+                                                       if(DEBUG) {
+                                                               System.out.println("COMPLETION - AST :"); //$NON-NLS-1$
+                                                               System.out.println(parsedUnit.toString());
+                                                       }
+                                                       parsedUnit.resolve();
+                                               }
+                                       } catch (CompletionNodeFound e) {
+                                               //                                      completionNodeFound = true;
+                                               if (e.astNode != null) {
+                                                       if(DEBUG) {
+                                                               System.out.print("COMPLETION - Completion node : "); //$NON-NLS-1$
+                                                               System.out.println(e.astNode.toString());
+                                                       }
+                                                       // if null then we found a problem in the completion node
+                                                       complete(e.astNode, e.qualifiedBinding, e.scope);
+                                               }
+                                       }
+                               }
+                       }
+
+                       /* Ignore package, import, class & interface keywords for now...
+                                       if (!completionNodeFound) {
+                                               if (parsedUnit == null || parsedUnit.types == null) {
+                                                       // this is not good enough... can still be trying to define a second type
+                                                       CompletionScanner scanner = (CompletionScanner) parser.scanner;
+                                                       setSourceRange(scanner.completedIdentifierStart, scanner.completedIdentifierEnd);
+                                                       findKeywords(scanner.completionIdentifier, mainDeclarations, null);
+                                               }
+                                               // currently have no way to know if extends/implements are possible keywords
+                                       }
+                       */
+               } catch (IndexOutOfBoundsException e) { // work-around internal failure - 1GEMF6D
+               } catch (InvalidCursorLocation e) { // may eventually report a usefull error
+               } catch (AbortCompilation e) { // ignore this exception for now since it typically means we cannot find java.lang.Object
+               } catch (CompletionNodeFound e){ // internal failure - bugs 5618
+               } finally {
+                       reset();
+               }
+       }
+
+       private TypeBinding[] computeTypes(Expression[] arguments, BlockScope scope) {
+
+               if (arguments == null)
+                       return null;
+
+               int argsLength = arguments.length;
+               TypeBinding[] argTypes = new TypeBinding[argsLength];
+               for (int a = argsLength; --a >= 0;)
+                       argTypes[a] = arguments[a].resolveType(scope);
+               return argTypes;
+       }
+       
+       private void findAnonymousType(
+               ReferenceBinding currentType,
+               TypeBinding[] argTypes,
+               Scope scope,
+               InvocationSite invocationSite) {
+
+               if (currentType.isInterface()) {
+                       char[] completion = TypeConstants.NoChar;
+                       // nothing to insert - do not want to replace the existing selector & arguments
+                       if (source == null
+                               || source.length <= endPosition
+                               || source[endPosition] != ')')
+                               completion = new char[] { ')' };
+                       
+                       requestor.acceptAnonymousType(
+                               currentType.qualifiedPackageName(),
+                               currentType.qualifiedSourceName(),
+                               TypeConstants.NoCharChar,
+                               TypeConstants.NoCharChar,
+                               TypeConstants.NoCharChar,
+                               completion,
+                               IConstants.AccPublic,
+                               endPosition - offset,
+                               endPosition - offset,
+                               R_DEFAULT);
+               } else {
+                       findConstructors(
+                               currentType,
+                               argTypes,
+                               scope,
+                               invocationSite,
+                               true);
+               }
+       }
+
+       private void findClassField(char[] token, TypeBinding receiverType, Scope scope) {
+
+               if (token == null)
+                       return;
+
+               if (token.length <= classField.length
+                       && CharOperation.prefixEquals(token, classField, false /* ignore case */
+               )) {
+                       int relevance = R_DEFAULT;
+                       relevance += computeRelevanceForCaseMatching(token, classField);
+                       relevance += computeRelevanceForExpectingType(scope.getJavaLangClass());
+                               
+                       requestor.acceptField(
+                               NoChar,
+                               NoChar,
+                               classField,
+                               NoChar,
+                               NoChar,
+                               classField,
+                               CompilerModifiers.AccStatic | CompilerModifiers.AccPublic,
+                               startPosition - offset,
+                               endPosition - offset,
+                               relevance);
+               }
+       }
+
+       private void findConstructors(
+               ReferenceBinding currentType,
+               TypeBinding[] argTypes,
+               Scope scope,
+               InvocationSite invocationSite,
+               boolean forAnonymousType) {
+
+               // No visibility checks can be performed without the scope & invocationSite
+               MethodBinding[] methods = currentType.availableMethods();
+               if(methods != null) {
+                       int minArgLength = argTypes == null ? 0 : argTypes.length;
+                       next : for (int f = methods.length; --f >= 0;) {
+                               MethodBinding constructor = methods[f];
+                               if (constructor.isConstructor()) {
+                                       
+                                       if (constructor.isSynthetic()) continue next;
+                                               
+                                       if (options.checkVisibility
+                                               && !constructor.canBeSeenBy(invocationSite, scope)) continue next;
+       
+                                       TypeBinding[] parameters = constructor.parameters;
+                                       int paramLength = parameters.length;
+                                       if (minArgLength > paramLength)
+                                               continue next;
+                                       for (int a = minArgLength; --a >= 0;)
+                                               if (argTypes[a] != null) // can be null if it could not be resolved properly
+                                                       if (!scope.areTypesCompatible(argTypes[a], constructor.parameters[a]))
+                                                               continue next;
+       
+                                       char[][] parameterPackageNames = new char[paramLength][];
+                                       char[][] parameterTypeNames = new char[paramLength][];
+                                       for (int i = 0; i < paramLength; i++) {
+                                               TypeBinding type = parameters[i];
+                                               parameterPackageNames[i] = type.qualifiedPackageName();
+                                               parameterTypeNames[i] = type.qualifiedSourceName();
+                                       }
+                                       char[][] parameterNames = findMethodParameterNames(constructor,parameterTypeNames);
+                                       
+                                       char[] completion = TypeConstants.NoChar;
+                                       // nothing to insert - do not want to replace the existing selector & arguments
+                                       if (source == null
+                                               || source.length <= endPosition
+                                               || source[endPosition] != ')')
+                                               completion = new char[] { ')' };
+                                       
+                                       if(forAnonymousType){
+                                               requestor.acceptAnonymousType(
+                                                       currentType.qualifiedPackageName(),
+                                                       currentType.qualifiedSourceName(),
+                                                       parameterPackageNames,
+                                                       parameterTypeNames,
+                                                       parameterNames,
+                                                       completion,
+                                                       constructor.modifiers,
+                                                       endPosition - offset,
+                                                       endPosition - offset,
+                                                       R_DEFAULT);
+                                       } else {
+                                               requestor.acceptMethod(
+                                                       currentType.qualifiedPackageName(),
+                                                       currentType.qualifiedSourceName(),
+                                                       currentType.sourceName(),
+                                                       parameterPackageNames,
+                                                       parameterTypeNames,
+                                                       parameterNames,
+                                                       TypeConstants.NoChar,
+                                                       TypeConstants.NoChar,
+                                                       completion,
+                                                       constructor.modifiers,
+                                                       endPosition - offset,
+                                                       endPosition - offset,
+                                                       R_DEFAULT);
+                                       }
+                               }
+                       }
+               }
+       }
+       
+       // Helper method for findFields(char[], ReferenceBinding, Scope, ObjectVector, boolean)
+       private void findFields(
+               char[] fieldName,
+               FieldBinding[] fields,
+               Scope scope,
+               ObjectVector fieldsFound,
+               ObjectVector localsFound,
+               boolean onlyStaticFields,
+               ReferenceBinding receiverType,
+               InvocationSite invocationSite,
+               Scope invocationScope,
+               boolean implicitCall) {
+
+               // Inherited fields which are hidden by subclasses are filtered out
+               // No visibility checks can be performed without the scope & invocationSite
+               
+               int fieldLength = fieldName.length;
+               next : for (int f = fields.length; --f >= 0;) {                 
+                       FieldBinding field = fields[f];
+
+                       if (field.isSynthetic())        continue next;
+
+                       if (onlyStaticFields && !field.isStatic()) continue next;
+
+                       if (fieldLength > field.name.length) continue next;
+
+                       if (!CharOperation.prefixEquals(fieldName, field.name, false /* ignore case */))        continue next;
+
+                       if (options.checkVisibility
+                               && !field.canBeSeenBy(receiverType, invocationSite, scope))     continue next;
+
+                       boolean prefixRequired = false;
+
+                       for (int i = fieldsFound.size; --i >= 0;) {
+                               Object[] other = (Object[])fieldsFound.elementAt(i);
+                               FieldBinding otherField = (FieldBinding) other[0];
+                               ReferenceBinding otherReceiverType = (ReferenceBinding) other[1];
+                               if (field == otherField && receiverType == otherReceiverType)
+                                       continue next;
+                               if (CharOperation.equals(field.name, otherField.name, true)) {
+                                       if (field.declaringClass.isSuperclassOf(otherField.declaringClass))
+                                               continue next;
+                                       if (otherField.declaringClass.isInterface())
+                                               if (field.declaringClass.implementsInterface(otherField.declaringClass, true))
+                                                       continue next;
+                                       if (field.declaringClass.isInterface())
+                                               if (otherField.declaringClass.implementsInterface(field.declaringClass, true))
+                                                       continue next;
+                                       prefixRequired = true;
+                               }
+                       }
+
+                       for (int l = localsFound.size; --l >= 0;) {
+                               LocalVariableBinding local = (LocalVariableBinding) localsFound.elementAt(l);   
+
+                               if (CharOperation.equals(field.name, local.name, true)) {
+                                       SourceTypeBinding declarationType = scope.enclosingSourceType();
+                                       if (declarationType.isAnonymousType() && declarationType != invocationScope.enclosingSourceType()) {
+                                               continue next;
+                                       }
+                                       prefixRequired = true;
+                                       break;
+                               }
+                       }
+                       
+                       fieldsFound.add(new Object[]{field, receiverType});
+                       
+                       char[] completion = field.name;
+                       
+                       if(prefixRequired || options.forceImplicitQualification){
+                               char[] prefix = computePrefix(scope.enclosingSourceType(), invocationScope.enclosingSourceType(), field.isStatic());
+                               completion = CharOperation.concat(prefix,completion,'.');
+                       }
+
+                       int relevance = R_DEFAULT;
+                       relevance += computeRelevanceForCaseMatching(fieldName, field.name);
+                       relevance += computeRelevanceForExpectingType(field.type);
+
+                       requestor
+                               .acceptField(
+                                       field.declaringClass.qualifiedPackageName(),
+                                       field.declaringClass.qualifiedSourceName(),
+                                       field.name,
+                                       field.type.qualifiedPackageName(),
+                                       field.type.qualifiedSourceName(),
+                                       completion,
+                       // may include some qualification to resolve ambiguities
+                       field.modifiers, startPosition - offset, endPosition - offset,
+                       relevance);
+               }
+       }
+
+       private void findFields(
+               char[] fieldName,
+               ReferenceBinding receiverType,
+               Scope scope,
+               ObjectVector fieldsFound,
+               ObjectVector localsFound,
+               boolean onlyStaticFields,
+               InvocationSite invocationSite,
+               Scope invocationScope,
+               boolean implicitCall) {
+
+               if (fieldName == null)
+                       return;
+
+               ReferenceBinding currentType = receiverType;
+               ReferenceBinding[][] interfacesToVisit = null;
+               int lastPosition = -1;
+               do {
+
+                       ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
+                       if (itsInterfaces != NoSuperInterfaces) {
+
+                               if (interfacesToVisit == null)
+                                       interfacesToVisit = new ReferenceBinding[5][];
+
+                               if (++lastPosition == interfacesToVisit.length)
+                                       System.arraycopy(
+                                               interfacesToVisit,
+                                               0,
+                                               interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
+                                               0,
+                                               lastPosition);
+                               interfacesToVisit[lastPosition] = itsInterfaces;
+                       }
+
+                       FieldBinding[] fields = currentType.availableFields();
+                       if(fields != null) {
+                               findFields(
+                                       fieldName,
+                                       fields,
+                                       scope,
+                                       fieldsFound,
+                                       localsFound,
+                                       onlyStaticFields,
+                                       receiverType,
+                                       invocationSite,
+                                       invocationScope,
+                                       implicitCall);
+                       }
+                       currentType = currentType.superclass();
+               } while (currentType != null);
+
+               if (interfacesToVisit != null) {
+                       for (int i = 0; i <= lastPosition; i++) {
+                               ReferenceBinding[] interfaces = interfacesToVisit[i];
+                               for (int j = 0, length = interfaces.length; j < length; j++) {
+
+                                       ReferenceBinding anInterface = interfaces[j];
+                                       if ((anInterface.tagBits & TagBits.InterfaceVisited) == 0) {
+                                               // if interface as not already been visited
+                                               anInterface.tagBits |= TagBits.InterfaceVisited;
+
+                                               FieldBinding[] fields = anInterface.availableFields();
+                                               if(fields !=  null) {
+                                                       findFields(
+                                                               fieldName,
+                                                               fields,
+                                                               scope,
+                                                               fieldsFound,
+                                                               localsFound,
+                                                               onlyStaticFields,
+                                                               receiverType,
+                                                               invocationSite,
+                                                               invocationScope,
+                                                               implicitCall);
+                                               }
+
+                                               ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
+                                               if (itsInterfaces != NoSuperInterfaces) {
+                                                       if (++lastPosition == interfacesToVisit.length)
+                                                               System.arraycopy(
+                                                                       interfacesToVisit,
+                                                                       0,
+                                                                       interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
+                                                                       0,
+                                                                       lastPosition);
+                                                       interfacesToVisit[lastPosition] = itsInterfaces;
+                                               }
+                                       }
+                               }
+                       }
+
+                       // bit reinitialization
+                       for (int i = 0; i <= lastPosition; i++) {
+                               ReferenceBinding[] interfaces = interfacesToVisit[i];
+                               for (int j = 0, length = interfaces.length; j < length; j++)
+                                       interfaces[j].tagBits &= ~TagBits.InterfaceVisited;
+                       }
+               }
+       }
+
+       private void findFieldsAndMethods(
+               char[] token,
+               TypeBinding receiverType,
+               Scope scope,
+               InvocationSite invocationSite,
+               Scope invocationScope,
+               boolean implicitCall) {
+
+               if (token == null)
+                       return;
+
+               if (receiverType.isBaseType())
+                       return; // nothing else is possible with base types
+
+               if (receiverType.isArrayType()) {
+                       if (token.length <= lengthField.length
+                               && CharOperation.prefixEquals(token, lengthField, false /* ignore case */
+                       )) {
+                               
+                               int relevance = R_DEFAULT;
+                               relevance += computeRelevanceForCaseMatching(token,lengthField);
+                               relevance += computeRelevanceForExpectingType(BaseTypes.IntBinding);
+                               
+                               requestor.acceptField(
+                                       NoChar,
+                                       NoChar,
+                                       lengthField,
+                                       NoChar,
+                                       NoChar,
+                                       lengthField,
+                                       CompilerModifiers.AccPublic,
+                                       startPosition - offset,
+                                       endPosition - offset,
+                                       relevance);
+                       }
+                       receiverType = scope.getJavaLangObject();
+               }
+
+               findFields(
+                       token,
+                       (ReferenceBinding) receiverType,
+                       scope,
+                       new ObjectVector(),
+                       new ObjectVector(),
+                       false,
+                       invocationSite,
+                       invocationScope,
+                       implicitCall);
+
+               findMethods(
+                       token,
+                       null,
+                       (ReferenceBinding) receiverType,
+                       scope,
+                       new ObjectVector(),
+                       false,
+                       false,
+                       false,
+                       invocationSite,
+                       invocationScope,
+                       implicitCall);
+       }
+
+       private void findImports(CompletionOnImportReference importReference) {
+               char[][] tokens = importReference.tokens;
+                       
+               char[] importName = CharOperation.concatWith(tokens, '.');
+               
+               if (importName.length == 0)
+                       return;
+                       
+               char[] lastToken = tokens[tokens.length - 1];
+               if(lastToken != null && lastToken.length == 0)
+                       importName = CharOperation.concat(importName, new char[]{'.'});
+
+               resolvingImports = true;
+               setSourceRange(
+                       importReference.sourceStart,
+                       importReference.declarationSourceEnd);
+                       
+               token =  importName;
+               // want to replace the existing .*;
+               nameEnvironment.findPackages(importName, this);
+               nameEnvironment.findTypes(importName, this);
+       }
+
+       // what about onDemand types? Ignore them since it does not happen!
+       // import p1.p2.A.*;
+       private void findKeywords(char[] keyword, char[][] choices, Scope scope) {
+
+               int length = keyword.length;
+               if (length > 0)
+                       for (int i = 0; i < choices.length; i++)
+                               if (length <= choices[i].length
+                                       && CharOperation.prefixEquals(keyword, choices[i], false /* ignore case */
+                               )){
+                                       int relevance = R_DEFAULT;
+                                       relevance += computeRelevanceForCaseMatching(keyword, choices[i]);
+                                       
+                                       requestor.acceptKeyword(choices[i], startPosition - offset, endPosition - offset,relevance);
+                               }
+       }
+
+       // Helper method for findMemberTypes(char[], ReferenceBinding, Scope)
+       private void findMemberTypes(
+               char[] typeName,
+               ReferenceBinding[] memberTypes,
+               ObjectVector typesFound,
+               ReferenceBinding receiverType,
+               SourceTypeBinding invocationType) {
+
+               // Inherited member types which are hidden by subclasses are filtered out
+               // No visibility checks can be performed without the scope & invocationSite
+               int typeLength = typeName.length;
+               next : for (int m = memberTypes.length; --m >= 0;) {
+                       ReferenceBinding memberType = memberTypes[m];
+                       //              if (!wantClasses && memberType.isClass()) continue next;
+                       //              if (!wantInterfaces && memberType.isInterface()) continue next;
+                       if (typeLength > memberType.sourceName.length)
+                               continue next;
+
+                       if (!CharOperation.prefixEquals(typeName, memberType.sourceName, false
+                               /* ignore case */
+                               ))
+                               continue next;
+
+                       if (options.checkVisibility
+                               && !memberType.canBeSeenBy(receiverType, invocationType))
+                               continue next;
+
+                       for (int i = typesFound.size; --i >= 0;) {
+                               ReferenceBinding otherType = (ReferenceBinding) typesFound.elementAt(i);
+
+                               if (memberType == otherType)
+                                       continue next;
+
+                               if (CharOperation.equals(memberType.sourceName, otherType.sourceName, true)) {
+
+                                       if (memberType.enclosingType().isSuperclassOf(otherType.enclosingType()))
+                                               continue next;
+
+                                       if (otherType.enclosingType().isInterface())
+                                               if (memberType.enclosingType()
+                                                       .implementsInterface(otherType.enclosingType(), true))
+                                                       continue next;
+
+                                       if (memberType.enclosingType().isInterface())
+                                               if (otherType.enclosingType()
+                                                       .implementsInterface(memberType.enclosingType(), true))
+                                                       continue next;
+                               }
+                       }
+
+                       typesFound.add(memberType);
+
+                       int relevance = R_DEFAULT;
+                       relevance += computeRelevanceForCaseMatching(typeName, memberType.sourceName);
+                       relevance += computeRelevanceForExpectingType(memberType);
+
+                       if (memberType.isClass()) {
+                               relevance += computeRelevanceForClass();
+                               requestor.acceptClass(
+                                       memberType.qualifiedPackageName(),
+                                       memberType.qualifiedSourceName(),
+                                       memberType.sourceName(),
+                                       memberType.modifiers,
+                                       startPosition - offset,
+                                       endPosition - offset,
+                                       relevance);
+
+                       } else {
+                               relevance += computeRelevanceForInterface();
+                               requestor.acceptInterface(
+                                       memberType.qualifiedPackageName(),
+                                       memberType.qualifiedSourceName(),
+                                       memberType.sourceName(),
+                                       memberType.modifiers,
+                                       startPosition - offset,
+                                       endPosition - offset,
+                                       relevance);
+                       }
+               }
+       }
+
+       private void findMemberTypes(
+               char[] typeName,
+               ReferenceBinding receiverType,
+               Scope scope,
+               SourceTypeBinding typeInvocation) {
+
+               ReferenceBinding currentType = receiverType;
+               if (typeName == null)
+                       return;
+
+               if (currentType.superInterfaces() == null)
+                       return; // we're trying to find a supertype
+
+               ObjectVector typesFound = new ObjectVector();
+               if (insideQualifiedReference
+                       || typeName.length == 0) { // do not search up the hierarchy
+
+                       findMemberTypes(
+                               typeName,
+                               currentType.memberTypes(),
+                               typesFound,
+                               receiverType,
+                               typeInvocation);
+                       return;
+               }
+
+               ReferenceBinding[][] interfacesToVisit = null;
+               int lastPosition = -1;
+
+               do {
+
+                       ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
+                       if (itsInterfaces != NoSuperInterfaces) {
+
+                               if (interfacesToVisit == null)
+                                       interfacesToVisit = new ReferenceBinding[5][];
+
+                               if (++lastPosition == interfacesToVisit.length)
+                                       System.arraycopy(
+                                               interfacesToVisit,
+                                               0,
+                                               interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
+                                               0,
+                                               lastPosition);
+                               interfacesToVisit[lastPosition] = itsInterfaces;
+                       }
+
+                       findMemberTypes(
+                               typeName,
+                               currentType.memberTypes(),
+                               typesFound,
+                               receiverType,
+                               typeInvocation);
+                       currentType = currentType.superclass();
+
+               } while (currentType != null);
+
+               if (interfacesToVisit != null) {
+                       for (int i = 0; i <= lastPosition; i++) {
+                               ReferenceBinding[] interfaces = interfacesToVisit[i];
+                               for (int j = 0, length = interfaces.length; j < length; j++) {
+
+                                       ReferenceBinding anInterface = interfaces[j];
+                                       if ((anInterface.tagBits & TagBits.InterfaceVisited) == 0) {
+                                               // if interface as not already been visited
+                                               anInterface.tagBits |= TagBits.InterfaceVisited;
+
+                                               findMemberTypes(
+                                                       typeName,
+                                                       anInterface.memberTypes(),
+                                                       typesFound,
+                                                       receiverType,
+                                                       typeInvocation);
+
+                                               ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
+                                               if (itsInterfaces != NoSuperInterfaces) {
+
+                                                       if (++lastPosition == interfacesToVisit.length)
+                                                               System.arraycopy(
+                                                                       interfacesToVisit,
+                                                                       0,
+                                                                       interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
+                                                                       0,
+                                                                       lastPosition);
+                                                       interfacesToVisit[lastPosition] = itsInterfaces;
+                                               }
+                                       }
+                               }
+                       }
+
+                       // bit reinitialization
+                       for (int i = 0; i <= lastPosition; i++) {
+                               ReferenceBinding[] interfaces = interfacesToVisit[i];
+                               for (int j = 0, length = interfaces.length; j < length; j++)
+                                       interfaces[j].tagBits &= ~TagBits.InterfaceVisited;
+                       }
+               }
+       }
+
+       private void findIntefacesMethods(
+               char[] selector,
+               TypeBinding[] argTypes,
+               ReferenceBinding receiverType,
+               ReferenceBinding[] itsInterfaces,
+               Scope scope,
+               ObjectVector methodsFound,
+               boolean onlyStaticMethods,
+               boolean exactMatch,
+               boolean isCompletingDeclaration,
+               InvocationSite invocationSite,
+               Scope invocationScope,
+               boolean implicitCall) {
+
+               if (selector == null)
+                       return;
+
+               if (itsInterfaces != NoSuperInterfaces) {
+                       ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
+                       int lastPosition = 0;
+                       interfacesToVisit[lastPosition] = itsInterfaces;
+                       
+                       for (int i = 0; i <= lastPosition; i++) {
+                               ReferenceBinding[] interfaces = interfacesToVisit[i];
+
+                               for (int j = 0, length = interfaces.length; j < length; j++) {
+                                       ReferenceBinding currentType = interfaces[j];
+
+                                       if ((currentType.tagBits & TagBits.InterfaceVisited) == 0) {
+                                               // if interface as not already been visited
+                                               currentType.tagBits |= TagBits.InterfaceVisited;
+
+                                               MethodBinding[] methods = currentType.availableMethods();
+                                               if(methods != null) {
+                                                       if(isCompletingDeclaration){
+       
+                                                               findLocalMethodDeclarations(
+                                                                       selector,
+                                                                       methods,
+                                                                       scope,
+                                                                       methodsFound,
+                                                                       onlyStaticMethods,
+                                                                       exactMatch,
+                                                                       receiverType);
+       
+                                                       } else {
+       
+                                                               findLocalMethods(
+                                                                       selector,
+                                                                       argTypes,
+                                                                       methods,
+                                                                       scope,
+                                                                       methodsFound,
+                                                                       onlyStaticMethods,
+                                                                       exactMatch,
+                                                                       receiverType,
+                                                                       invocationSite,
+                                                                       invocationScope,
+                                                                       implicitCall);
+                                                       }
+                                               }
+
+                                               itsInterfaces = currentType.superInterfaces();
+                                               if (itsInterfaces != NoSuperInterfaces) {
+
+                                                       if (++lastPosition == interfacesToVisit.length)
+                                                               System.arraycopy(
+                                                                       interfacesToVisit,
+                                                                       0,
+                                                                       interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
+                                                                       0,
+                                                                       lastPosition);
+                                                       interfacesToVisit[lastPosition] = itsInterfaces;
+                                               }
+                                       }
+                               }
+                       }
+
+                       // bit reinitialization
+                       for (int i = 0; i <= lastPosition; i++) {
+                               ReferenceBinding[] interfaces = interfacesToVisit[i];
+
+                               for (int j = 0, length = interfaces.length; j < length; j++){
+                                       interfaces[j].tagBits &= ~TagBits.InterfaceVisited;
+                               }
+                       }
+               }
+       }
+       
+       private void findImplicitMessageSends(
+               char[] token,
+               TypeBinding[] argTypes,
+               Scope scope,
+               InvocationSite invocationSite,
+               Scope invocationScope) {
+
+               if (token == null)
+                       return;
+
+               boolean staticsOnly = false;
+               // need to know if we're in a static context (or inside a constructor)
+               ObjectVector methodsFound = new ObjectVector();
+
+               done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
+
+                       switch (scope.kind) {
+
+                               case Scope.METHOD_SCOPE :
+                                       // handle the error case inside an explicit constructor call (see MethodScope>>findField)
+                                       MethodScope methodScope = (MethodScope) scope;
+                                       staticsOnly |= methodScope.isStatic | methodScope.isConstructorCall;
+                                       break;
+
+                               case Scope.CLASS_SCOPE :
+                                       ClassScope classScope = (ClassScope) scope;
+                                       SourceTypeBinding enclosingType = classScope.referenceContext.binding;
+                                       findMethods(
+                                               token,
+                                               argTypes,
+                                               enclosingType,
+                                               classScope,
+                                               methodsFound,
+                                               staticsOnly,
+                                               true,
+                                               false,
+                                               invocationSite,
+                                               invocationScope,
+                                               true);
+                                       staticsOnly |= enclosingType.isStatic();
+                                       break;
+
+                               case Scope.COMPILATION_UNIT_SCOPE :
+                                       break done;
+                       }
+                       scope = scope.parent;
+               }
+       }
+
+       // Helper method for findMethods(char[], TypeBinding[], ReferenceBinding, Scope, ObjectVector, boolean, boolean, boolean)
+       private void findLocalMethods(
+               char[] methodName,
+               TypeBinding[] argTypes,
+               MethodBinding[] methods,
+               Scope scope,
+               ObjectVector methodsFound,
+               boolean onlyStaticMethods,
+               boolean exactMatch,
+               ReferenceBinding receiverType,
+               InvocationSite invocationSite,
+               Scope invocationScope,
+               boolean implicitCall) {
+
+               // Inherited methods which are hidden by subclasses are filtered out
+               // No visibility checks can be performed without the scope & invocationSite
+
+               int methodLength = methodName.length;
+               int minArgLength = argTypes == null ? 0 : argTypes.length;
+
+               next : for (int f = methods.length; --f >= 0;) {
+                       MethodBinding method = methods[f];
+
+                       if (method.isSynthetic()) continue next;
+
+                       if (method.isDefaultAbstract()) continue next;
+
+                       if (method.isConstructor()) continue next;
+
+                       //              if (noVoidReturnType && method.returnType == BaseTypes.VoidBinding) continue next;
+                       if (onlyStaticMethods && !method.isStatic()) continue next;
+
+                       if (options.checkVisibility
+                               && !method.canBeSeenBy(receiverType, invocationSite, scope)) continue next;
+
+                       if (exactMatch) {
+                               if (!CharOperation.equals(methodName, method.selector, false /* ignore case */
+                                       ))
+                                       continue next;
+
+                       } else {
+
+                               if (methodLength > method.selector.length)
+                                       continue next;
+
+                               if (!CharOperation.prefixEquals(methodName, method.selector, false
+                                       /* ignore case */
+                                       ))
+                                       continue next;
+                       }
+                       if (minArgLength > method.parameters.length)
+                               continue next;
+
+                       for (int a = minArgLength; --a >= 0;){
+                               if (argTypes[a] != null){ // can be null if it could not be resolved properly
+                                       if (!scope.areTypesCompatible(argTypes[a], method.parameters[a])) {
+                                               continue next;
+                                       }
+                               }
+                       }
+                       
+                       boolean prefixRequired = false;
+                       
+                       for (int i = methodsFound.size; --i >= 0;) {
+                               Object[] other = (Object[]) methodsFound.elementAt(i);
+                               MethodBinding otherMethod = (MethodBinding) other[0];
+                               ReferenceBinding otherReceiverType = (ReferenceBinding) other[1];
+                               if (method == otherMethod && receiverType == otherReceiverType)
+                                       continue next;
+
+                               if (CharOperation.equals(method.selector, otherMethod.selector, true)
+                                       && method.areParametersEqual(otherMethod)) {
+
+                                       if (method.declaringClass.isSuperclassOf(otherMethod.declaringClass))
+                                               continue next;
+
+                                       if (otherMethod.declaringClass.isInterface())
+                                               if (method
+                                                       .declaringClass
+                                                       .implementsInterface(otherMethod.declaringClass, true))
+                                                       continue next;
+
+                                       if (method.declaringClass.isInterface())
+                                               if(otherMethod
+                                                       .declaringClass
+                                                       .implementsInterface(method.declaringClass,true))
+                                                       continue next;
+                                       prefixRequired = true;
+                               }
+                       }
+
+                       methodsFound.add(new Object[]{method, receiverType});
+                       int length = method.parameters.length;
+                       char[][] parameterPackageNames = new char[length][];
+                       char[][] parameterTypeNames = new char[length][];
+
+                       for (int i = 0; i < length; i++) {
+                               TypeBinding type = method.parameters[i];
+                               parameterPackageNames[i] = type.qualifiedPackageName();
+                               parameterTypeNames[i] = type.qualifiedSourceName();
+                       }
+                       char[][] parameterNames = findMethodParameterNames(method,parameterTypeNames);
+
+                       char[] completion = TypeConstants.NoChar;
+                       
+                       int previousStartPosition = startPosition;
+                       
+                       // nothing to insert - do not want to replace the existing selector & arguments
+                       if (!exactMatch) {
+                               if (source != null
+                                       && source.length > endPosition
+                                       && source[endPosition] == '(')
+                                       completion = method.selector;
+                               else
+                                       completion = CharOperation.concat(method.selector, new char[] { '(', ')' });
+                       } else {
+                               if(prefixRequired && (source != null)) {
+                                       completion = CharOperation.subarray(source, startPosition, endPosition);
+                               } else {
+                                       startPosition = endPosition;
+                               }
+                       }
+                       
+                       if(prefixRequired || options.forceImplicitQualification){
+                               char[] prefix = computePrefix(scope.enclosingSourceType(), invocationScope.enclosingSourceType(), method.isStatic());
+                               completion = CharOperation.concat(prefix,completion,'.');
+                       }
+
+                       int relevance = R_DEFAULT;
+                       relevance += computeRelevanceForCaseMatching(methodName, method.selector);
+                       relevance += computeRelevanceForExpectingType(method.returnType);
+
+                       requestor.acceptMethod(
+                               method.declaringClass.qualifiedPackageName(),
+                               method.declaringClass.qualifiedSourceName(),
+                               method.selector,
+                               parameterPackageNames,
+                               parameterTypeNames,
+                               parameterNames,
+                               method.returnType.qualifiedPackageName(),
+                               method.returnType.qualifiedSourceName(),
+                               completion,
+                               method.modifiers,
+                               startPosition - offset,
+                               endPosition - offset,
+                               relevance);
+                       startPosition = previousStartPosition;
+               }
+       }
+       
+       private int computeRelevanceForCaseMatching(char[] token, char[] proposalName){
+               if (CharOperation.prefixEquals(token, proposalName, true /* do not ignore case */)) {
+                       return  R_CASE;
+               } else {
+                       return R_DEFAULT;
+               }
+       }
+       private int computeRelevanceForClass(){
+               if(assistNodeIsClass) {
+                       return R_CLASS;
+               }
+               return 0;
+       }
+       private int computeRelevanceForInterface(){
+               if(assistNodeIsInterface) {
+                       return R_INTERFACE;
+               }
+               return R_DEFAULT;
+       }
+       private int computeRelevanceForException(char[] proposalName){
+               
+               if(assistNodeIsException &&
+                       (CharOperation.match(EXCEPTION_PATTERN, proposalName, false) ||
+                       CharOperation.match(ERROR_PATTERN, proposalName, false))) { 
+                       return R_EXCEPTION;
+               }
+               return R_DEFAULT;
+       }
+       private int computeRelevanceForExpectingType(TypeBinding proposalType){
+               if(expectedTypes != null && proposalType != null) {
+                       for (int i = 0; i < expectedTypes.length; i++) {
+                               if(Scope.areTypesCompatible(proposalType, expectedTypes[i])) {
+                                       return R_EXPECTED_TYPE;
+                               }
+                       }
+               } 
+               return R_DEFAULT;
+       }
+       private int computeRelevanceForExpectingType(char[] packageName, char[] typeName){
+               if(expectedTypes != null) {
+                       for (int i = 0; i < expectedTypes.length; i++) {
+                               if(CharOperation.equals(expectedTypes[i].qualifiedPackageName(), packageName) &&
+                                       CharOperation.equals(expectedTypes[i].qualifiedSourceName(), typeName)) {
+                                       return R_EXPECTED_TYPE;
+                               }
+                       }
+               } 
+               return R_DEFAULT;
+       }
+
+       // Helper method for findMethods(char[], MethodBinding[], Scope, ObjectVector, boolean, boolean, boolean, TypeBinding)
+       private void findLocalMethodDeclarations(
+               char[] methodName,
+               MethodBinding[] methods,
+               Scope scope,
+               ObjectVector methodsFound,
+               //      boolean noVoidReturnType, how do you know?
+               boolean onlyStaticMethods,
+               boolean exactMatch,
+               ReferenceBinding receiverType) {
+
+               // Inherited methods which are hidden by subclasses are filtered out
+               // No visibility checks can be performed without the scope & invocationSite
+               int methodLength = methodName.length;
+               next : for (int f = methods.length; --f >= 0;) {
+
+                       MethodBinding method = methods[f];
+                       if (method.isSynthetic())       continue next;
+                               
+                       if (method.isDefaultAbstract()) continue next;
+                       
+                       if (method.isConstructor()) continue next;
+                               
+                       if (method.isFinal()) continue next;
+
+                       //              if (noVoidReturnType && method.returnType == BaseTypes.VoidBinding) continue next;
+                       if (onlyStaticMethods && !method.isStatic()) continue next;
+
+                       if (options.checkVisibility
+                               && !method.canBeSeenBy(receiverType, FakeInvocationSite , scope)) continue next;
+
+                       if (exactMatch) {
+                               if (!CharOperation.equals(methodName, method.selector, false /* ignore case */
+                                       ))
+                                       continue next;
+
+                       } else {
+
+                               if (methodLength > method.selector.length)
+                                       continue next;
+
+                               if (!CharOperation.prefixEquals(methodName, method.selector, false
+                                       /* ignore case */
+                                       ))
+                                       continue next;
+                       }
+
+                       for (int i = methodsFound.size; --i >= 0;) {
+                               MethodBinding otherMethod = (MethodBinding) methodsFound.elementAt(i);
+                               if (method == otherMethod)
+                                       continue next;
+
+                               if (CharOperation.equals(method.selector, otherMethod.selector, true)
+                                       && method.areParametersEqual(otherMethod)) {
+                                       continue next;
+                               }
+                       }
+
+                       methodsFound.add(method);
+                       
+                       int length = method.parameters.length;
+                       char[][] parameterPackageNames = new char[length][];
+                       char[][] parameterTypeNames = new char[length][];
+                       
+                       for (int i = 0; i < length; i++) {
+                               TypeBinding type = method.parameters[i];
+                               parameterPackageNames[i] = type.qualifiedPackageName();
+                               parameterTypeNames[i] = type.qualifiedSourceName();
+                       }
+
+                       char[][] parameterNames = findMethodParameterNames(method,parameterTypeNames);
+                       
+                       StringBuffer completion = new StringBuffer(10);
+                       // flush uninteresting modifiers
+                       int insertedModifiers = method.modifiers & ~(CompilerModifiers.AccNative | CompilerModifiers.AccAbstract);
+
+                       if (!exactMatch) {
+                               if(insertedModifiers != CompilerModifiers.AccDefault){
+                                       completion.append(AstNode.modifiersString(insertedModifiers));
+                               }
+                               char[] returnPackageName = method.returnType.qualifiedPackageName();
+                               char[] returnTypeName = method.returnType.qualifiedSourceName();
+                               if(mustQualifyType(returnPackageName, returnTypeName)) {
+                                       completion.append(CharOperation.concat(returnPackageName, returnTypeName,'.'));
+                               } else {
+                                       completion.append(method.returnType.sourceName());
+                               }
+                               completion.append(' ');
+                               completion.append(method.selector);
+                               completion.append('(');
+
+                               for(int i = 0; i < length ; i++){
+                                       if(mustQualifyType(parameterPackageNames[i], parameterTypeNames[i])){
+                                               completion.append(CharOperation.concat(parameterPackageNames[i], parameterTypeNames[i], '.'));
+                                       } else {
+                                               completion.append(parameterTypeNames[i]);
+                                       }
+                                       completion.append(' ');
+                                       if(parameterNames != null){
+                                               completion.append(parameterNames[i]);
+                                       } else {
+                                               completion.append('%');
+                                       }
+                                       if(i != (length - 1))
+                                               completion.append(','); 
+                               }
+                               completion.append(')');
+                               
+                               ReferenceBinding[] exceptions = method.thrownExceptions;
+                               
+                               if (exceptions != null && exceptions.length > 0){
+                                       completion.append(' ');
+                                       completion.append(THROWS);
+                                       completion.append(' ');
+                                       for(int i = 0; i < exceptions.length ; i++){
+                                               ReferenceBinding exception = exceptions[i];
+
+                                               char[] exceptionPackageName = exception.qualifiedPackageName();
+                                               char[] exceptionTypeName = exception.qualifiedSourceName();
+                                               
+                                               if(i != 0){
+                                                       completion.append(',');
+                                                       completion.append(' ');
+                                               }
+                                               
+                                               if(mustQualifyType(exceptionPackageName, exceptionTypeName)){
+                                                       completion.append(CharOperation.concat(exceptionPackageName, exceptionTypeName, '.'));
+                                               } else {
+                                                       completion.append(exception.sourceName());
+                                               }
+                                       }
+                               }
+                       }
+
+                       int relevance = R_DEFAULT;
+                       relevance += computeRelevanceForCaseMatching(methodName, method.selector);
+
+                       requestor.acceptMethodDeclaration(
+                               method.declaringClass.qualifiedPackageName(),
+                               method.declaringClass.qualifiedSourceName(),
+                               method.selector,
+                               parameterPackageNames,
+                               parameterTypeNames,
+                               parameterNames,
+                               method.returnType.qualifiedPackageName(),
+                               method.returnType.qualifiedSourceName(),
+                               completion.toString().toCharArray(),
+                               method.modifiers,
+                               startPosition - offset,
+                               endPosition - offset,
+                               relevance);
+               }
+       }
+       private void findMethods(
+               char[] selector,
+               TypeBinding[] argTypes,
+               ReferenceBinding receiverType,
+               Scope scope,
+               ObjectVector methodsFound,
+               boolean onlyStaticMethods,
+               boolean exactMatch,
+               boolean isCompletingDeclaration,
+               InvocationSite invocationSite,
+               Scope invocationScope,
+               boolean implicitCall) {
+               if (selector == null)
+                       return;
+               
+               if(isCompletingDeclaration) {
+                       MethodBinding[] methods = receiverType.availableMethods();
+                       if (methods != null){
+                               for (int i = 0; i < methods.length; i++) {
+                                       if(!methods[i].isDefaultAbstract()) {
+                                               methodsFound.add(methods[i]);
+                                       }
+                               }
+                       }
+               }
+               
+               ReferenceBinding currentType = receiverType;
+               if (receiverType.isInterface()) {
+                       if(isCompletingDeclaration) {
+                               findIntefacesMethods(
+                                       selector,
+                                       argTypes,
+                                       receiverType,
+                                       currentType.superInterfaces(),
+                                       scope,
+                                       methodsFound,
+                                       onlyStaticMethods,
+                                       exactMatch,
+                                       isCompletingDeclaration,
+                                       invocationSite,
+                                       invocationScope,
+                                       implicitCall);
+                       } else {
+                               findIntefacesMethods(
+                                       selector,
+                                       argTypes,
+                                       receiverType,
+                                       new ReferenceBinding[]{currentType},
+                                       scope,
+                                       methodsFound,
+                                       onlyStaticMethods,
+                                       exactMatch,
+                                       isCompletingDeclaration,
+                                       invocationSite,
+                                       invocationScope,
+                                       implicitCall);
+                       }
+                       
+                       currentType = scope.getJavaLangObject();
+               } else {
+                       if(isCompletingDeclaration){
+                               findIntefacesMethods(
+                                       selector,
+                                       argTypes,
+                                       receiverType,
+                                       currentType.superInterfaces(),
+                                       scope,
+                                       methodsFound,
+                                       onlyStaticMethods,
+                                       exactMatch,
+                                       isCompletingDeclaration,
+                                       invocationSite,
+                                       invocationScope,
+                                       implicitCall);
+                               
+                               currentType = receiverType.superclass();
+                       }
+               }
+               boolean hasPotentialDefaultAbstractMethods = true;
+               while (currentType != null) {
+                       
+                       MethodBinding[] methods = currentType.availableMethods();
+                       if(methods != null) {
+                               if(isCompletingDeclaration){
+                                       findLocalMethodDeclarations(
+                                               selector,
+                                               methods,
+                                               scope,
+                                               methodsFound,
+                                               onlyStaticMethods,
+                                               exactMatch,
+                                               receiverType);
+                               } else{
+                                       findLocalMethods(
+                                               selector,
+                                               argTypes,
+                                               methods,
+                                               scope,
+                                               methodsFound,
+                                               onlyStaticMethods,
+                                               exactMatch,
+                                               receiverType,
+                                               invocationSite,
+                                               invocationScope,
+                                               implicitCall);
+                               }
+                       }
+                       
+                       if(hasPotentialDefaultAbstractMethods && currentType.isAbstract()){
+                               findIntefacesMethods(
+                                       selector,
+                                       argTypes,
+                                       receiverType,
+                                       currentType.superInterfaces(),
+                                       scope,
+                                       methodsFound,
+                                       onlyStaticMethods,
+                                       exactMatch,
+                                       isCompletingDeclaration,
+                                       invocationSite,
+                                       invocationScope,
+                                       implicitCall);
+                       } else {
+                               hasPotentialDefaultAbstractMethods = false;
+                       }
+                       currentType = currentType.superclass();
+               }
+       }
+       private char[][] findMethodParameterNames(MethodBinding method, char[][] parameterTypeNames){
+               ReferenceBinding bindingType = method.declaringClass;
+
+               char[][] parameterNames = null;
+               
+               int length = parameterTypeNames.length;
+
+               if (length == 0){
+                       return TypeConstants.NoCharChar;
+               }
+               // look into the corresponding unit if it is available
+               if (bindingType instanceof SourceTypeBinding){
+                       SourceTypeBinding sourceType = (SourceTypeBinding) bindingType;
+
+                       if (sourceType.scope != null){
+                               TypeDeclaration parsedType;
+
+                               if ((parsedType = sourceType.scope.referenceContext) != null){
+                                       AbstractMethodDeclaration methodDecl = parsedType.declarationOf(method);
+
+                                       if (methodDecl != null){
+                                               Argument[] arguments = methodDecl.arguments;
+                                               parameterNames = new char[length][];
+
+                                               for(int i = 0 ; i < length ; i++){
+                                                       parameterNames[i] = arguments[i].name;
+                                               }
+                                       }
+                               }
+                       }
+               }
+               // look into the model          
+               if(parameterNames == null){
+                       NameEnvironmentAnswer answer = nameEnvironment.findType(bindingType.compoundName);
+
+                       if(answer != null){
+                               if(answer.isSourceType()) {
+                                       ISourceType sourceType = answer.getSourceTypes()[0];
+                                       ISourceMethod[] sourceMethods = sourceType.getMethods();
+                                       int len = sourceMethods == null ? 0 : sourceMethods.length;
+                                       for(int i = 0; i < len ; i++){
+                                               ISourceMethod sourceMethod = sourceMethods[i];
+                                               char[][] argTypeNames = sourceMethod.getArgumentTypeNames();
+
+                                               if(argTypeNames != null &&
+                                                       CharOperation.equals(method.selector,sourceMethod.getSelector()) &&
+                                                       CharOperation.equals(argTypeNames,parameterTypeNames)){
+                                                       parameterNames = sourceMethod.getArgumentNames();
+                                                       break;
+                                               }
+                                       }
+                               } 
+                       }
+               }
+               return parameterNames;
+       }
+       
+       private void findNestedTypes(
+               char[] typeName,
+               SourceTypeBinding currentType,
+               Scope scope) {
+               if (typeName == null)
+                       return;
+
+               int typeLength = typeName.length;
+
+               while (scope != null) { // done when a COMPILATION_UNIT_SCOPE is found
+
+                       switch (scope.kind) {
+
+                               case Scope.METHOD_SCOPE :
+                               case Scope.BLOCK_SCOPE :
+                                       BlockScope blockScope = (BlockScope) scope;
+
+                                       next : for (int i = 0, length = blockScope.scopeIndex; i < length; i++) {
+
+                                               if (blockScope.subscopes[i] instanceof ClassScope) {
+                                                       SourceTypeBinding localType =
+                                                               ((ClassScope) blockScope.subscopes[i]).referenceContext.binding;
+
+                                                       if (!localType.isAnonymousType()) {
+                                                               if (typeLength > localType.sourceName.length)
+                                                                       continue next;
+                                                               if (!CharOperation.prefixEquals(typeName, localType.sourceName, false
+                                                                       /* ignore case */
+                                                                       ))
+                                                                       continue next;
+
+                                                               int relevance = R_DEFAULT;
+                                                               relevance += computeRelevanceForCaseMatching(typeName, localType.sourceName);
+                                                               relevance += computeRelevanceForExpectingType(localType);
+                                                               relevance += computeRelevanceForClass();
+                                                               
+                                                               requestor.acceptClass(
+                                                                       localType.qualifiedPackageName(),
+                                                                       localType.sourceName,
+                                                                       localType.sourceName,
+                                                                       localType.modifiers,
+                                                                       startPosition - offset,
+                                                                       endPosition - offset,
+                                                                       relevance);
+                                                       }
+                                               }
+                                       }
+                                       break;
+
+                               case Scope.CLASS_SCOPE :
+                                       findMemberTypes(typeName, scope.enclosingSourceType(), scope, currentType);
+                                       if (typeLength == 0)
+                                               return; // do not search outside the class scope if no prefix was provided
+                                       break;
+
+                               case Scope.COMPILATION_UNIT_SCOPE :
+                                       return;
+                       }
+                       scope = scope.parent;
+               }
+       }
+
+       private void findPackages(CompletionOnPackageReference packageStatement) {
+
+               token = CharOperation.concatWith(packageStatement.tokens, '.');
+               if (token.length == 0)
+                       return;
+
+               setSourceRange(packageStatement.sourceStart, packageStatement.sourceEnd);
+               nameEnvironment.findPackages(CharOperation.toLowerCase(token), this);
+       }
+
+       private void findTypesAndPackages(char[] token, Scope scope) {
+
+               if (token == null)
+                       return;
+
+               if (scope.enclosingSourceType() != null)
+                       findNestedTypes(token, scope.enclosingSourceType(), scope);
+
+               if (unitScope != null) {
+                       int typeLength = token.length;
+                       SourceTypeBinding[] types = unitScope.topLevelTypes;
+
+                       for (int i = 0, length = types.length; i < length; i++) {
+                               SourceTypeBinding sourceType = types[i]; 
+
+                               if (typeLength > sourceType.sourceName.length)  continue;
+                               
+                               if (!CharOperation.prefixEquals(token, sourceType.sourceName, false))   continue;
+
+                               int relevance = R_DEFAULT;
+                               relevance += computeRelevanceForCaseMatching(token, sourceType.sourceName);
+                               relevance += computeRelevanceForExpectingType(sourceType);
+
+                               if (sourceType.isClass()){
+                                       relevance += computeRelevanceForClass();
+                                       requestor.acceptClass(
+                                               sourceType.qualifiedPackageName(),
+                                               sourceType.sourceName(),
+                                               sourceType.sourceName(),
+                                               sourceType.modifiers,
+                                               startPosition - offset, 
+                                               endPosition - offset,
+                                               relevance);
+                               } else {
+                                       relevance += computeRelevanceForInterface();
+                                       requestor.acceptInterface(
+                                               sourceType.qualifiedPackageName(),
+                                               sourceType.sourceName(),
+                                               sourceType.sourceName(),
+                                               sourceType.modifiers,
+                                               startPosition - offset,
+                                               endPosition - offset,
+                                               relevance);
+                               }
+                       }
+               }
+
+               if (token.length == 0)
+                       return;
+
+               findKeywords(token, baseTypes, scope);
+               nameEnvironment.findTypes(token, this);
+               nameEnvironment.findPackages(token, this);
+       }
+
+       private void findTypesAndSubpackages(
+               char[] token,
+               PackageBinding packageBinding) {
+
+               char[] qualifiedName =
+                       CharOperation.concatWith(packageBinding.compoundName, token, '.');
+
+               if (token == null || token.length == 0) {
+                       int length = qualifiedName.length;
+                       System.arraycopy(
+                               qualifiedName,
+                               0,
+                               qualifiedName = new char[length + 1],
+                               0,
+                               length);
+                       qualifiedName[length] = '.';
+               }
+               nameEnvironment.findTypes(qualifiedName, this);
+               nameEnvironment.findPackages(qualifiedName, this);
+       }
+
+       private void findVariablesAndMethods(
+               char[] token,
+               Scope scope,
+               InvocationSite invocationSite,
+               Scope invocationScope) {
+
+               if (token == null)
+                       return;
+
+               // Should local variables hide fields from the receiver type or any of its enclosing types?
+               // we know its an implicit field/method access... see BlockScope getBinding/getImplicitMethod
+
+               boolean staticsOnly = false;
+               // need to know if we're in a static context (or inside a constructor)
+               int tokenLength = token.length;
+
+               ObjectVector localsFound = new ObjectVector();
+               ObjectVector fieldsFound = new ObjectVector();
+               ObjectVector methodsFound = new ObjectVector();
+
+               Scope currentScope = scope;
+
+               done1 : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
+
+                       switch (currentScope.kind) {
+
+                               case Scope.METHOD_SCOPE :
+                                       // handle the error case inside an explicit constructor call (see MethodScope>>findField)
+                                       MethodScope methodScope = (MethodScope) currentScope;
+                                       staticsOnly |= methodScope.isStatic | methodScope.isConstructorCall;
+
+                               case Scope.BLOCK_SCOPE :
+                                       BlockScope blockScope = (BlockScope) currentScope;
+
+                                       next : for (int i = 0, length = blockScope.locals.length; i < length; i++) {
+                                               LocalVariableBinding local = blockScope.locals[i];
+
+                                               if (local == null)
+                                                       break next;
+
+                                               if (tokenLength > local.name.length)
+                                                       continue next;
+
+                                               if (!CharOperation.prefixEquals(token, local.name, false /* ignore case */
+                                                       ))
+                                                       continue next;
+
+                                               if (local.isSecret())
+                                                       continue next;
+
+                                               for (int f = 0; f < localsFound.size; f++) {
+                                                       LocalVariableBinding otherLocal =
+                                                               (LocalVariableBinding) localsFound.elementAt(f);
+                                                       if (CharOperation.equals(otherLocal.name, local.name, true))
+                                                               continue next;
+                                               }
+                                               localsFound.add(local);
+
+                                               int relevance = R_DEFAULT;
+                                               relevance += computeRelevanceForCaseMatching(token, local.name);
+                                               relevance += computeRelevanceForExpectingType(local.type);
+                                               
+                                               requestor.acceptLocalVariable(
+                                                       local.name,
+                                                       local.type == null 
+                                                               ? NoChar
+                                                               : local.type.qualifiedPackageName(),
+                                                       local.type == null
+                                                               ? local.declaration.type.toString().toCharArray()
+                                                               : local.type.qualifiedSourceName(),
+                                                       local.modifiers,
+                                                       startPosition - offset,
+                                                       endPosition - offset,
+                                                       relevance);
+                                       }
+                                       break;
+
+                               case Scope.COMPILATION_UNIT_SCOPE :
+                                       break done1;
+                       }
+                       currentScope = currentScope.parent;
+               }
+
+               currentScope = scope;
+
+               done2 : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
+
+                       switch (currentScope.kind) {
+
+                               case Scope.CLASS_SCOPE :
+                                       ClassScope classScope = (ClassScope) currentScope;
+                                       SourceTypeBinding enclosingType = classScope.referenceContext.binding;
+                                       /*                              if (tokenLength == 0) { // only search inside the type itself if no prefix was provided
+                                                                               findFields(token, enclosingType.fields(), classScope, fieldsFound, staticsOnly);
+                                                                               findMethods(token, enclosingType.methods(), classScope, methodsFound, staticsOnly, false);
+                                                                               break done;
+                                                                       } else { */
+                                       findFields(
+                                               token,
+                                               enclosingType,
+                                               classScope,
+                                               fieldsFound,
+                                               localsFound,
+                                               staticsOnly,
+                                               invocationSite,
+                                               invocationScope,
+                                               true);
+
+                                       findMethods(
+                                               token,
+                                               null,
+                                               enclosingType,
+                                               classScope,
+                                               methodsFound,
+                                               staticsOnly,
+                                               false,
+                                               false,
+                                               invocationSite,
+                                               invocationScope,
+                                               true);
+                                       staticsOnly |= enclosingType.isStatic();
+                                       //                              }
+                                       break;
+
+                               case Scope.COMPILATION_UNIT_SCOPE :
+                                       break done2;
+                       }
+                       currentScope = currentScope.parent;
+               }
+       }
+
+       // Helper method for private void findVariableNames(char[] name, TypeReference type )
+       private void findVariableName(char[] token, char[] qualifiedPackageName, char[] qualifiedSourceName, char[] sourceName, char[][] excludeNames, int dim){
+                       if(sourceName == null || sourceName.length == 0)
+                               return;
+                               
+                       char[] name = null;
+                       
+                       // compute variable name for base type
+                       try{
+                               nameScanner.setSource(sourceName);
+        nameScanner.getNextToken();  //        switch (nameScanner.getNextToken()) {
+//                                     case TokenNameint :
+//                                     case TokenNamebyte :
+//                                     case TokenNameshort :
+//                                     case TokenNamechar :
+//                                     case TokenNamelong :
+//                                     case TokenNamefloat :
+//                                     case TokenNamedouble :
+//                                     case TokenNameboolean :
+//                                             if(token != null && token.length != 0)
+//                                                     return;
+//                                             name = computeBaseNames(sourceName[0], excludeNames);
+//                                             break;
+//                             }
+                               if(name != null) {
+                                       int relevance = R_DEFAULT;
+                                       relevance += computeRelevanceForCaseMatching(token, name);
+                                       
+                                       // accept result
+                                       requestor.acceptVariableName(
+                                               qualifiedPackageName,
+                                               qualifiedSourceName,
+                                               name,
+                                               name,
+                                               startPosition - offset,
+                                               endPosition - offset,
+                                               relevance);
+                                       return;
+                               }
+                       } catch(InvalidInputException e){
+                       }
+                       
+                       // compute variable name for non base type
+                       char[][] names = computeNames(sourceName, dim > 0);
+                       char[] displayName;
+                       if (dim > 0){
+                               int l = qualifiedSourceName.length;
+                               displayName = new char[l+(2*dim)];
+                               System.arraycopy(qualifiedSourceName, 0, displayName, 0, l);
+                               for(int i = 0; i < dim; i++){
+                                       displayName[l+(i*2)] = '[';
+                                       displayName[l+(i*2)+1] = ']';
+                               }
+                       } else {
+                               displayName = qualifiedSourceName;
+                       }
+                       next : for(int i = 0 ; i < names.length ; i++){
+                               name = names[i];
+                               
+                               if (!CharOperation.prefixEquals(token, name, false))
+                                       continue next;
+                               
+                               // completion must be an identifier (not a keyword, ...).
+                               try{
+                                       nameScanner.setSource(name);
+                                       if(nameScanner.getNextToken() != TokenNameIdentifier)
+                                               continue next;
+                               } catch(InvalidInputException e){
+                                       continue next;
+                               }
+                               
+                               int count = 2;
+                               char[] originalName = name;
+                               for(int j = 0 ; j < excludeNames.length ; j++){
+                                       if(CharOperation.equals(name, excludeNames[j], false)) {
+                                               name = CharOperation.concat(originalName, String.valueOf(count++).toCharArray());
+                                               j = 0;
+                                       }       
+                               }
+                               
+                               int relevance = R_DEFAULT;
+                               relevance += computeRelevanceForCaseMatching(token, name);
+                               
+                               // accept result
+                               requestor.acceptVariableName(
+                                       qualifiedPackageName,
+                                       displayName,
+                                       name,
+                                       name,
+                                       startPosition - offset,
+                                       endPosition - offset,
+                                       relevance);
+                       }
+       }
+
+       private void findVariableNames(char[] name, TypeReference type , char[][] excludeNames){
+
+               if(type != null &&
+                       type.binding != null &&
+                       type.binding.problemId() == Binding.NoError){
+                       TypeBinding tb = type.binding;
+                       findVariableName(
+                               name,
+                               tb.leafComponentType().qualifiedPackageName(),
+                               tb.leafComponentType().qualifiedSourceName(),
+                               tb.leafComponentType().sourceName(),
+                               excludeNames,
+                               type.dimensions());
+               }/*     else {
+                       char[][] typeName = type.getTypeName();
+                       findVariableName(
+                               name,
+                               NoChar,
+                               CharOperation.concatWith(typeName, '.'),
+                               typeName[typeName.length - 1],
+                               excludeNames,
+                               type.dimensions());
+               }*/
+       }
+       
+       public AssistParser getParser() {
+
+               return parser;
+       }
+
+       protected void reset() {
+
+               super.reset();
+               this.knownPkgs = new HashtableOfObject(10);
+               this.knownTypes = new HashtableOfObject(10);
+       }
+
+       private void setSourceRange(int start, int end) {
+
+               this.startPosition = start;
+               this.endPosition = end + 1;
+       }
+       
+       private char[] computeBaseNames(char firstName, char[][] excludeNames){
+               char[] name = new char[]{firstName};
+               
+               for(int i = 0 ; i < excludeNames.length ; i++){
+                       if(CharOperation.equals(name, excludeNames[i], false)) {
+                               name[0]++;
+                               if(name[0] > 'z')
+                                       name[0] = 'a';
+                               if(name[0] == firstName)
+                                       return null;
+                               i = 0;
+                       }       
+               }
+               
+               return name;
+       }
+       private void computeExpectedTypes(AstNode parent, Scope scope){
+               int expectedTypeCount = 0;
+               expectedTypes = new TypeBinding[1];
+               
+               if(parent instanceof AbstractVariableDeclaration) {
+                       TypeBinding binding = ((AbstractVariableDeclaration)parent).type.binding;
+                       if(binding != null) {
+                               expectedTypes[expectedTypeCount++] = binding;
+                       }
+               } else if(parent instanceof Assignment) {
+                       TypeBinding binding = ((Assignment)parent).lhsType;
+                       if(binding != null) {
+                               expectedTypes[expectedTypeCount++] = binding;
+                       }
+               } else if(parent instanceof ReturnStatement) {
+                       MethodBinding methodBinding = ((AbstractMethodDeclaration) scope.methodScope().referenceContext).binding;
+                       TypeBinding binding = methodBinding  == null ? null : methodBinding.returnType;
+                       if(binding != null) {
+                               expectedTypes[expectedTypeCount++] = binding;
+                       }
+               }
+               
+               System.arraycopy(expectedTypes, 0, expectedTypes = new TypeBinding[expectedTypeCount], 0, expectedTypeCount);
+       }
+       private char[][] computeNames(char[] sourceName, boolean forArray){
+               char[][] names = new char[5][];
+               int nameCount = 0;
+               boolean previousIsUpperCase = false;
+               for(int i = sourceName.length - 1 ; i >= 0 ; i--){
+                       boolean isUpperCase = Character.isUpperCase(sourceName[i]);
+                       if(isUpperCase && !previousIsUpperCase){
+                               char[] name = CharOperation.subarray(sourceName,i,sourceName.length);
+                               if(name.length > 1){
+                                       if(nameCount == names.length) {
+                                               System.arraycopy(names, 0, names = new char[nameCount * 2][], 0, nameCount);
+                                       }
+                                       name[0] = Character.toLowerCase(name[0]);
+                                       
+                                       if(forArray) {
+                                               int length = name.length;
+                                               if (name[length-1] == 's'){
+                                                       System.arraycopy(name, 0, name = new char[length + 2], 0, length);
+                                                       name[length] = 'e';
+                                                       name[length+1] = 's';
+                                               } else {
+                                                       System.arraycopy(name, 0, name = new char[length + 1], 0, length);
+                                                       name[length] = 's';
+                                               }
+                                       }                                       
+                                       names[nameCount++] = name;
+                               }
+                       }
+                       previousIsUpperCase = isUpperCase;
+               }
+               if(nameCount == 0){
+                       char[] name = CharOperation.toLowerCase(sourceName);
+                       if(forArray) {
+                               int length = name.length;
+                               if (name[length-1] == 's'){
+                                       System.arraycopy(name, 0, name = new char[length + 2], 0, length);
+                                       name[length] = 'e';
+                                       name[length+1] = 's';
+                               } else {
+                                       System.arraycopy(name, 0, name = new char[length + 1], 0, length);
+                                       name[length] = 's';
+                               }
+                       }                                       
+                       names[nameCount++] = name;
+                       
+               }
+               System.arraycopy(names, 0, names = new char[nameCount][], 0, nameCount);
+               return names;
+       }
+       
+       private char[] computePrefix(SourceTypeBinding declarationType, SourceTypeBinding invocationType, boolean isStatic){
+               
+               StringBuffer completion = new StringBuffer(10);
+
+               if (isStatic) {
+                       completion.append(declarationType.sourceName());
+                       
+               } else if (declarationType == invocationType) {
+                       completion.append(THIS);
+                       
+               } else {
+                       
+                       if (!declarationType.isNestedType()) {
+                               
+                               completion.append(declarationType.sourceName());
+                               completion.append('.');
+                               completion.append(THIS);
+
+                       } else if (!declarationType.isAnonymousType()) {
+                               
+                               completion.append(declarationType.sourceName());
+                               completion.append('.');
+                               completion.append(THIS);
+                               
+                       }
+               }
+               
+               return completion.toString().toCharArray();
+       }
+       
+       private boolean isEnclosed(ReferenceBinding possibleEnclosingType, ReferenceBinding type){
+               if(type.isNestedType()){
+                       ReferenceBinding enclosing = type.enclosingType();
+                       while(enclosing != null ){
+                               if(possibleEnclosingType == enclosing)
+                                       return true;
+                               enclosing = enclosing.enclosingType();
+                       }
+               }
+               return false;
+       }
+
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/ISearchRequestor.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/ISearchRequestor.java
new file mode 100644 (file)
index 0000000..a7ddb3a
--- /dev/null
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist;
+
+/**
+ * This is the internal requestor passed to the searchable name environment
+ * so as to process the multiple search results as they are discovered.
+ *
+ * It is used to allow the code assist engine to add some more information
+ * to the raw name environment results before answering them to the UI.
+ */
+public interface ISearchRequestor {
+       
+       /**
+        * One result of the search consists of a new class.
+        *
+        * NOTE - All package and type names are presented in their readable form:
+        *    Package names are in the form "a.b.c".
+        *    Nested type names are in the qualified form "A.M".
+        *    The default package is represented by an empty array.
+        */
+       public void acceptClass(char[] packageName, char[] typeName, int modifiers);
+
+       /**
+        * One result of the search consists of a new interface.
+        *
+        * NOTE - All package and type names are presented in their readable form:
+        *    Package names are in the form "a.b.c".
+        *    Nested type names are in the qualified form "A.I".
+        *    The default package is represented by an empty array.
+        */
+       public void acceptInterface(char[] packageName, char[] typeName, int modifiers);
+
+       /**
+        * One result of the search consists of a new package.
+        *
+        * NOTE - All package names are presented in their readable form:
+        *    Package names are in the form "a.b.c".
+        *    The default package is represented by an empty array.
+        */
+       public void acceptPackage(char[] packageName);
+
+       /**
+        * One result of the search consists of a new type.
+        *
+        * NOTE - All package and type names are presented in their readable form:
+        *    Package names are in the form "a.b.c".
+        *    Nested type names are in the qualified form "A.M".
+        *    The default package is represented by an empty array.
+        */
+       public void acceptType(char[] packageName, char[] typeName);
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/ISearchableNameEnvironment.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/ISearchableNameEnvironment.java
new file mode 100644 (file)
index 0000000..3bd46bf
--- /dev/null
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist;
+
+import net.sourceforge.phpdt.internal.compiler.env.INameEnvironment;
+
+/**
+ * This interface defines the API that may be used to implement any
+ * search-based tool (such as a CodeAssist, a Finder, ...).
+ * It is mainly used to hide from the search tool the implementation
+ * of the underlying environment and its constructions.
+ */
+public interface ISearchableNameEnvironment extends INameEnvironment {
+
+       /**
+        * Find the packages that start with the given prefix.
+        * A valid prefix is a qualified name separated by periods
+        * (ex. java.util).
+        * The packages found are passed to:
+        *    ISearchRequestor.acceptPackage(char[][] packageName)
+        */
+       void findPackages(char[] prefix, ISearchRequestor requestor);
+
+       /**
+        * Find the top-level types (classes and interfaces) that are defined
+        * in the current environment and whose name starts with the
+        * given prefix. The prefix is a qualified name separated by periods
+        * or a simple name (ex. java.util.V or V).
+        *
+        * The types found are passed to one of the following methods (if additional
+        * information is known about the types):
+        *    ISearchRequestor.acceptType(char[][] packageName, char[] typeName)
+        *    ISearchRequestor.acceptClass(char[][] packageName, char[] typeName, int modifiers)
+        *    ISearchRequestor.acceptInterface(char[][] packageName, char[] typeName, int modifiers)
+        *
+        * This method can not be used to find member types... member
+        * types are found relative to their enclosing type.
+        */
+       void findTypes(char[] prefix, ISearchRequestor requestor);
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/ISelectionRequestor.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/ISelectionRequestor.java
new file mode 100644 (file)
index 0000000..b8384a5
--- /dev/null
@@ -0,0 +1,145 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist;
+
+import net.sourceforge.phpdt.core.compiler.IProblem;
+
+/**
+ * A selection requestor accepts results from the selection engine.
+ */
+public interface ISelectionRequestor {
+       /**
+        * Code assist notification of a class selection.
+        * @param packageName char[]
+        *              Declaring package name of the class.
+        * 
+        * @param className char[]
+        *              Name of the class.
+        * 
+        * @param needQualification boolean
+        *              Flag indicating if the type name 
+        *      must be qualified by its package name (depending on imports).
+        *
+        * NOTE - All package and type names are presented in their readable form:
+        *    Package names are in the form "a.b.c".
+        *    Nested type names are in the qualified form "A.M".
+        *    The default package is represented by an empty array.
+        */
+       void acceptClass(
+               char[] packageName,
+               char[] className,
+               boolean needQualification);
+
+       /**
+        * Code assist notification of a compilation error detected during selection.
+        *  @param error net.sourceforge.phpdt.internal.compiler.IProblem
+        *      Only problems which are categorized as errors are notified to the requestor,
+        *              warnings are silently ignored.
+        *              In case an error got signaled, no other completions might be available,
+        *              therefore the problem message should be presented to the user.
+        *              The source positions of the problem are related to the source where it was
+        *              detected (might be in another compilation unit, if it was indirectly requested
+        *              during the code assist process).
+        *      Note: the problem knows its originating file name.
+        */
+       void acceptError(IProblem error);
+
+       /**
+        * Code assist notification of a field selection.
+        * @param declaringTypePackageName char[]
+        *              Name of the package in which the type that contains this field is declared.
+        * 
+        * @param declaringTypeName char[]
+        *              Name of the type declaring this new field.
+        * 
+        * @param name char[]
+        *              Name of the field.
+        *
+        * NOTE - All package and type names are presented in their readable form:
+        *    Package names are in the form "a.b.c".
+        *    Nested type names are in the qualified form "A.M".
+        *    The default package is represented by an empty array.
+        */
+       void acceptField(
+               char[] declaringTypePackageName,
+               char[] declaringTypeName,
+               char[] name);
+
+       /**
+        * Code assist notification of an interface selection.
+        * @param packageName char[]
+        *              Declaring package name of the interface.
+        * 
+        * @param interfaceName char[]
+        *              Name of the interface.
+        * 
+        * @param needQualification boolean
+        *              Flag indicating if the type name 
+        *      must be qualified by its package name (depending on imports).
+        *
+        * NOTE - All package and type names are presented in their readable form:
+        *    Package names are in the form "a.b.c".
+        *    Nested type names are in the qualified form "A.I".
+        *    The default package is represented by an empty array.
+        */
+       void acceptInterface(
+               char[] packageName,
+               char[] interfaceName,
+               boolean needQualification);
+
+       /**
+        * Code assist notification of a method selection.
+        * @param declaringTypePackageName char[]
+        *              Name of the package in which the type that contains this new method is declared.
+        * 
+        * @param declaringTypeName char[]
+        *              Name of the type declaring this new method.
+        * 
+        * @param selector char[]
+        *              Name of the new method.
+        * 
+        * @param parameterPackageNames char[][]
+        *              Names of the packages in which the parameter types are declared.
+        *      Should contain as many elements as parameterTypeNames.
+        * 
+        * @param parameterTypeNames char[][]
+        *              Names of the parameters types.
+        *      Should contain as many elements as parameterPackageNames.
+        * 
+        *  @param isConstructor boolean
+        *              Answer if the method is a constructor.
+        *
+        * NOTE - All package and type names are presented in their readable form:
+        *    Package names are in the form "a.b.c".
+        *    Base types are in the form "int" or "boolean".
+        *    Array types are in the qualified form "M[]" or "int[]".
+        *    Nested type names are in the qualified form "A.M".
+        *    The default package is represented by an empty array.
+        */
+       void acceptMethod(
+               char[] declaringTypePackageName,
+               char[] declaringTypeName,
+               char[] selector,
+               char[][] parameterPackageNames,
+               char[][] parameterTypeNames,
+               boolean isConstructor);
+
+       /**
+        * Code assist notification of a package selection.
+        * @param packageName char[]
+        *              The package name.
+        *
+        * NOTE - All package names are presented in their readable form:
+        *    Package names are in the form "a.b.c".
+        *    The default package is represented by an empty array.
+        */
+       void acceptPackage(char[] packageName);
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/RelevanceConstants.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/RelevanceConstants.java
new file mode 100644 (file)
index 0000000..1c00a85
--- /dev/null
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist;
+
+public interface RelevanceConstants {
+       
+       int R_DEFAULT = 0;
+       int R_CASE = 10;
+       int R_EXPECTED_TYPE = 20;
+       int R_INTERFACE = 20;
+       int R_CLASS = 20;
+       int R_EXCEPTION = 20;
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/SelectionEngine.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/SelectionEngine.java
new file mode 100644 (file)
index 0000000..6f5e306
--- /dev/null
@@ -0,0 +1,739 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist;
+
+import java.util.*;
+
+import net.sourceforge.phpdt.core.compiler.*;
+import net.sourceforge.phpdt.core.compiler.InvalidInputException;
+import net.sourceforge.phpdt.core.compiler.IProblem;
+import net.sourceforge.phpdt.internal.codeassist.impl.*;
+import net.sourceforge.phpdt.internal.codeassist.select.*;
+import net.sourceforge.phpdt.internal.compiler.*;
+import net.sourceforge.phpdt.internal.compiler.env.*;
+import net.sourceforge.phpdt.internal.compiler.ast.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+import net.sourceforge.phpdt.internal.compiler.parser.*;
+import net.sourceforge.phpdt.internal.compiler.problem.*;
+import net.sourceforge.phpdt.internal.compiler.util.*;
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+
+/**
+ * The selection engine is intended to infer the nature of a selected name in some
+ * source code. This name can be qualified.
+ *
+ * Selection is resolving context using a name environment (no need to search), assuming
+ * the source where selection occurred is correct and will not perform any completion
+ * attempt. If this was the desired behavior, a call to the CompletionEngine should be
+ * performed instead.
+ */
+public final class SelectionEngine extends Engine implements ISearchRequestor {
+
+       public static boolean DEBUG = false;
+       
+       SelectionParser parser;
+       ISelectionRequestor requestor;
+
+       boolean acceptedAnswer;
+
+       private int actualSelectionStart;
+       private int actualSelectionEnd;
+       private char[] qualifiedSelection;
+       private char[] selectedIdentifier;
+       
+       private char[][][] acceptedClasses;
+       private char[][][] acceptedInterfaces;
+       int acceptedClassesCount;
+       int acceptedInterfacesCount;
+
+       /**
+        * The SelectionEngine is responsible for computing the selected object.
+        *
+        * It requires a searchable name environment, which supports some
+        * specific search APIs, and a requestor to feed back the results to a UI.
+        *
+        *  @param nameEnvironment net.sourceforge.phpdt.internal.codeassist.ISearchableNameEnvironment
+        *      used to resolve type/package references and search for types/packages
+        *      based on partial names.
+        *
+        *  @param requestor net.sourceforge.phpdt.internal.codeassist.ISelectionRequestor
+        *      since the engine might produce answers of various forms, the engine 
+        *      is associated with a requestor able to accept all possible completions.
+        *
+        *  @param settings java.util.Map
+        *              set of options used to configure the code assist engine.
+        */
+       public SelectionEngine(
+               ISearchableNameEnvironment nameEnvironment,
+               ISelectionRequestor requestor,
+               Map settings) {
+
+               super(settings);
+
+               this.requestor = requestor;
+               this.nameEnvironment = nameEnvironment;
+
+               ProblemReporter problemReporter =
+                       new ProblemReporter(
+                               DefaultErrorHandlingPolicies.proceedWithAllProblems(),
+                               this.compilerOptions,
+                               new DefaultProblemFactory(Locale.getDefault())) {
+                       public void record(IProblem problem, CompilationResult unitResult, ReferenceContext referenceContext) {
+                               unitResult.record(problem, referenceContext);
+                               SelectionEngine.this.requestor.acceptError(problem);
+                       }
+               };
+               this.parser = new SelectionParser(problemReporter, this.compilerOptions.assertMode);
+               this.lookupEnvironment =
+                       new LookupEnvironment(this, this.compilerOptions, problemReporter, nameEnvironment);
+       }
+
+       /**
+        * One result of the search consists of a new class.
+        * @param packageName char[]
+        * @param className char[]
+        * @param modifiers int
+        *
+        * NOTE - All package and type names are presented in their readable form:
+        *    Package names are in the form "a.b.c".
+        *    Nested type names are in the qualified form "A.M".
+        *    The default package is represented by an empty array.
+        */
+       public void acceptClass(char[] packageName, char[] className, int modifiers) {
+               if (CharOperation.equals(className, selectedIdentifier)) {
+                       if (qualifiedSelection != null
+                               && !CharOperation.equals(
+                                       qualifiedSelection,
+                                       CharOperation.concat(packageName, className, '.'))) {
+                               return;
+                       }
+                       
+                       if(mustQualifyType(packageName, className)) {
+                               char[][] acceptedClass = new char[2][];
+                               acceptedClass[0] = packageName;
+                               acceptedClass[1] = className;
+                               
+                               if(acceptedClasses == null) {
+                                       acceptedClasses = new char[10][][];
+                                       acceptedClassesCount = 0;
+                               }
+                               int length = acceptedClasses.length;
+                               if(length == acceptedClassesCount) {
+                                       System.arraycopy(acceptedClasses, 0, acceptedClasses = new char[(length + 1)* 2][][], 0, length);
+                               }
+                               acceptedClasses[acceptedClassesCount++] = acceptedClass;
+                               
+                       } else {
+                               requestor.acceptClass(
+                                       packageName,
+                                       className,
+                                       false);
+                               acceptedAnswer = true;
+                       }
+               }
+       }
+
+       /**
+        * One result of the search consists of a new interface.
+        *
+        * NOTE - All package and type names are presented in their readable form:
+        *    Package names are in the form "a.b.c".
+        *    Nested type names are in the qualified form "A.I".
+        *    The default package is represented by an empty array.
+        */
+       public void acceptInterface(
+               char[] packageName,
+               char[] interfaceName,
+               int modifiers) {
+
+               if (CharOperation.equals(interfaceName, selectedIdentifier)) {
+                       if (qualifiedSelection != null
+                               && !CharOperation.equals(
+                                       qualifiedSelection,
+                                       CharOperation.concat(packageName, interfaceName, '.'))) {
+                               return;
+                       }
+                       
+                       if(mustQualifyType(packageName, interfaceName)) {
+                               char[][] acceptedInterface= new char[2][];
+                               acceptedInterface[0] = packageName;
+                               acceptedInterface[1] = interfaceName;
+                               
+                               if(acceptedInterfaces == null) {
+                                       acceptedInterfaces = new char[10][][];
+                                       acceptedInterfacesCount = 0;
+                               }
+                               int length = acceptedInterfaces.length;
+                               if(length == acceptedInterfacesCount) {
+                                       System.arraycopy(acceptedInterfaces, 0, acceptedInterfaces = new char[(length + 1) * 2][][], 0, length);
+                               }
+                               acceptedInterfaces[acceptedInterfacesCount++] = acceptedInterface;
+                               
+                       } else {
+                               requestor.acceptInterface(
+                                       packageName,
+                                       interfaceName,
+                                       false);
+                               acceptedAnswer = true;
+                       }
+               }
+       }
+
+       /**
+        * One result of the search consists of a new package.
+        * @param packageName char[]
+        * 
+        * NOTE - All package names are presented in their readable form:
+        *    Package names are in the form "a.b.c".
+        *    The default package is represented by an empty array.
+        */
+       public void acceptPackage(char[] packageName) {
+       }
+
+       private void acceptQualifiedTypes() {
+               if(acceptedClasses != null){
+                       acceptedAnswer = true;
+                       for (int i = 0; i < acceptedClassesCount; i++) {
+                               requestor.acceptClass(
+                                       acceptedClasses[i][0],
+                                       acceptedClasses[i][1],
+                                       true);
+                       }
+                       acceptedClasses = null;
+                       acceptedClassesCount = 0;
+               }
+               if(acceptedInterfaces != null){
+                       acceptedAnswer = true;
+                       for (int i = 0; i < acceptedInterfacesCount; i++) {
+                               requestor.acceptInterface(
+                                       acceptedInterfaces[i][0],
+                                       acceptedInterfaces[i][1],
+                                       true);
+                       }
+                       acceptedInterfaces = null;
+                       acceptedInterfacesCount = 0;
+               }
+       }
+       
+       /**
+        * One result of the search consists of a new type.
+        * @param packageName char[]
+        * @param typeName char[]
+        * 
+        * NOTE - All package and type names are presented in their readable form:
+        *    Package names are in the form "a.b.c".
+        *    Nested type names are in the qualified form "A.M".
+        *    The default package is represented by an empty array.
+        */
+       public void acceptType(char[] packageName, char[] typeName) {
+               acceptClass(packageName, typeName, 0);
+       }
+
+       private boolean checkSelection(
+               char[] source,
+               int selectionStart,
+               int selectionEnd) {
+
+               Scanner scanner = new Scanner();
+               scanner.setSource(source);
+               
+               int lastIdentifierStart = -1;
+               int lastIdentifierEnd = -1;
+               char[] lastIdentifier = null;
+               int token, identCount = 0;
+               StringBuffer entireSelection = new StringBuffer(selectionEnd - selectionStart + 1);
+               
+               if(selectionStart > selectionEnd){
+                       
+                       // compute start position of current line
+                       int currentPosition = selectionStart - 1;
+                       int nextCharacterPosition = selectionStart;
+                       char currentCharacter = ' ';
+                       try {
+                               while(currentPosition > 0 || currentCharacter == '\r' || currentCharacter == '\n'){
+                                       
+                                       if(source[currentPosition] == '\\' && source[currentPosition+1] == 'u') {
+                                               int pos = currentPosition + 2;
+                                               int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
+                                               while (source[pos] == 'u') {
+                                                       pos++;
+                                               }
+                                               if ((c1 = Character.getNumericValue(source[pos++])) > 15
+                                                       || c1 < 0
+                                                       || (c2 = Character.getNumericValue(source[pos++])) > 15
+                                                       || c2 < 0
+                                                       || (c3 = Character.getNumericValue(source[pos++])) > 15
+                                                       || c3 < 0
+                                                       || (c4 = Character.getNumericValue(source[pos++])) > 15
+                                                       || c4 < 0) {
+                                                       return false;
+                                               } else {
+                                                       currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+                                                       nextCharacterPosition = pos;
+                                               }
+                                       } else {
+                                               currentCharacter = source[currentPosition];
+                                               nextCharacterPosition = currentPosition+1;
+                                       }
+                                       
+                                       if(currentCharacter == '\r' || currentCharacter == '\n') {
+                                               break;
+                                       }
+                                       currentPosition--;
+                               }
+                       }
+                       catch (ArrayIndexOutOfBoundsException e) {
+                               return false;
+                       }
+                       
+                       // compute start and end of the last token
+                       scanner.resetTo(nextCharacterPosition, selectionEnd);
+                       do {
+                               try {
+                                       token = scanner.getNextToken();
+                               } catch (InvalidInputException e) {
+                                       return false;
+                               }
+                               if((
+        // token == ITerminalSymbols.TokenNamethis ||
+                               // token == ITerminalSymbols.TokenNamesuper ||
+                                       token == ITerminalSymbols.TokenNameIdentifier) &&
+                                       scanner.startPosition <= selectionStart &&
+                                       selectionStart <= scanner.currentPosition) {
+                                       lastIdentifierStart = scanner.startPosition;
+                                       lastIdentifierEnd = scanner.currentPosition - 1;
+                                       lastIdentifier = scanner.getCurrentTokenSource();
+                               }
+                       } while (token != ITerminalSymbols.TokenNameEOF);
+               } else {
+                       scanner.resetTo(selectionStart, selectionEnd);
+       
+                       boolean expectingIdentifier = true;
+                       
+                       do {
+                               try {
+                                       token = scanner.getNextToken();
+                               } catch (InvalidInputException e) {
+                                       return false;
+                               }
+                               switch (token) {
+//                                     case ITerminalSymbols.TokenNamethis :
+//                                     case ITerminalSymbols.TokenNamesuper :
+                                       case ITerminalSymbols.TokenNameIdentifier :
+                                               if (!expectingIdentifier)
+                                                       return false;
+                                               lastIdentifier = scanner.getCurrentTokenSource();
+                                               lastIdentifierStart = scanner.startPosition;
+                                               lastIdentifierEnd = scanner.currentPosition - 1;
+                                               if(lastIdentifierEnd > selectionEnd) {
+                                                       lastIdentifierEnd = selectionEnd;
+                                                       lastIdentifier = CharOperation.subarray(lastIdentifier, 0,lastIdentifierEnd - lastIdentifierStart + 1);
+                                               }
+                                               entireSelection.append(lastIdentifier);
+                                                       
+                                               identCount++;
+                                               expectingIdentifier = false;
+                                               break;
+                                       case ITerminalSymbols.TokenNameDOT :
+                                               if (expectingIdentifier)
+                                                       return false;
+                                               entireSelection.append('.');
+                                               expectingIdentifier = true;
+                                               break;
+                                       case ITerminalSymbols.TokenNameEOF :
+                                               if (expectingIdentifier)
+                                                       return false;
+                                               break;
+                                       default :
+                                               return false;
+                               }
+                       } while (token != ITerminalSymbols.TokenNameEOF);
+               }
+               if (lastIdentifierStart > 0) {
+                       actualSelectionStart = lastIdentifierStart;
+                       actualSelectionEnd = lastIdentifierEnd;
+                       selectedIdentifier = lastIdentifier;
+                       if (identCount > 1)
+                               qualifiedSelection = entireSelection.toString().toCharArray();
+                       return true;
+               }
+               return false;
+       }
+
+       public AssistParser getParser() {
+               return parser;
+       }
+
+       /**
+        * Ask the engine to compute the selection at the specified position
+        * of the given compilation unit.
+
+        *  @param sourceUnit net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit
+        *      the source of the current compilation unit.
+        *
+        *  @param selectionSourceStart int
+        *  @param selectionSourceEnd int
+        *      a range in the source where the selection is.
+        */
+       public void select(
+               ICompilationUnit sourceUnit,
+               int selectionSourceStart,
+               int selectionSourceEnd) {
+
+               char[] source = sourceUnit.getContents();
+               
+               if(DEBUG) {
+                       System.out.print("SELECTION IN "); //$NON-NLS-1$
+                       System.out.print(sourceUnit.getFileName());
+                       System.out.print(" FROM "); //$NON-NLS-1$
+                       System.out.print(selectionSourceStart);
+                       System.out.print(" TO "); //$NON-NLS-1$
+                       System.out.println(selectionSourceEnd);
+                       System.out.println("SELECTION - Source :"); //$NON-NLS-1$
+                       System.out.println(source);
+               }
+               if (!checkSelection(source, selectionSourceStart, selectionSourceEnd))
+                       return;
+               try {
+                       acceptedAnswer = false;
+                       CompilationResult result = new CompilationResult(sourceUnit, 1, 1, this.compilerOptions.maxProblemsPerUnit);
+                       CompilationUnitDeclaration parsedUnit =
+                               parser.dietParse(sourceUnit, result, actualSelectionStart, actualSelectionEnd);
+
+                       if (parsedUnit != null) {
+                               if(DEBUG) {
+                                       System.out.println("SELECTION - Diet AST :"); //$NON-NLS-1$
+                                       System.out.println(parsedUnit.toString());
+                               }
+                               
+                               // scan the package & import statements first
+                               if (parsedUnit.currentPackage instanceof SelectionOnPackageReference) {
+                                       char[][] tokens =
+                                               ((SelectionOnPackageReference) parsedUnit.currentPackage).tokens;
+                                       requestor.acceptPackage(CharOperation.concatWith(tokens, '.'));
+                                       return;
+                               }
+                               ImportReference[] imports = parsedUnit.imports;
+                               if (imports != null) {
+                                       for (int i = 0, length = imports.length; i < length; i++) {
+                                               ImportReference importReference = imports[i];
+                                               if (importReference instanceof SelectionOnImportReference) {
+                                                       char[][] tokens = ((SelectionOnImportReference) importReference).tokens;
+                                                       requestor.acceptPackage(CharOperation.concatWith(tokens, '.'));
+                                                       nameEnvironment.findTypes(CharOperation.concatWith(tokens, '.'), this);
+                                                       // accept qualified types only if no unqualified type was accepted
+                                                       if(!acceptedAnswer) {
+                                                               acceptQualifiedTypes();
+                                                               if (!acceptedAnswer) {
+                                                                       nameEnvironment.findTypes(selectedIdentifier, this);
+                                                                       // try with simple type name
+                                                                       if(!acceptedAnswer) {
+                                                                               acceptQualifiedTypes();
+                                                                       }
+                                                               }
+                                                       }
+                                                       return;
+                                               }
+                                       }
+                               }
+                               if (parsedUnit.types != null) {
+                                       lookupEnvironment.buildTypeBindings(parsedUnit);
+                                       if ((this.unitScope = parsedUnit.scope)  != null) {
+                                               try {
+                                                       lookupEnvironment.completeTypeBindings(parsedUnit, true);
+                                                       parsedUnit.scope.faultInTypes();
+                                                       selectDeclaration(parsedUnit);
+                                                       parseMethod(parsedUnit, selectionSourceStart);
+                                                       if(DEBUG) {
+                                                               System.out.println("SELECTION - AST :"); //$NON-NLS-1$
+                                                               System.out.println(parsedUnit.toString());
+                                                       }
+                                                       parsedUnit.resolve();
+                                               } catch (SelectionNodeFound e) {
+                                                       if (e.binding != null) {
+                                                               if(DEBUG) {
+                                                                       System.out.println("SELECTION - Selection binding:"); //$NON-NLS-1$
+                                                                       System.out.println(e.binding.toString());
+                                                               }
+                                                               // if null then we found a problem in the selection node
+                                                               selectFrom(e.binding);
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       // only reaches here if no selection could be derived from the parsed tree
+                       // thus use the selected source and perform a textual type search
+                       if (!acceptedAnswer) {
+                               nameEnvironment.findTypes(selectedIdentifier, this);
+                               
+                               // accept qualified types only if no unqualified type was accepted
+                               if(!acceptedAnswer) {
+                                       acceptQualifiedTypes();
+                               }
+                       }
+               } catch (IndexOutOfBoundsException e) { // work-around internal failure - 1GEMF6D               
+               } catch (AbortCompilation e) { // ignore this exception for now since it typically means we cannot find java.lang.Object
+               } finally {
+                       reset();
+               }
+       }
+
+       private void selectFrom(Binding binding) {
+               if (binding instanceof ReferenceBinding) {
+                       ReferenceBinding typeBinding = (ReferenceBinding) binding;
+                       if (qualifiedSelection != null
+                               && !CharOperation.equals(qualifiedSelection, typeBinding.readableName())) {
+                               return;
+                       }
+                       if (typeBinding.isInterface()) {
+                               requestor.acceptInterface(
+                                       typeBinding.qualifiedPackageName(),
+                                       typeBinding.qualifiedSourceName(),
+                                       false);
+                       } else if(typeBinding instanceof ProblemReferenceBinding){
+                               ProblemReferenceBinding problemBinding = (ProblemReferenceBinding)typeBinding;
+                               if(problemBinding.original == null
+                                       || !(problemBinding.original instanceof ReferenceBinding)) {
+                                       return;
+                               }
+                               ReferenceBinding original = (ReferenceBinding) problemBinding.original;
+
+                               requestor.acceptClass(
+                                       original.qualifiedPackageName(),
+                                       original.qualifiedSourceName(),
+                                       false);
+                       } else {
+                               requestor.acceptClass(
+                                       typeBinding.qualifiedPackageName(),
+                                       typeBinding.qualifiedSourceName(),
+                                       false);
+                       }
+                       acceptedAnswer = true;
+               } else
+                       if (binding instanceof MethodBinding) {
+                               MethodBinding methodBinding = (MethodBinding) binding;
+                               TypeBinding[] parameterTypes = methodBinding.parameters;
+                               int length = parameterTypes.length;
+                               char[][] parameterPackageNames = new char[length][];
+                               char[][] parameterTypeNames = new char[length][];
+                               for (int i = 0; i < length; i++) {
+                                       parameterPackageNames[i] = parameterTypes[i].qualifiedPackageName();
+                                       parameterTypeNames[i] = parameterTypes[i].qualifiedSourceName();
+                               }
+                               requestor.acceptMethod(
+                                       methodBinding.declaringClass.qualifiedPackageName(),
+                                       methodBinding.declaringClass.qualifiedSourceName(),
+                                       methodBinding.isConstructor()
+                                               ? methodBinding.declaringClass.sourceName()
+                                               : methodBinding.selector,
+                                       parameterPackageNames,
+                                       parameterTypeNames,
+                                       methodBinding.isConstructor());
+                               acceptedAnswer = true;
+                       } else
+                               if (binding instanceof FieldBinding) {
+                                       FieldBinding fieldBinding = (FieldBinding) binding;
+                                       if (fieldBinding.declaringClass != null) { // arraylength
+                                               requestor.acceptField(
+                                                       fieldBinding.declaringClass.qualifiedPackageName(),
+                                                       fieldBinding.declaringClass.qualifiedSourceName(),
+                                                       fieldBinding.name);
+                                               acceptedAnswer = true;
+                                       }
+                               } else
+                                       if (binding instanceof LocalVariableBinding) {
+                                               selectFrom(((LocalVariableBinding) binding).type);
+                                               // open on the type of the variable
+                                       } else
+                                               if (binding instanceof ArrayBinding) {
+                                                       selectFrom(((ArrayBinding) binding).leafComponentType);
+                                                       // open on the type of the array
+                                               } else
+                                                       if (binding instanceof PackageBinding) {
+                                                               PackageBinding packageBinding = (PackageBinding) binding;
+                                                               requestor.acceptPackage(packageBinding.readableName());
+                                                               acceptedAnswer = true;
+                                                       } else
+                                                               if(binding instanceof BaseTypeBinding) {
+                                                                       acceptedAnswer = true;
+                                                               }
+       }
+
+       /**
+        * Asks the engine to compute the selection of the given type
+        * from the source type.
+        *
+        *  @param sourceType net.sourceforge.phpdt.internal.compiler.env.ISourceType
+        *      a source form of the current type in which code assist is invoked.
+        *
+        *  @param typeName char[]
+        *      a type name which is to be resolved in the context of a compilation unit.
+        *              NOTE: the type name is supposed to be correctly reduced (no whitespaces, no unicodes left)
+        * 
+        *  @param searchInEnvironment
+        *      if <code>true</code> and no selection could be found in context then search type in environment.
+        */
+       public void selectType(ISourceType sourceType, char[] typeName, boolean searchInEnvironment) {
+               try {
+                       acceptedAnswer = false;
+
+                       // find the outer most type
+                       ISourceType outerType = sourceType;
+                       ISourceType parent = sourceType.getEnclosingType();
+                       while (parent != null) {
+                               outerType = parent;
+                               parent = parent.getEnclosingType();
+                       }
+                       // compute parse tree for this most outer type
+                       CompilationResult result = new CompilationResult(outerType.getFileName(), 1, 1, this.compilerOptions.maxProblemsPerUnit);
+                       CompilationUnitDeclaration parsedUnit =
+                               SourceTypeConverter
+                                       .buildCompilationUnit(
+                                               new ISourceType[] { outerType },
+                                               false,
+                       // don't need field and methods
+                       true, // by default get member types
+                       this.parser.problemReporter(), result);
+
+                       if (parsedUnit != null && parsedUnit.types != null) {
+                               if(DEBUG) {
+                                       System.out.println("SELECTION - Diet AST :"); //$NON-NLS-1$
+                                       System.out.println(parsedUnit.toString());
+                               }
+                               // find the type declaration that corresponds to the original source type
+                               char[] packageName = sourceType.getPackageName();
+                               char[] sourceTypeName = sourceType.getQualifiedName();
+                               // the fully qualified name without the package name
+                               if (packageName != null) {
+                                       // remove the package name if necessary
+                                       sourceTypeName =
+                                               CharOperation.subarray(
+                                                       sourceType.getQualifiedName(),
+                                                       packageName.length + 1,
+                                                       sourceTypeName.length);
+                               };
+                               TypeDeclaration typeDecl =
+                                       parsedUnit.declarationOfType(CharOperation.splitOn('.', sourceTypeName));
+                               if (typeDecl != null) {
+
+                                       // add fake field with the type we're looking for
+                                       // note: since we didn't ask for fields above, there is no field defined yet
+                                       FieldDeclaration field = new FieldDeclaration();
+                                       int dot;
+                                       if ((dot = CharOperation.lastIndexOf('.', typeName)) == -1) {
+                                               this.selectedIdentifier = typeName;
+                                               field.type = new SelectionOnSingleTypeReference(typeName, -1);
+                                               // position not used
+                                       } else {
+                                               qualifiedSelection = typeName;
+                                               char[][] previousIdentifiers = CharOperation.splitOn('.', typeName, 0, dot - 1);
+                                               char[] selectionIdentifier =
+                                                       CharOperation.subarray(typeName, dot + 1, typeName.length);
+                                               this.selectedIdentifier = selectionIdentifier;
+                                               field.type =
+                                                       new SelectionOnQualifiedTypeReference(
+                                                               previousIdentifiers,
+                                                               selectionIdentifier,
+                                                               new long[previousIdentifiers.length + 1]);
+                                       }
+                                       field.name = "<fakeField>".toCharArray(); //$NON-NLS-1$
+                                       typeDecl.fields = new FieldDeclaration[] { field };
+
+                                       // build bindings
+                                       lookupEnvironment.buildTypeBindings(parsedUnit);
+                                       if ((this.unitScope = parsedUnit.scope) != null) {
+                                               try {
+                                                       // build fields
+                                                       // note: this builds fields only in the parsed unit (the buildFieldsAndMethods flag is not passed along)
+                                                       this.lookupEnvironment.completeTypeBindings(parsedUnit, true);
+
+                                                       // resolve
+                                                       parsedUnit.scope.faultInTypes();
+                                                       parsedUnit.resolve();
+                                               } catch (SelectionNodeFound e) {
+                                                       if (e.binding != null) {
+                                                               if(DEBUG) {
+                                                                       System.out.println("SELECTION - Selection binding :"); //$NON-NLS-1$
+                                                                       System.out.println(e.binding.toString());
+                                                               }
+                                                               // if null then we found a problem in the selection node
+                                                               selectFrom(e.binding);
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       // only reaches here if no selection could be derived from the parsed tree
+                       // thus use the selected source and perform a textual type search
+                       if (!acceptedAnswer && searchInEnvironment) {
+                               if (this.selectedIdentifier != null) {
+                                       nameEnvironment.findTypes(typeName, this);
+                                       
+                                       // accept qualified types only if no unqualified type was accepted
+                                       if(!acceptedAnswer) {
+                                               acceptQualifiedTypes();
+                                       }
+                               }
+                       }
+               } catch (AbortCompilation e) { // ignore this exception for now since it typically means we cannot find java.lang.Object
+               } finally {
+                       qualifiedSelection = null;
+                       reset();
+               }
+       }
+
+       // Check if a declaration got selected in this unit
+       private void selectDeclaration(CompilationUnitDeclaration compilationUnit){
+
+               // the selected identifier is not identical to the parser one (equals but not identical),
+               // for traversing the parse tree, the parser assist identifier is necessary for identitiy checks
+               char[] assistIdentifier = this.getParser().assistIdentifier();
+               if (assistIdentifier == null) return;
+               
+               // iterate over the types
+               TypeDeclaration[] types = compilationUnit.types;
+               for (int i = 0, length = types == null ? 0 : types.length; i < length; i++){
+                       selectDeclaration(types[i], assistIdentifier);
+               }
+       }
+
+       // Check if a declaration got selected in this type
+       private void selectDeclaration(TypeDeclaration typeDeclaration, char[] assistIdentifier){
+
+               if (typeDeclaration.name == assistIdentifier){
+                       throw new SelectionNodeFound(typeDeclaration.binding);
+               }
+               TypeDeclaration[] memberTypes = typeDeclaration.memberTypes;
+               for (int i = 0, length = memberTypes == null ? 0 : memberTypes.length; i < length; i++){
+                       selectDeclaration(memberTypes[i], assistIdentifier);
+               }
+               FieldDeclaration[] fields = typeDeclaration.fields;
+               for (int i = 0, length = fields == null ? 0 : fields.length; i < length; i++){
+                       if (fields[i].name == assistIdentifier){
+                               throw new SelectionNodeFound(fields[i].binding);
+                       }
+               }
+               AbstractMethodDeclaration[] methods = typeDeclaration.methods;
+               for (int i = 0, length = methods == null ? 0 : methods.length; i < length; i++){
+                       AbstractMethodDeclaration method = methods[i];
+                       if (method.selector == assistIdentifier){
+                               if(method.binding != null) {
+                                       throw new SelectionNodeFound(method.binding);
+                               } else {
+                                       if(method.scope != null) {
+                                               throw new SelectionNodeFound(new MethodBinding(method.modifiers, method.selector, null, null, null, method.scope.referenceType().binding));
+                                       }
+                               }
+               }
+               }
+       }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionNodeFound.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionNodeFound.java
new file mode 100644 (file)
index 0000000..41e45e5
--- /dev/null
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.complete;
+
+import net.sourceforge.phpdt.internal.compiler.ast.AstNode;
+import net.sourceforge.phpdt.internal.compiler.lookup.Binding;
+import net.sourceforge.phpdt.internal.compiler.lookup.Scope;
+
+public class CompletionNodeFound extends RuntimeException {
+       public AstNode astNode;
+       public Binding qualifiedBinding;
+       public Scope scope;
+public CompletionNodeFound() {
+       this(null, null, null); // we found a problem in the completion node
+}
+public CompletionNodeFound(AstNode astNode, Binding qualifiedBinding, Scope scope) {
+       this.astNode = astNode;
+       this.qualifiedBinding = qualifiedBinding;
+       this.scope = scope;
+}
+public CompletionNodeFound(AstNode astNode, Scope scope) {
+       this(astNode, null, scope);
+}
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnArgumentName.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnArgumentName.java
new file mode 100644 (file)
index 0000000..50bb859
--- /dev/null
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.complete;
+
+import net.sourceforge.phpdt.internal.compiler.ast.Argument;
+import net.sourceforge.phpdt.internal.compiler.ast.TypeReference;
+import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
+import net.sourceforge.phpdt.internal.compiler.lookup.MethodScope;
+import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
+import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
+
+
+public class CompletionOnArgumentName extends Argument {
+       private static final char[] FAKENAMESUFFIX = " ".toCharArray(); //$NON-NLS-1$
+       public char[] realName;
+       public CompletionOnArgumentName(char[] name , long posNom , TypeReference tr , int modifiers){
+               super(CharOperation.concat(name, FAKENAMESUFFIX), posNom, tr, modifiers);
+               this.realName = name;
+       }
+       
+       public void resolve(BlockScope scope) {
+               super.resolve(scope);
+               throw new CompletionNodeFound(this, scope);
+       }
+       
+       public void bind(MethodScope scope, TypeBinding typeBinding, boolean used) {
+               super.bind(scope, typeBinding, used);
+               
+               throw new CompletionNodeFound(this, scope);
+       }
+       
+       public String toString(int tab) {
+               String s = tabString(tab);
+               s += "<CompleteOnArgumentName:"; //$NON-NLS-1$
+               if (type != null) s += type.toString() + " "; //$NON-NLS-1$
+               s += new String(realName);
+               if (initialization != null) s += " = " + initialization.toStringExpression(); //$NON-NLS-1$
+               s += ">"; //$NON-NLS-1$
+               return s;
+       }       
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnClassLiteralAccess.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnClassLiteralAccess.java
new file mode 100644 (file)
index 0000000..947c57f
--- /dev/null
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.complete;
+
+/*
+ * Completion node build by the parser in any case it was intending to
+ * reduce an access to the literal 'class' containing the cursor.
+ * e.g.
+ *
+ *     class X {
+ *    void foo() {
+ *      String[].[cursor]
+ *    }
+ *  }
+ *
+ *     ---> class X {
+ *         void foo() {
+ *           <CompleteOnClassLiteralAccess:String[].>
+ *         }
+ *       }
+ *
+ * The source range of the completion node denotes the source range
+ * which should be replaced by the completion.
+ */
+
+import net.sourceforge.phpdt.internal.compiler.ast.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+public class CompletionOnClassLiteralAccess extends ClassLiteralAccess {
+       public char[] completionIdentifier;
+       public int classStart;
+       
+public CompletionOnClassLiteralAccess(long pos, TypeReference t) {
+       super((int)pos, t);
+       this.classStart = (int) (pos >>> 32);
+}
+public TypeBinding resolveType(BlockScope scope) {
+       if (super.resolveType(scope) == null)
+               throw new CompletionNodeFound();
+       else
+               throw new CompletionNodeFound(this, targetType, scope);
+}
+public String toStringExpression() {
+       StringBuffer result = new StringBuffer("<CompleteOnClassLiteralAccess:"); //$NON-NLS-1$
+       result.append(type.toString());
+       result.append("."); //$NON-NLS-1$
+       result.append(completionIdentifier);
+       result.append(">"); //$NON-NLS-1$
+       return result.toString();
+}
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnClassReference.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnClassReference.java
new file mode 100644 (file)
index 0000000..f22f53c
--- /dev/null
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.complete;
+
+public class CompletionOnClassReference extends CompletionOnSingleTypeReference {
+       public CompletionOnClassReference(char[] source, long pos) {
+               super(source, pos);
+       }
+       public String toStringExpression(int tab) {
+               return "<CompleteOnClass:" + new String(token) + ">"; //$NON-NLS-2$ //$NON-NLS-1$
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnExceptionReference.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnExceptionReference.java
new file mode 100644 (file)
index 0000000..f3f723e
--- /dev/null
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.complete;
+
+/*
+ * Completion node build by the parser in any case it was intending to
+ * reduce an exception type reference containing the completion identifier.
+ * e.g.
+ *
+ *     class X {
+ *    void foo() {
+ *      try {
+ *        bar();
+ *      } catch (IOExc[cursor] e) {
+ *      }
+ *    }
+ *  }
+ *
+ *     ---> class X {
+ *         void foo() {
+ *           try {
+ *             bar();
+ *           } catch (<CompleteOnException:IOExc> e) {
+ *           }
+ *         }
+ *       }
+ *
+ * The source range of the completion node denotes the source range
+ * which should be replaced by the completion.
+ */
+public class CompletionOnExceptionReference extends CompletionOnSingleTypeReference {
+public CompletionOnExceptionReference(char[] source, long pos) {
+       super(source, pos);
+}
+public String toStringExpression(int tab) {
+       return "<CompleteOnException:" + new String(token) + ">"; //$NON-NLS-2$ //$NON-NLS-1$
+}
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnExplicitConstructorCall.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnExplicitConstructorCall.java
new file mode 100644 (file)
index 0000000..50d998e
--- /dev/null
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.complete;
+
+/*
+ * Completion node build by the parser in any case it was intending to
+ * reduce a explicit constructor call containing the cursor.
+ * e.g.
+ *
+ *     class X {
+ *    X() {
+ *      this(1, 2, [cursor]
+ *    }
+ *  }
+ *
+ *     ---> class X {
+ *         X() {
+ *           <CompleteOnExplicitConstructorCall:this(1, 2)>
+ *         }
+ *       }
+ *
+ * The source range is always of length 0.
+ * The arguments of the constructor call are all the arguments defined
+ * before the cursor.
+ */
+
+import net.sourceforge.phpdt.internal.compiler.ast.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+public class CompletionOnExplicitConstructorCall extends ExplicitConstructorCall {
+public CompletionOnExplicitConstructorCall(int accessMode) {
+       super(accessMode);
+}
+public void resolve(BlockScope scope) {
+       ReferenceBinding receiverType = scope.enclosingSourceType();
+
+       if (accessMode != This && receiverType != null) {
+               if (receiverType.isHierarchyInconsistent())
+                       throw new CompletionNodeFound();
+               receiverType = receiverType.superclass();
+       }
+       if (receiverType == null)
+               throw new CompletionNodeFound();
+       else
+               throw new CompletionNodeFound(this, receiverType, scope);
+}
+public String toString(int tab) {
+       String s = tabString(tab);
+       s += "<CompleteOnExplicitConstructorCall:"; //$NON-NLS-1$
+       if (qualification != null)
+               s = s + qualification.toStringExpression() + "."; //$NON-NLS-1$
+       if (accessMode == This) {
+               s = s + "this("; //$NON-NLS-1$
+       } else {
+               s = s + "super("; //$NON-NLS-1$
+       }
+       if (arguments != null) {
+               for (int i = 0; i < arguments.length; i++) {
+                       s += arguments[i].toStringExpression();
+                       if (i != arguments.length - 1) {
+                               s += ", "; //$NON-NLS-1$
+                       }
+               };
+       }
+       s += ")>"; //$NON-NLS-1$
+       return s;
+}
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnFieldName.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnFieldName.java
new file mode 100644 (file)
index 0000000..f5994ca
--- /dev/null
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.complete;
+
+import net.sourceforge.phpdt.internal.compiler.ast.Expression;
+import net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration;
+import net.sourceforge.phpdt.internal.compiler.lookup.MethodScope;
+import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
+
+public class CompletionOnFieldName extends FieldDeclaration {
+       private static final char[] FAKENAMESUFFIX = " ".toCharArray(); //$NON-NLS-1$
+       public char[] realName;
+       public CompletionOnFieldName(Expression initialization, char[] name, int sourceStart, int sourceEnd) {
+               super(initialization, CharOperation.concat(name, FAKENAMESUFFIX), sourceStart, sourceEnd); //$NON-NLS-1$
+               this.realName = name;
+       }
+       
+       public void resolve(MethodScope initializationScope) {
+               super.resolve(initializationScope);
+               
+               throw new CompletionNodeFound(this, initializationScope);
+       }
+       
+       public String toString(int tab) {
+               String s = tabString(tab);
+               s += "<CompleteOnFieldName:"; //$NON-NLS-1$
+               if (type != null) s += type.toString() + " "; //$NON-NLS-1$
+               s += new String(realName);
+               if (initialization != null) s += " = " + initialization.toStringExpression(); //$NON-NLS-1$
+               s += ">"; //$NON-NLS-1$
+               return s;
+       }       
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnFieldType.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnFieldType.java
new file mode 100644 (file)
index 0000000..01bfd9b
--- /dev/null
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.complete;
+
+/*
+ * Completion node build by the parser in any case it was intending to
+ * reduce an type reference located as a potential return type for a class
+ * member, containing the cursor location.
+ * This node is only a fake-field wrapper of the actual completion node
+ * which is accessible as the fake-field type.
+ * e.g.
+ *
+ *     class X {
+ *    Obj[cursor]
+ *  }
+ *
+ *     ---> class X {
+ *         <CompleteOnType:Obj>;
+ *       }
+ *
+ * The source range is always of length 0.
+ * The arguments of the allocation expression are all the arguments defined
+ * before the cursor.
+ */
+import net.sourceforge.phpdt.internal.compiler.ast.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+public class CompletionOnFieldType extends FieldDeclaration {
+       public boolean isLocalVariable;
+       
+public CompletionOnFieldType(TypeReference type, boolean isLocalVariable){
+       super();
+       this.sourceStart = type.sourceStart;
+       this.sourceEnd = type.sourceEnd;
+       this.type = type;
+       this.name = NoChar;
+       this.isLocalVariable = isLocalVariable;
+}
+public TypeBinding getTypeBinding(Scope scope) {
+       if(type instanceof CompletionOnSingleTypeReference)
+               throw new CompletionNodeFound(this, scope);
+       else // handle the qualified type ref directly
+               return type.getTypeBinding(scope);
+}
+public String toString(int tab) {
+
+       return type.toString(tab);
+}
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnImportReference.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnImportReference.java
new file mode 100644 (file)
index 0000000..8aff63e
--- /dev/null
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.complete;
+
+/*
+ * Completion node build by the parser in any case it was intending to
+ * reduce an import reference containing the cursor location.
+ * e.g.
+ *
+ *  import java.io[cursor];
+ *     class X {
+ *    void foo() {
+ *    }
+ *  }
+ *
+ *     ---> <CompleteOnImport:java.io>
+ *              class X {
+ *         void foo() {
+ *         }
+ *       }
+ *
+ * The source range is always of length 0.
+ * The arguments of the allocation expression are all the arguments defined
+ * before the cursor.
+ */
+
+import net.sourceforge.phpdt.internal.compiler.ast.*;
+
+public class CompletionOnImportReference extends ImportReference {
+
+public CompletionOnImportReference(char[][] tokens , long[] positions) {
+       super(tokens, positions, false);
+}
+public String toString(int tab, boolean withOnDemand) {
+
+       StringBuffer buffer = new StringBuffer(tabString(tab));
+       buffer. append("<CompleteOnImport:"); //$NON-NLS-1$
+       for (int i = 0; i < tokens.length; i++) {
+               buffer.append(tokens[i]);
+               if (i < (tokens.length - 1)) {
+                       buffer.append("."); //$NON-NLS-1$
+               }
+       }
+       buffer.append(">"); //$NON-NLS-1$
+       return buffer.toString();
+}
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnInterfaceReference.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnInterfaceReference.java
new file mode 100644 (file)
index 0000000..a52fdf7
--- /dev/null
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.complete;
+
+public class CompletionOnInterfaceReference extends CompletionOnSingleTypeReference {
+       public CompletionOnInterfaceReference(char[] source, long pos) {
+               super(source, pos);
+       }
+       public String toStringExpression(int tab) {
+               return "<CompleteOnInterface:" + new String(token) + ">"; //$NON-NLS-2$ //$NON-NLS-1$
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnLocalName.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnLocalName.java
new file mode 100644 (file)
index 0000000..8d4feb5
--- /dev/null
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.complete;
+
+import net.sourceforge.phpdt.internal.compiler.ast.Expression;
+import net.sourceforge.phpdt.internal.compiler.ast.LocalDeclaration;
+import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
+import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
+
+
+public class CompletionOnLocalName extends LocalDeclaration {
+       private static final char[] FAKENAMESUFFIX = " ".toCharArray(); //$NON-NLS-1$
+       public char[] realName;
+       public CompletionOnLocalName(Expression expr,char[] name, int sourceStart, int sourceEnd){
+               super(expr, CharOperation.concat(name, FAKENAMESUFFIX), sourceStart, sourceEnd);
+               this.realName = name;
+       }
+       
+       public void resolve(BlockScope scope) {
+               super.resolve(scope);
+               
+               throw new CompletionNodeFound(this, scope);
+       }
+       public String toString(int tab) {
+               String s = tabString(tab);
+               s += "<CompleteOnLocalName:"; //$NON-NLS-1$
+               if (type != null) s += type.toString() + " "; //$NON-NLS-1$
+               s += new String(realName);
+               if (initialization != null) s += " = " + initialization.toStringExpression(); //$NON-NLS-1$
+               s += ">"; //$NON-NLS-1$
+               return s;
+       }       
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnMemberAccess.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnMemberAccess.java
new file mode 100644 (file)
index 0000000..8933d7c
--- /dev/null
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.complete;
+
+/*
+ * Completion node build by the parser in any case it was intending to
+ * reduce an access to a member (field reference or message send) 
+ * containing the completion identifier.
+ * e.g.
+ *
+ *     class X {
+ *    void foo() {
+ *      bar().fred[cursor]
+ *    }
+ *  }
+ *
+ *     ---> class X {
+ *         void foo() {
+ *           <CompleteOnMemberAccess:bar().fred>
+ *         }
+ *       }
+ *
+ * The source range of the completion node denotes the source range
+ * which should be replaced by the completion.
+ */
+
+import net.sourceforge.phpdt.internal.compiler.ast.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+public class CompletionOnMemberAccess extends FieldReference {
+       
+       public CompletionOnMemberAccess(char[] source, long pos) {
+               super(source, pos);
+       }
+       
+       public TypeBinding resolveType(BlockScope scope) {
+               TypeBinding receiverType = receiver.resolveType(scope);
+               if (receiverType == null || receiverType.isBaseType())
+                       throw new CompletionNodeFound();
+               else
+                       throw new CompletionNodeFound(this, receiverType, scope);
+               // array types are passed along to find the length field
+       }
+       
+       public String toStringExpression() {
+
+               return "<CompleteOnMemberAccess:" //$NON-NLS-1$
+                                               + super.toStringExpression() + ">"; //$NON-NLS-1$
+       }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnMessageSend.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnMessageSend.java
new file mode 100644 (file)
index 0000000..0882c74
--- /dev/null
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.complete;
+
+/*
+ * Completion node build by the parser in any case it was intending to
+ * reduce a message send containing the cursor.
+ * e.g.
+ *
+ *     class X {
+ *    void foo() {
+ *      this.bar(1, 2, [cursor]
+ *    }
+ *  }
+ *
+ *     ---> class X {
+ *         void foo() {
+ *           <CompleteOnMessageSend:this.bar(1, 2)>
+ *         }
+ *       }
+ *
+ * The source range is always of length 0.
+ * The arguments of the message send are all the arguments defined
+ * before the cursor.
+ */
+
+import net.sourceforge.phpdt.internal.compiler.ast.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+public class CompletionOnMessageSend extends MessageSend {
+
+       public TypeBinding resolveType(BlockScope scope) {
+               if (receiver == ThisReference.ThisImplicit)
+                       throw new CompletionNodeFound(this, null, scope);
+
+               TypeBinding receiverType = receiver.resolveType(scope);
+               if (receiverType == null || receiverType.isBaseType())
+                       throw new CompletionNodeFound();
+
+               if (receiverType.isArrayType())
+                       receiverType = scope.getJavaLangObject();
+               throw new CompletionNodeFound(this, receiverType, scope);
+       }
+
+       public String toStringExpression() {
+
+               String s = "<CompleteOnMessageSend:"; //$NON-NLS-1$
+               if (receiver != ThisReference.ThisImplicit)
+                       s = s + receiver.toStringExpression() + "."; //$NON-NLS-1$
+               s = s + new String(selector) + "("; //$NON-NLS-1$
+               if (arguments != null) {
+                       for (int i = 0; i < arguments.length; i++) {
+                               s += arguments[i].toStringExpression();
+                               if (i != arguments.length - 1) {
+                                       s += ", "; //$NON-NLS-1$
+                               }
+                       };
+               }
+               s = s + ")>"; //$NON-NLS-1$
+               return s;
+       }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnMethodName.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnMethodName.java
new file mode 100644 (file)
index 0000000..9679be1
--- /dev/null
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.complete;
+
+import net.sourceforge.phpdt.internal.compiler.CompilationResult;
+import net.sourceforge.phpdt.internal.compiler.ast.MethodDeclaration;
+import net.sourceforge.phpdt.internal.compiler.lookup.ClassScope;
+
+public class CompletionOnMethodName extends MethodDeclaration {
+       public int selectorEnd;
+
+       public CompletionOnMethodName(CompilationResult compilationResult){
+               super(compilationResult);
+       }
+       
+       public void resolve(ClassScope upperScope) {
+               
+               super.resolve(upperScope);
+               throw new CompletionNodeFound(this, upperScope);
+       }
+
+       public String toString(int tab) {
+
+               String s = tabString(tab);
+               s += "<CompletionOnMethodName:"; //$NON-NLS-1$
+
+               if (modifiers != AccDefault) {
+                       s += modifiersString(modifiers);
+               }
+
+               s += returnTypeToString(0);
+               s += new String(selector) + "("; //$NON-NLS-1$
+               if (arguments != null) {
+                       for (int i = 0; i < arguments.length; i++) {
+                               s += arguments[i].toString(0);
+                               if (i != (arguments.length - 1))
+                                       s = s + ", "; //$NON-NLS-1$
+                       };
+               };
+               s += ")"; //$NON-NLS-1$
+               if (thrownExceptions != null) {
+                       s += " throws "; //$NON-NLS-1$
+                       for (int i = 0; i < thrownExceptions.length; i++) {
+                               s += thrownExceptions[i].toString(0);
+                               if (i != (thrownExceptions.length - 1))
+                                       s = s + ", "; //$NON-NLS-1$
+                       };
+               };
+
+               s += ">"; //$NON-NLS-1$
+               return s;
+       }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnMethodReturnType.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnMethodReturnType.java
new file mode 100644 (file)
index 0000000..a220457
--- /dev/null
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.complete;
+
+import net.sourceforge.phpdt.internal.compiler.CompilationResult;
+import net.sourceforge.phpdt.internal.compiler.ast.MethodDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.TypeReference;
+import net.sourceforge.phpdt.internal.compiler.lookup.ClassScope;
+
+public class CompletionOnMethodReturnType extends MethodDeclaration {
+       public CompletionOnMethodReturnType(TypeReference returnType, CompilationResult compilationResult){
+               super(compilationResult);
+               this.returnType = returnType;
+               this.sourceStart = returnType.sourceStart;
+               this.sourceEnd = returnType.sourceEnd;
+       }
+       
+       public void resolveStatements(ClassScope upperScope) {
+                       throw new CompletionNodeFound(this, upperScope);
+       }
+       
+       public String toString(int tab) {
+               return returnType.toString(tab);
+       }
+
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnPackageReference.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnPackageReference.java
new file mode 100644 (file)
index 0000000..0bb48b2
--- /dev/null
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.complete;
+
+/*
+ * Completion node build by the parser in any case it was intending to
+ * reduce an package statement containing the cursor location.
+ * e.g.
+ *
+ *  package java.io[cursor];
+ *     class X {
+ *    void foo() {
+ *    }
+ *  }
+ *
+ *     ---> <CompleteOnPackage:java.io>
+ *              class X {
+ *         void foo() {
+ *         }
+ *       }
+ *
+ * The source range is always of length 0.
+ * The arguments of the allocation expression are all the arguments defined
+ * before the cursor.
+ */
+import net.sourceforge.phpdt.internal.compiler.ast.*;
+
+public class CompletionOnPackageReference extends ImportReference {
+public CompletionOnPackageReference(char[][] tokens , long[] positions) {
+       super(tokens, positions, true);
+}
+public String toString(int tab, boolean withOnDemand) {
+       StringBuffer buffer = new StringBuffer(tabString(tab));
+       buffer. append("<CompleteOnPackage:"); //$NON-NLS-1$
+       for (int i = 0; i < tokens.length; i++) {
+               buffer.append(tokens[i]);
+               if (i < (tokens.length - 1)) {
+                       buffer.append("."); //$NON-NLS-1$
+               }
+       }
+       buffer.append(">"); //$NON-NLS-1$
+       return buffer.toString();
+}
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnQualifiedAllocationExpression.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnQualifiedAllocationExpression.java
new file mode 100644 (file)
index 0000000..6aec572
--- /dev/null
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.complete;
+
+/*
+ * Completion node build by the parser in any case it was intending to
+ * reduce an allocation expression containing the cursor.
+ * If the allocation expression is not qualified, the enclosingInstance field
+ * is null.
+ * e.g.
+ *
+ *     class X {
+ *    void foo() {
+ *      new Bar(1, 2, [cursor]
+ *    }
+ *  }
+ *
+ *     ---> class X {
+ *         void foo() {
+ *           <CompleteOnAllocationExpression:new Bar(1, 2)>
+ *         }
+ *       }
+ *
+ * The source range is always of length 0.
+ * The arguments of the allocation expression are all the arguments defined
+ * before the cursor.
+ */
+
+import net.sourceforge.phpdt.internal.compiler.ast.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+public class CompletionOnQualifiedAllocationExpression extends QualifiedAllocationExpression {
+public TypeBinding resolveType(BlockScope scope) {
+       TypeBinding typeBinding = null;
+       if (enclosingInstance != null) {
+               TypeBinding enclosingType = enclosingInstance.resolveType(scope);
+               if (!(enclosingType instanceof ReferenceBinding)) {
+                       scope.problemReporter().illegalPrimitiveOrArrayTypeForEnclosingInstance(enclosingType, enclosingInstance);
+                       throw new CompletionNodeFound();
+               }
+               typeBinding = ((SingleTypeReference) type).resolveTypeEnclosing(scope, (ReferenceBinding) enclosingType);
+               if (!(typeBinding instanceof ReferenceBinding))
+                       throw new CompletionNodeFound(); // no need to continue if its an array or base type
+               if (typeBinding.isInterface()) // handle the anonymous class definition case
+                       typeBinding = scope.getJavaLangObject();
+       } else {
+               typeBinding = type.resolveType(scope);
+               if (!(typeBinding instanceof ReferenceBinding))
+                       throw new CompletionNodeFound(); // no need to continue if its an array or base type
+       }
+
+       throw new CompletionNodeFound(this, typeBinding, scope);
+}
+public String toStringExpression(int tab) {
+       return 
+               ((this.enclosingInstance == null) ? 
+                       "<CompleteOnAllocationExpression:" :  //$NON-NLS-1$
+                       "<CompleteOnQualifiedAllocationExpression:") +  //$NON-NLS-1$
+               super.toStringExpression(tab) + ">"; //$NON-NLS-1$
+}
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnQualifiedClassReference.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnQualifiedClassReference.java
new file mode 100644 (file)
index 0000000..7d28391
--- /dev/null
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.complete;
+
+public class CompletionOnQualifiedClassReference extends CompletionOnQualifiedTypeReference {
+public CompletionOnQualifiedClassReference(char[][] previousIdentifiers, char[] completionIdentifier, long[] positions) {
+       super(previousIdentifiers, completionIdentifier, positions);
+}
+public String toStringExpression(int tab) {
+
+       StringBuffer buffer = new StringBuffer();
+       buffer. append("<CompleteOnClass:"); //$NON-NLS-1$
+       for (int i = 0; i < tokens.length; i++) {
+               buffer.append(tokens[i]);
+               buffer.append("."); //$NON-NLS-1$
+       }
+       buffer.append(completionIdentifier).append(">"); //$NON-NLS-1$
+       return buffer.toString();
+}
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnQualifiedExceptionReference.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnQualifiedExceptionReference.java
new file mode 100644 (file)
index 0000000..f788b6e
--- /dev/null
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.complete;
+
+/*
+ * Completion node build by the parser in any case it was intending to
+ * reduce an exception type reference containing the completion identifier 
+ * as part of a qualified name.
+ * e.g.
+ *
+ *     class X {
+ *    void foo() {
+ *      try {
+ *        bar();
+ *      } catch (java.io.IOExc[cursor] e) {
+ *      }
+ *    }
+ *  }
+ *
+ *     ---> class X {
+ *         void foo() {
+ *           try {
+ *             bar();
+ *           } catch (<CompleteOnException:java.io.IOExc> e) {
+ *           }
+ *         }
+ *       }
+ *
+ * The source range of the completion node denotes the source range
+ * which should be replaced by the completion.
+ */
+public class CompletionOnQualifiedExceptionReference extends CompletionOnQualifiedTypeReference {
+public CompletionOnQualifiedExceptionReference(char[][] previousIdentifiers, char[] completionIdentifier, long[] positions) {
+       super(previousIdentifiers, completionIdentifier, positions);
+}
+public String toStringExpression(int tab) {
+
+       StringBuffer buffer = new StringBuffer();
+       buffer. append("<CompleteOnException:"); //$NON-NLS-1$
+       for (int i = 0; i < tokens.length; i++) {
+               buffer.append(tokens[i]);
+               buffer.append("."); //$NON-NLS-1$
+       }
+       buffer.append(completionIdentifier).append(">"); //$NON-NLS-1$
+       return buffer.toString();
+}
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnQualifiedInterfaceReference.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnQualifiedInterfaceReference.java
new file mode 100644 (file)
index 0000000..aca5446
--- /dev/null
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.complete;
+
+public class CompletionOnQualifiedInterfaceReference  extends CompletionOnQualifiedTypeReference {
+public CompletionOnQualifiedInterfaceReference(char[][] previousIdentifiers, char[] completionIdentifier, long[] positions) {
+       super(previousIdentifiers, completionIdentifier, positions);
+}
+public String toStringExpression(int tab) {
+
+       StringBuffer buffer = new StringBuffer();
+       buffer. append("<CompleteOnInterface:"); //$NON-NLS-1$
+       for (int i = 0; i < tokens.length; i++) {
+               buffer.append(tokens[i]);
+               buffer.append("."); //$NON-NLS-1$
+       }
+       buffer.append(completionIdentifier).append(">"); //$NON-NLS-1$
+       return buffer.toString();
+}
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnQualifiedNameReference.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnQualifiedNameReference.java
new file mode 100644 (file)
index 0000000..ad0cda8
--- /dev/null
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.complete;
+
+/*
+ * Completion node build by the parser in any case it was intending to
+ * reduce a qualified name reference containing the completion identifier.
+ * e.g.
+ *
+ *     class X {
+ *    Y y;
+ *    void foo() {
+ *      y.fred.ba[cursor]
+ *    }
+ *  }
+ *
+ *     ---> class X {
+ *         Y y;
+ *         void foo() {
+ *           <CompleteOnName:y.fred.ba>
+ *         }
+ *       }
+ *
+ * The source range of the completion node denotes the source range
+ * which should be replaced by the completion.
+ */
+
+import net.sourceforge.phpdt.internal.compiler.ast.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+public class CompletionOnQualifiedNameReference extends QualifiedNameReference {
+       public char[] completionIdentifier;
+       public long[] sourcePositions; // positions of each token, the last one being the positions of the completion identifier
+public CompletionOnQualifiedNameReference(char[][] previousIdentifiers, char[] completionIdentifier, long[] positions) {
+       super(previousIdentifiers, (int) (positions[0] >>> 32), (int) positions[positions.length - 1]);
+       this.completionIdentifier = completionIdentifier;
+       this.sourcePositions = positions;
+}
+public CompletionOnQualifiedNameReference(char[][] previousIdentifiers, char[] completionIdentifier, int sourceStart, int sourceEnd) {
+       super(previousIdentifiers, sourceStart, sourceEnd);
+       this.completionIdentifier = completionIdentifier;
+       this.sourcePositions = new long[] {((long)sourceStart << 32) + sourceEnd};
+}
+public TypeBinding resolveType(BlockScope scope) {
+       // it can be a package, type, member type, local variable or field
+       binding = scope.getBinding(tokens, this);
+       if (!binding.isValidBinding()) {
+               if (binding instanceof ProblemFieldBinding) {
+                       scope.problemReporter().invalidField(this, (FieldBinding) binding);
+               } else if (binding instanceof ProblemReferenceBinding) {
+                       scope.problemReporter().invalidType(this, (TypeBinding) binding);
+               } else {
+                       scope.problemReporter().unresolvableReference(this, binding);
+               }
+               throw new CompletionNodeFound();
+       }
+
+       throw new CompletionNodeFound(this, binding, scope);
+}
+public String toStringExpression() {
+
+       StringBuffer buffer = new StringBuffer("<CompleteOnName:"); //$NON-NLS-1$
+       for (int i = 0; i < tokens.length; i++) {
+               buffer.append(tokens[i]);
+               buffer.append("."); //$NON-NLS-1$
+       }
+       buffer.append(completionIdentifier).append(">"); //$NON-NLS-1$
+       return buffer.toString();
+}
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnQualifiedTypeReference.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnQualifiedTypeReference.java
new file mode 100644 (file)
index 0000000..a62d389
--- /dev/null
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.complete;
+
+/*
+ * Completion node build by the parser in any case it was intending to
+ * reduce a type reference containing the completion identifier as part
+ * of a qualified name.
+ * e.g.
+ *
+ *     class X extends java.lang.Obj[cursor]
+ *
+ *     ---> class X extends <CompleteOnType:java.lang.Obj>
+ *
+ * The source range of the completion node denotes the source range
+ * which should be replaced by the completion.
+ */
+import net.sourceforge.phpdt.internal.compiler.ast.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+public class CompletionOnQualifiedTypeReference extends QualifiedTypeReference {
+       public char[] completionIdentifier;
+public CompletionOnQualifiedTypeReference(char[][] previousIdentifiers, char[] completionIdentifier, long[] positions) {
+       super(previousIdentifiers, positions);
+       this.completionIdentifier = completionIdentifier;
+}
+public void aboutToResolve(Scope scope) {
+       getTypeBinding(scope);
+}
+/*
+ * No expansion of the completion reference into an array one
+ */
+public TypeReference copyDims(int dim){
+       return this;
+}
+public TypeBinding getTypeBinding(Scope scope) {
+       // it can be a package, type or member type
+       Binding binding = scope.parent.getTypeOrPackage(tokens); // step up from the ClassScope
+       if (!binding.isValidBinding()) {
+               scope.problemReporter().invalidType(this, (TypeBinding) binding);
+               throw new CompletionNodeFound();
+       }
+
+       throw new CompletionNodeFound(this, binding, scope);
+}
+public String toStringExpression(int tab) {
+
+       StringBuffer buffer = new StringBuffer();
+       buffer.append("<CompleteOnType:"); //$NON-NLS-1$
+       for (int i = 0; i < tokens.length; i++) {
+               buffer.append(tokens[i]);
+               buffer.append("."); //$NON-NLS-1$
+       }
+       buffer.append(completionIdentifier).append(">"); //$NON-NLS-1$
+       return buffer.toString();
+}
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnSingleNameReference.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnSingleNameReference.java
new file mode 100644 (file)
index 0000000..ed517e9
--- /dev/null
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.complete;
+
+/*
+ * Completion node build by the parser in any case it was intending to
+ * reduce a single name reference containing the completion identifier.
+ * e.g.
+ *
+ *     class X {
+ *    void foo() {
+ *      ba[cursor]
+ *    }
+ *  }
+ *
+ *     ---> class X {
+ *         void foo() {
+ *           <CompleteOnName:ba>
+ *         }
+ *       }
+ *
+ * The source range of the completion node denotes the source range
+ * which should be replaced by the completion.
+ */
+
+import net.sourceforge.phpdt.internal.compiler.ast.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+public class CompletionOnSingleNameReference extends SingleNameReference {
+public CompletionOnSingleNameReference(char[] source, long pos) {
+       super(source, pos);
+}
+public TypeBinding resolveType(BlockScope scope) {
+       throw new CompletionNodeFound(this, scope);
+}
+public String toStringExpression() {
+       return "<CompleteOnName:" + super.toStringExpression() + ">"; //$NON-NLS-2$ //$NON-NLS-1$
+}
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnSingleTypeReference.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionOnSingleTypeReference.java
new file mode 100644 (file)
index 0000000..a72d1f5
--- /dev/null
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.complete;
+
+/*
+ * Completion node build by the parser in any case it was intending to
+ * reduce a type reference containing the completion identifier as a single
+ * name reference.
+ * e.g.
+ *
+ *     class X extends Obj[cursor]
+ *
+ *     ---> class X extends <CompleteOnType:Obj>
+ *
+ * The source range of the completion node denotes the source range
+ * which should be replaced by the completion.
+ */
+import net.sourceforge.phpdt.internal.compiler.ast.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+public class CompletionOnSingleTypeReference extends SingleTypeReference {
+public boolean isCompletionNode;
+public CompletionOnSingleTypeReference(char[] source, long pos) {
+       super(source, pos);
+       isCompletionNode = true;
+}
+public void aboutToResolve(Scope scope) {
+       getTypeBinding(scope);
+}
+/*
+ * No expansion of the completion reference into an array one
+ */
+public TypeReference copyDims(int dim){
+       return this;
+}
+public TypeBinding getTypeBinding(Scope scope) {
+       if(isCompletionNode) {
+               throw new CompletionNodeFound(this, scope);
+       } else {
+               return super.getTypeBinding(scope);
+       }
+}
+public TypeBinding resolveTypeEnclosing(BlockScope scope, ReferenceBinding enclosingType) {
+       if(isCompletionNode) {
+               throw new CompletionNodeFound(this, enclosingType, scope);
+       } else {
+               return super.resolveTypeEnclosing(scope, enclosingType);
+       }
+}
+public String toStringExpression(int tab){
+
+       return "<CompleteOnType:" + new String(token) + ">" ; //$NON-NLS-2$ //$NON-NLS-1$
+}
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionParser.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionParser.java
new file mode 100644 (file)
index 0000000..228c98c
--- /dev/null
@@ -0,0 +1,1386 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.complete;
+
+/*
+ * Parser able to build specific completion parse nodes, given a cursorLocation.
+ *
+ * Cursor location denotes the position of the last character behind which completion
+ * got requested:
+ *  -1 means completion at the very beginning of the source
+ *     0  means completion behind the first character
+ *  n  means completion behind the n-th character
+ */
+import net.sourceforge.phpdt.internal.compiler.*;
+import net.sourceforge.phpdt.internal.compiler.env.*;
+
+import net.sourceforge.phpdt.internal.compiler.ast.*;
+import net.sourceforge.phpdt.internal.compiler.parser.*;
+import net.sourceforge.phpdt.internal.compiler.problem.*;
+import net.sourceforge.phpdt.internal.codeassist.impl.*;
+
+public class CompletionParser extends AssistParser {
+
+       /* public fields */
+
+       public int cursorLocation;
+       public char[][] labels; // the visible labels up to the cursor location
+       public AstNode assistNodeParent; // the parent node of assist node
+       /* the following fields are internal flags */
+       
+       boolean betweenNewAndLeftBraket; // whether we are between the keyword 'new' and the following left braket, ie. '[', '(' or '{'
+       boolean betweenCatchAndRightParen; // whether we are between the keyword 'catch' and the following ')'
+       boolean completionBehindDot; // true when completion identifier immediately follows a dot
+       
+       boolean nextTypeReferenceIsClass;
+       boolean nextTypeReferenceIsException;
+       boolean nextTypeReferenceIsInterface;
+       
+       int bracketDepth;
+       int throwBracketDepth;
+
+       // the stacks of types and qualifiers for invocations (ie. method invocations, allocation expressions and
+       // explicit constructor invocations). They use the same stack pointer as the selector stack (ie. invocationPtr)
+       // the invocation type stack contains one of the invocation type constants below
+       // the qualifier stack contains pointers to the expression stack or -1 if there is no qualifier
+       // (a qualifier is the expression that qualifies a 'new', a 'super' constructor or a 'this' constructor
+       //  or it is the receiver of a message send)
+       int[] invocationTypeStack = new int[StackIncrement];
+       int[] qualifierStack = new int[StackIncrement];
+
+       // invocation type constants
+       static final int EXPLICIT_RECEIVER = 0;
+       static final int NO_RECEIVER = -1;
+       static final int SUPER_RECEIVER = -2;
+       static final int NAME_RECEIVER = -3;
+       static final int ALLOCATION = -4;
+       static final int QUALIFIED_ALLOCATION = -5;
+
+       // the type of the current invocation (one of the invocation type constants)
+       int invocationType;
+
+       // a pointer in the expression stack to the qualifier of a invocation
+       int qualifier;
+
+       // a stack of label counters
+       // a new counter is pushed on the stack each time when a method (or a constructor) is entered, 
+       // it is poped when the method (or constructor) is exited,
+       // it is incremented when a new label is defined
+       int labelCounterPtr;
+       int[] labelCounterStack = new int[StackIncrement];
+
+       // a stack of invocationPtr: contains the first invocationPtr of a block
+       // the current invocationPtr+1 is pushed when a block is entered
+       // it is poped when a block is exited 
+       int blockInvocationPtr;
+       int[] blockInvocationStack = new int[StackIncrement];
+       
+       // last modifiers info
+       int lastModifiers = AccDefault;
+       int lastModifiersStart = -1;
+       
+public CompletionParser(ProblemReporter problemReporter, boolean assertMode) {
+       super(problemReporter, assertMode);
+}
+public char[] assistIdentifier(){
+       return ((CompletionScanner)scanner).completionIdentifier;
+}
+protected void attachOrphanCompletionNode(){
+       if (this.isOrphanCompletionNode) {
+               AstNode orphan = this.assistNode;
+               this.isOrphanCompletionNode = false;
+               
+               /* if in context of a type, then persists the identifier into a fake field return type */
+               if (currentElement instanceof RecoveredType){
+                       RecoveredType recoveredType = (RecoveredType)currentElement;
+                       /* filter out cases where scanner is still inside type header */
+                       if (recoveredType.foundOpeningBrace) {
+                               /* generate a pseudo field with a completion on type reference */       
+                               if (orphan instanceof TypeReference){
+                                       CompletionOnFieldType fieldDeclaration = new CompletionOnFieldType((TypeReference)orphan, false);
+
+                                       // retrieve available modifiers if any
+                                       if (intPtr >= 2 && intStack[intPtr-1] == this.lastModifiersStart && intStack[intPtr-2] == this.lastModifiers){
+                                               fieldDeclaration.modifiersSourceStart = intStack[intPtr-1];
+                                               fieldDeclaration.modifiers = intStack[intPtr-2];
+                                       }
+
+                                       currentElement = currentElement.add(fieldDeclaration, 0);
+                                       return;
+                               }
+                       }
+               }
+               /* if in context of a method, persists if inside arguments as a type */
+               if (currentElement instanceof RecoveredMethod){
+                       RecoveredMethod recoveredMethod = (RecoveredMethod)currentElement;
+                       /* only consider if inside method header */
+                       if (!recoveredMethod.foundOpeningBrace) {
+                               //if (rParenPos < lParenPos){ // inside arguments
+                               if (orphan instanceof TypeReference){
+                                       currentElement = currentElement.parent.add(
+                                               new CompletionOnFieldType((TypeReference)orphan, true), 0);
+                                       return;
+                               }
+                       }
+               }
+
+               // add the completion node to the method declaration or constructor declaration
+               if (orphan instanceof Statement) {
+                       /* check for completion at the beginning of method body
+                               behind an invalid signature
+                        */
+                       RecoveredMethod method = currentElement.enclosingMethod();
+                       if (method != null){
+                               AbstractMethodDeclaration methodDecl = method.methodDeclaration;
+                               if ((methodDecl.bodyStart == methodDecl.sourceEnd+1) // was missing opening brace
+                                       && (scanner.getLineNumber(orphan.sourceStart) == scanner.getLineNumber(methodDecl.sourceEnd))){
+                                       return;
+                               }
+                       }
+                       // add the completion node as a statement to the list of block statements
+                       currentElement = currentElement.add((Statement)orphan, 0);
+                       return;
+               } 
+       }
+       
+       // the following code applies only in methods, constructors or initializers
+       if ((!this.inMethodStack[this.inMethodPtr] && !this.inFieldInitializationStack[this.inFieldInitializationPtr])) { 
+               return;
+       }
+       
+       // push top expression on ast stack if it contains the completion node
+       Expression expression;
+       if (this.expressionPtr > -1 && containsCompletionNode(expression = this.expressionStack[this.expressionPtr])) {
+               /* check for completion at the beginning of method body
+                       behind an invalid signature
+                */
+               RecoveredMethod method = currentElement.enclosingMethod();
+               if (method != null){
+                       AbstractMethodDeclaration methodDecl = method.methodDeclaration;
+                       if ((methodDecl.bodyStart == methodDecl.sourceEnd+1) // was missing opening brace
+                               && (scanner.getLineNumber(expression.sourceStart) == scanner.getLineNumber(methodDecl.sourceEnd))){
+                               return;
+                       }
+               }
+               if (expression instanceof AllocationExpression) {
+                       // keep the context if it is an allocation expression
+                       Statement statement = (Statement)wrapWithExplicitConstructorCallIfNeeded(expression);
+                       currentElement = currentElement.add(statement, 0);
+               } else {
+                       Statement statement = (Statement)wrapWithExplicitConstructorCallIfNeeded(this.assistNode);
+                       currentElement = currentElement.add(statement, 0);
+               }
+       }
+}
+public int bodyEnd(AbstractMethodDeclaration method){
+       return cursorLocation;
+}
+public int bodyEnd(Initializer initializer){
+       return cursorLocation;
+}
+/**
+ * Checks if the completion is on the exception type of a catch clause.
+ * Returns whether we found a completion node.
+ */
+private boolean checkCatchClause() {
+       if (this.betweenCatchAndRightParen && this.identifierPtr > -1) { 
+               // NB: if the cursor is on the variable, then it has been reduced (so identifierPtr is -1), 
+               //     thus this can only be a completion on the type of the catch clause
+               this.assistNode = getTypeReference(0);
+               this.lastCheckPoint = this.assistNode.sourceEnd + 1;
+               this.isOrphanCompletionNode = true;
+               return true;
+       }
+       return false;
+}
+/**
+ * Checks if the completion is on the type following a 'new'.
+ * Returns whether we found a completion node.
+ */
+private boolean checkClassInstanceCreation() {
+       if (this.betweenNewAndLeftBraket) {
+               // completion on type inside an allocation expression
+               
+               if(this.throwBracketDepth != -1 && this.throwBracketDepth == this.bracketDepth) {
+                       this.nextTypeReferenceIsException = true;       
+               }
+               TypeReference type = getTypeReference(0);
+               this.nextTypeReferenceIsException = false;
+               this.assistNode = type;
+               this.lastCheckPoint = type.sourceEnd + 1;
+               if (this.invocationType == ALLOCATION) {
+                       // non qualified allocation expression
+                       AllocationExpression allocExpr = new AllocationExpression();
+                       allocExpr.type = type;
+                       allocExpr.sourceStart = type.sourceStart;
+                       allocExpr.sourceEnd = type.sourceEnd;
+                       pushOnExpressionStack(allocExpr);
+                       this.isOrphanCompletionNode = false;
+               } else {
+                       // qualified allocation expression
+                       QualifiedAllocationExpression allocExpr = new QualifiedAllocationExpression();
+                       allocExpr.type = type;
+                       allocExpr.enclosingInstance = this.expressionStack[this.qualifier];
+                       allocExpr.sourceStart = this.intStack[this.intPtr--];
+                       allocExpr.sourceEnd = type.sourceEnd;
+                       this.expressionStack[this.qualifier] = allocExpr; // attach it now (it replaces the qualifier expression)
+                       this.isOrphanCompletionNode = false;
+               }
+               return true;
+       }
+       return false;
+}
+/**
+ * Checks if the completion is on the dot following an array type,
+ * a primitive type or an primitive array type.
+ * Returns whether we found a completion node.
+ */
+private boolean checkClassLiteralAccess() {
+       if (this.identifierLengthPtr >= 1 && this.previousToken == TokenNameDOT) { // (NB: the top id length is 1 and it is for the completion identifier)
+               int length;
+               // if the penultimate id length is negative, 
+               // the completion is after a primitive type or a primitive array type
+               if ((length = this.identifierLengthStack[this.identifierLengthPtr-1]) < 0) {
+                       // build the primitive type node
+                       int dim = this.isAfterArrayType() ? this.intStack[this.intPtr--] : 0;
+                       SingleTypeReference typeRef = (SingleTypeReference)TypeReference.baseTypeReference(-length, dim);
+                       typeRef.sourceStart = this.intStack[this.intPtr--];
+                       if (dim == 0) {
+                               typeRef.sourceEnd = this.intStack[this.intPtr--];
+                       } else {
+                               this.intPtr--;
+                               typeRef.sourceEnd = this.endPosition;
+                       }
+                       //typeRef.sourceEnd = typeRef.sourceStart + typeRef.token.length; // NB: It's ok to use the length of the token since it doesn't contain any unicode
+
+                       // find the completion identifier and its source positions
+                       char[] source = identifierStack[identifierPtr];
+                       long pos = this.identifierPositionStack[this.identifierPtr--];
+                       this.identifierLengthPtr--; // it can only be a simple identifier (so its length is one)
+
+                       // build the completion on class literal access node
+                       CompletionOnClassLiteralAccess access = new CompletionOnClassLiteralAccess(pos, typeRef);
+                       access.completionIdentifier = source;
+                       this.identifierLengthPtr--; // pop the length that was used to say it is a primitive type
+                       this.assistNode = access;
+                       this.isOrphanCompletionNode = true;
+                       return true;
+               }
+
+               // if the completion is after a regular array type
+               if (isAfterArrayType()) {
+                       // find the completion identifier and its source positions
+                       char[] source = identifierStack[identifierPtr];
+                       long pos = this.identifierPositionStack[this.identifierPtr--];
+                       this.identifierLengthPtr--; // it can only be a simple identifier (so its length is one)
+                       
+                       // get the type reference
+                       TypeReference typeRef = getTypeReference(this.intPtr--);
+                       
+                       // build the completion on class literal access node
+                       CompletionOnClassLiteralAccess access = new CompletionOnClassLiteralAccess(pos, typeRef);
+                       access.completionIdentifier = source;
+                       this.assistNode = access;
+                       this.isOrphanCompletionNode = true;
+                       return true;
+               }
+
+       }
+       return false;
+}
+/**
+ * Checks if the completion is inside a method invocation or a constructor invocation.
+ * Returns whether we found a completion node.
+ */
+private boolean checkInvocation() {
+       Expression topExpression = this.expressionPtr >= 0 ? 
+               this.expressionStack[this.expressionPtr] :
+               null;
+       boolean isEmptyNameCompletion = false;
+       boolean isEmptyAssistIdentifier = false;
+       int startInvocationPtr = this.blockInvocationPtr >= 0 ? this.blockInvocationStack[this.blockInvocationPtr] : 0;
+       if (this.invocationPtr >= startInvocationPtr
+               && ((isEmptyNameCompletion = topExpression == this.assistNode && this.isEmptyNameCompletion()) // eg. it is something like "this.fred([cursor]" but it is not something like "this.fred(1 + [cursor]"
+                       || (isEmptyAssistIdentifier = this.indexOfAssistIdentifier() >= 0 && this.identifierStack[this.identifierPtr].length == 0))) { // eg. it is something like "this.fred(1 [cursor]"
+                               
+               // pop empty name completion
+               if (isEmptyNameCompletion) {
+                       this.expressionPtr--;
+                       this.expressionLengthStack[this.expressionLengthPtr]--;
+               } else if (isEmptyAssistIdentifier) {
+                       this.identifierPtr--;
+                       this.identifierLengthPtr--;
+               }
+
+               // find receiver and qualifier
+               int invocationType = this.invocationTypeStack[this.invocationPtr];
+               int qualifierExprPtr = this.qualifierStack[this.invocationPtr];
+
+               // find arguments
+               int numArgs = this.expressionPtr - qualifierExprPtr;
+               int argStart = qualifierExprPtr + 1;
+               Expression[] arguments = null;
+               if (numArgs > 0) {
+                       // remember the arguments
+                       arguments = new Expression[numArgs];
+                       System.arraycopy(this.expressionStack, argStart, arguments, 0, numArgs);
+
+                       // consume the expression arguments
+                       this.expressionPtr -= numArgs;
+                       int count = numArgs;
+                       while (count > 0) {
+                               count -= this.expressionLengthStack[this.expressionLengthPtr--];
+                       } 
+               }
+
+               // build ast node
+               if (invocationType != ALLOCATION && invocationType != QUALIFIED_ALLOCATION) {
+                       // creates completion on message send   
+                       CompletionOnMessageSend messageSend = new CompletionOnMessageSend();
+                       messageSend.arguments = arguments;
+                       switch (invocationType) {
+                               case NO_RECEIVER:
+                                       // implicit this
+                                       messageSend.receiver = ThisReference.ThisImplicit;
+                                       break;
+                               case NAME_RECEIVER:
+                                       // remove special flags for primitive types
+                                       while (this.identifierLengthPtr >= 0 && this.identifierLengthStack[this.identifierLengthPtr] < 0) {
+                                               this.identifierLengthPtr--;
+                                       }
+                               
+                                       // remove selector 
+                                       this.identifierPtr--; 
+                                       this.identifierLengthStack[this.identifierLengthPtr]--;
+                                       // consume the receiver
+                                       messageSend.receiver = this.getUnspecifiedReference();
+                                       break;
+                               case SUPER_RECEIVER:
+                                       messageSend.receiver = SuperReference.Super;
+                                       break;
+                               case EXPLICIT_RECEIVER:
+                                       messageSend.receiver = this.expressionStack[qualifierExprPtr];
+                       }
+
+                       // set selector
+                       int selectorPtr = this.selectorStack[this.invocationPtr];
+                       messageSend.selector = this.identifierStack[selectorPtr];
+                       // remove selector
+                       if (this.identifierLengthPtr >=0 && this.identifierLengthStack[this.identifierLengthPtr] == 1) {
+                               this.identifierPtr--; 
+                               this.identifierLengthPtr--;
+                       }
+               
+                       // the entire message may be replaced in case qualification is needed
+                       messageSend.sourceStart = (int)(this.identifierPositionStack[selectorPtr] >> 32); //this.cursorLocation + 1;
+                       messageSend.sourceEnd = this.cursorLocation;
+
+                       // remember the message send as an orphan completion node
+                       this.assistNode = messageSend;
+                       this.lastCheckPoint = messageSend.sourceEnd + 1;
+                       this.isOrphanCompletionNode = true;
+                       return true;
+               } else {
+                       int selectorPtr = this.selectorStack[this.invocationPtr];
+                       if (selectorPtr == THIS_CONSTRUCTOR || selectorPtr == SUPER_CONSTRUCTOR) {
+                               // creates an explicit constructor call
+                               CompletionOnExplicitConstructorCall call = new CompletionOnExplicitConstructorCall(
+                                       (selectorPtr == THIS_CONSTRUCTOR) ? ExplicitConstructorCall.This : ExplicitConstructorCall.Super);
+                               call.arguments = arguments;
+                               if (invocationType == QUALIFIED_ALLOCATION) {
+                                       call.qualification = this.expressionStack[qualifierExprPtr];
+                               }
+               
+                               // no source is going to be replaced
+                               call.sourceStart = this.cursorLocation + 1;
+                               call.sourceEnd = this.cursorLocation;
+
+                               // remember the explicit constructor call as an orphan completion node
+                               this.assistNode = call;
+                               this.lastCheckPoint = call.sourceEnd + 1;
+                               this.isOrphanCompletionNode = true;
+                               return true;
+                       } else {
+                               // creates an allocation expression 
+                               CompletionOnQualifiedAllocationExpression allocExpr = new CompletionOnQualifiedAllocationExpression();
+                               allocExpr.arguments = arguments;
+                               allocExpr.type = super.getTypeReference(0); // we don't want a completion node here, so call super
+                               if (invocationType == QUALIFIED_ALLOCATION) {
+                                       allocExpr.enclosingInstance = this.expressionStack[qualifierExprPtr];
+                               }
+                               // no source is going to be replaced
+                               allocExpr.sourceStart = this.cursorLocation + 1;
+                               allocExpr.sourceEnd = this.cursorLocation;
+                               
+                               // remember the allocation expression as an orphan completion node
+                               this.assistNode = allocExpr;
+                               this.lastCheckPoint = allocExpr.sourceEnd + 1;
+                               this.isOrphanCompletionNode = true;
+                               return true;
+                       }
+               }
+       }
+       return false;
+}
+/**
+ * Checks if the completion is on a member access (ie. in an identifier following a dot).
+ * Returns whether we found a completion node.
+ */
+private boolean checkMemberAccess() {
+       if (this.previousToken == TokenNameDOT && this.qualifier > -1 && this.expressionPtr == this.qualifier) {
+               // the receiver is an expression
+               pushCompletionOnMemberAccessOnExpressionStack(false);
+               return true;
+       }
+       return false;
+}
+/**
+ * Checks if the completion is on a name reference.
+ * Returns whether we found a completion node.
+ */
+private boolean checkNameCompletion() {
+       /* 
+               We didn't find any other completion, but the completion identifier is on the identifier stack,
+               so it can only be a completion on name.
+               Note that we allow the completion on a name even if nothing is expected (eg. foo() b[cursor] would
+               be a completion on 'b'). This policy gives more to the user than he/she would expect, but this 
+               simplifies the problem. To fix this, the recovery must be changed to work at a 'statement' granularity
+               instead of at the 'expression' granularity as it does right now.
+       */ 
+       
+       // NB: at this point the completion identifier is on the identifier stack
+       this.assistNode = getUnspecifiedReferenceOptimized();
+       this.lastCheckPoint = this.assistNode.sourceEnd + 1;
+       this.isOrphanCompletionNode = true;
+       return true;
+}
+/**
+ * Checks if the completion is in the context of a method and on the type of one of its arguments
+ * Returns whether we found a completion node.
+ */
+private boolean checkRecoveredMethod() {
+       if (currentElement instanceof RecoveredMethod){
+               /* check if current awaiting identifier is the completion identifier */
+               if (this.indexOfAssistIdentifier() < 0) return false;
+
+               /* check if on line with an error already - to avoid completing inside 
+                       illegal type names e.g.  int[<cursor> */
+               if (lastErrorEndPosition <= cursorLocation+1
+                       && scanner.getLineNumber(lastErrorEndPosition) 
+                               == scanner.getLineNumber(((CompletionScanner)scanner).completedIdentifierStart)){
+                       return false;
+               }               
+               RecoveredMethod recoveredMethod = (RecoveredMethod)currentElement;
+               /* only consider if inside method header */
+               if (!recoveredMethod.foundOpeningBrace
+                       && lastIgnoredToken == -1) {
+                       //if (rParenPos < lParenPos){ // inside arguments
+                       this.assistNode = this.getTypeReference(0);
+                       this.lastCheckPoint = this.assistNode.sourceEnd + 1;
+                       this.isOrphanCompletionNode = true;
+                       return true;
+               }
+       }
+       return false;
+}
+/**
+ * Checks if the completion is in the context of a type and on a type reference in this type.
+ * Persists the identifier into a fake field return type
+ * Returns whether we found a completion node.
+ */
+private boolean checkRecoveredType() {
+       if (currentElement instanceof RecoveredType){
+               /* check if current awaiting identifier is the completion identifier */
+               if (this.indexOfAssistIdentifier() < 0) return false;
+
+               /* check if on line with an error already - to avoid completing inside 
+                       illegal type names e.g.  int[<cursor> */
+               if ((lastErrorEndPosition <= cursorLocation+1)
+                       && scanner.getLineNumber(lastErrorEndPosition) 
+                               == scanner.getLineNumber(((CompletionScanner)scanner).completedIdentifierStart)){
+                       return false;
+               }
+               RecoveredType recoveredType = (RecoveredType)currentElement;
+               /* filter out cases where scanner is still inside type header */
+               if (recoveredType.foundOpeningBrace) {
+                       this.assistNode = this.getTypeReference(0);
+                       this.lastCheckPoint = this.assistNode.sourceEnd + 1;
+                       this.isOrphanCompletionNode = true;
+                       return true;
+               }
+       }
+       return false;
+}
+/* 
+ * Check whether about to shift beyond the completion token.
+ * If so, depending on the context, a special node might need to be created
+ * and attached to the existing recovered structure so as to be remember in the
+ * resulting parsed structure.
+ */
+public void completionIdentifierCheck(){
+
+       if (checkRecoveredType()) return;
+       if (checkRecoveredMethod()) return;
+
+       // if not in a method in non diet mode and if not inside a field initializer, only record references attached to types
+       if (!(this.inMethodStack[this.inMethodPtr] && !this.diet)
+               && !insideFieldInitialization()) return; 
+
+       /*
+               In some cases, the completion identifier may not have yet been consumed,
+               e.g.  int.[cursor]
+               This is because the grammar does not allow any (empty) identifier to follow
+               a base type. We thus have to manually force the identifier to be consumed
+               (i.e. pushed).
+        */
+       if (assistIdentifier() == null && this.currentToken == TokenNameIdentifier) { // Test below copied from CompletionScanner.getCurrentIdentifierSource()
+               if (cursorLocation < this.scanner.startPosition && this.scanner.currentPosition == this.scanner.startPosition){ // fake empty identifier got issued
+                       this.pushIdentifier();                                  
+               } else if (cursorLocation+1 >= this.scanner.startPosition && cursorLocation < this.scanner.currentPosition){
+                       this.pushIdentifier();
+               }
+       }
+
+       // check for different scenarii
+       try {
+               // no need to go further if we found a non empty completion node
+               // (we still need to store labels though)
+               if (this.assistNode != null) {
+                       // however inside an invocation, the completion identifier may already have been consumed into an empty name 
+                       // completion, so this check should be before we check that we are at the cursor location
+                       if (!isEmptyNameCompletion() || checkInvocation()) return;
+               }
+
+               // no need to check further if we are not at the cursor location
+               if (this.indexOfAssistIdentifier() < 0) return;
+
+               if (checkClassInstanceCreation()) return;
+               if (checkCatchClause()) return;
+               if (checkMemberAccess()) return;
+               if (checkClassLiteralAccess()) return;
+
+               // if the completion was not on an empty name, it can still be inside an invocation (eg. this.fred("abc"[cursor])
+               // (NB: Put this check before checkNameCompletion() because the selector of the invocation can be on the identifier stack)
+               if (checkInvocation()) return;
+
+               if (checkNameCompletion()) return;
+       } finally {
+               storeLabelsIfNeeded();
+       }
+}
+protected void consumeCaseLabel() {
+       Expression caseExpression = this.expressionStack[this.expressionPtr];
+       if (caseExpression instanceof SingleNameReference || caseExpression instanceof QualifiedNameReference) {
+               // label counter was wrongly incremented in consumeToken
+               if (this.labelCounterPtr >= 0) this.labelCounterStack[this.labelCounterPtr]--;
+       }
+       super.consumeCaseLabel();
+}
+protected void consumeClassHeaderExtends() {
+       this.nextTypeReferenceIsClass = true;
+       super.consumeClassHeaderExtends();
+       this.nextTypeReferenceIsClass = false;
+}
+protected void consumeClassTypeElt() {
+       this.nextTypeReferenceIsException = true;
+       super.consumeClassTypeElt();
+       this.nextTypeReferenceIsException = false;
+}
+protected void consumeConditionalExpression(int op) {
+       Expression valueIfTrue = this.expressionStack[this.expressionPtr - 1];
+       if (valueIfTrue instanceof SingleNameReference || valueIfTrue instanceof QualifiedNameReference) {
+               // label counter was wrongly incremented in consumeToken
+               if (this.labelCounterPtr >= 0) this.labelCounterStack[this.labelCounterPtr]--;
+       }
+       super.consumeConditionalExpression(op);
+}
+protected void consumeConstructorBody() {
+       super.consumeConstructorBody();
+       this.labelCounterPtr--;
+       if (this.blockInvocationPtr >= 0) this.blockInvocationPtr--;
+}
+protected void consumeConstructorHeader() {
+       super.consumeConstructorHeader();
+       pushBlockInvocationPtr();
+}
+protected void consumeConstructorHeaderName() {
+
+       /* no need to take action if not inside assist identifiers */
+       if (indexOfAssistIdentifier() < 0) {
+               super.consumeConstructorHeaderName();
+               return;
+       }
+               
+       /* force to start recovering in order to get fake field behavior */
+       if (currentElement == null){
+               this.hasReportedError = true; // do not report any error
+       }
+       this.restartRecovery = true;
+}
+protected void consumeEnterVariable() {
+       identifierPtr--;
+       identifierLengthPtr--;
+
+       boolean isLocalDeclaration = nestedMethod[nestedType] != 0;
+       int variableIndex = variablesCounter[nestedType];
+       int extendedDimension = intStack[intPtr + 1];
+       
+       if(isLocalDeclaration || indexOfAssistIdentifier() < 0 || variableIndex != 0 || extendedDimension != 0) {
+               identifierPtr++;
+               identifierLengthPtr++;
+               super.consumeEnterVariable();
+       } else {
+               restartRecovery = true;
+               
+               // recovery
+               if (currentElement != null) {
+                       int nameSourceStart = (int)(identifierPositionStack[identifierPtr] >>> 32);
+                       intPtr--;
+                       
+                       TypeReference type = getTypeReference(intStack[intPtr--]);
+                       intPtr--;
+                       
+                       if (!(currentElement instanceof RecoveredType)
+                               && (currentToken == TokenNameDOT
+                                       || (scanner.getLineNumber(type.sourceStart)
+                                                       != scanner.getLineNumber(nameSourceStart)))){
+                               lastCheckPoint = nameSourceStart;
+                               restartRecovery = true;
+                               return;
+                       }
+                       
+                       FieldDeclaration completionFieldDecl = new CompletionOnFieldType(type, false);
+                       completionFieldDecl.modifiers = intStack[intPtr--];
+                       assistNode = completionFieldDecl;
+                       lastCheckPoint = type.sourceEnd + 1;
+                       currentElement = currentElement.add(completionFieldDecl, 0);
+                       lastIgnoredToken = -1;
+               }
+       }
+}
+protected void consumeExitVariableWithInitialization() {
+       super.consumeExitVariableWithInitialization();
+       
+       // does not keep the initialization if completion is not inside
+       AbstractVariableDeclaration variable = (AbstractVariableDeclaration) astStack[astPtr];
+       if (cursorLocation + 1 < variable.initialization.sourceStart ||
+               cursorLocation > variable.initialization.sourceEnd) {
+               variable.initialization = null;
+       }
+}
+
+/*
+ * Copy of code from superclass with the following change:
+ * If the cursor location is on the field access, then create a 
+ * CompletionOnMemberAccess instead.
+ */
+protected void consumeFieldAccess(boolean isSuperAccess) {
+       // FieldAccess ::= Primary '.' 'Identifier'
+       // FieldAccess ::= 'super' '.' 'Identifier'
+
+       // potential receiver is being poped, so reset potential receiver
+       this.invocationType = NO_RECEIVER;
+
+       if (this.indexOfAssistIdentifier() < 0) {
+               super.consumeFieldAccess(isSuperAccess);
+       } else {
+               this.pushCompletionOnMemberAccessOnExpressionStack(isSuperAccess);
+       }
+}
+
+protected void consumeFormalParameter() {
+       if (this.indexOfAssistIdentifier() < 0) {
+               super.consumeFormalParameter();
+       } else {
+
+               identifierLengthPtr--;
+               char[] name = identifierStack[identifierPtr];
+               long namePositions = identifierPositionStack[identifierPtr--];
+               TypeReference type = getTypeReference(intStack[intPtr--] + intStack[intPtr--]);
+               intPtr -= 2;
+               Argument arg = 
+                       new CompletionOnArgumentName(
+                               name, 
+                               namePositions, 
+                               type, 
+                               intStack[intPtr + 1] & ~AccDeprecated); // modifiers
+               pushOnAstStack(arg);
+               
+               assistNode = arg;
+               this.lastCheckPoint = (int) namePositions;
+               isOrphanCompletionNode = true;
+
+               /* if incomplete method header, listLength counter will not have been reset,
+                       indicating that some arguments are available on the stack */
+               listLength++;
+       }       
+}
+protected void consumeInterfaceType() {
+       this.nextTypeReferenceIsInterface = true;
+       super.consumeInterfaceType();
+       this.nextTypeReferenceIsInterface = false;
+}
+protected void consumeMethodHeaderName() {
+       if(this.indexOfAssistIdentifier() < 0) {
+               identifierPtr--;
+               identifierLengthPtr--;
+               if(this.indexOfAssistIdentifier() != 0) {
+                       identifierPtr++;
+                       identifierLengthPtr++;
+                       super.consumeMethodHeaderName();
+               } else {
+                       restartRecovery = true;
+                       
+                       // recovery
+                       if (currentElement != null) {
+                               //name
+                               char[] selector = identifierStack[identifierPtr + 1];
+                               long selectorSource = identifierPositionStack[identifierPtr + 1];
+                               
+                               //type
+                               TypeReference type = getTypeReference(intStack[intPtr--]);
+                               ((CompletionOnSingleTypeReference)type).isCompletionNode = false;
+                               //modifiers
+                               int declarationSourceStart = intStack[intPtr--];
+                               int modifiers = intStack[intPtr--];
+                               
+                               if(scanner.getLineNumber(type.sourceStart) != scanner.getLineNumber((int) (selectorSource >>> 32))) {
+                                       FieldDeclaration completionFieldDecl = new CompletionOnFieldType(type, false);
+                                       completionFieldDecl.modifiers = modifiers;
+                                       assistNode = completionFieldDecl;
+                                       lastCheckPoint = type.sourceEnd + 1;
+                                       currentElement = currentElement.add(completionFieldDecl, 0);
+                                       lastIgnoredToken = -1;
+                               } else {
+                                       CompletionOnMethodReturnType md = new CompletionOnMethodReturnType(type, this.compilationUnit.compilationResult);
+                                       md.selector = selector;
+                                       md.declarationSourceStart = declarationSourceStart;
+                                       md.modifiers = modifiers;
+                                       md.bodyStart = lParenPos+1;
+                                       listLength = 0; // initialize listLength before reading parameters/throws
+                                       assistNode = md;
+                                       this.lastCheckPoint = md.bodyStart;
+                                       currentElement = currentElement.add(md, 0);
+                                       lastIgnoredToken = -1;
+                               }
+                       }
+               }
+       } else {
+               // MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
+               CompletionOnMethodName md = new CompletionOnMethodName(this.compilationUnit.compilationResult);
+       
+               //name
+               md.selector = identifierStack[identifierPtr];
+               long selectorSource = identifierPositionStack[identifierPtr--];
+               //type
+               md.returnType = getTypeReference(intStack[intPtr--]);
+               //modifiers
+               md.declarationSourceStart = intStack[intPtr--];
+               md.modifiers = intStack[intPtr--];
+       
+               //highlight starts at selector start
+               md.sourceStart = (int) (selectorSource >>> 32);
+               md.selectorEnd = (int) selectorSource;
+               pushOnAstStack(md);
+               md.sourceEnd = lParenPos;
+               md.bodyStart = lParenPos+1;
+               listLength = 0; // initialize listLength before reading parameters/throws
+               
+               this.assistNode = md;   
+               this.lastCheckPoint = md.sourceEnd;
+               // recovery
+               if (currentElement != null){
+                       if (currentElement instanceof RecoveredType 
+                               //|| md.modifiers != 0
+                               || (scanner.getLineNumber(md.returnType.sourceStart)
+                                               == scanner.getLineNumber(md.sourceStart))){
+                               lastCheckPoint = md.bodyStart;
+                               currentElement = currentElement.add(md, 0);
+                               lastIgnoredToken = -1;
+                       } else {
+                               lastCheckPoint = md.sourceStart;
+                               restartRecovery = true;
+                       }
+               }
+       }
+}
+
+
+protected void consumeMethodBody() {
+       super.consumeMethodBody();
+       this.labelCounterPtr--;
+       if (this.blockInvocationPtr >= 0) this.blockInvocationPtr--;
+}
+
+protected void consumeMethodHeader() {
+       super.consumeMethodHeader();
+       pushBlockInvocationPtr();
+}
+protected void consumeModifiers() {
+       super.consumeModifiers();
+       // save from stack values
+       this.lastModifiersStart = intStack[intPtr];
+       this.lastModifiers =    intStack[intPtr-1];
+}
+protected void consumeNestedMethod() {
+       super.consumeNestedMethod();
+       this.pushNewLabelCounter();
+}
+protected void consumeStatementLabel() {
+       super.consumeStatementLabel();
+       if (this.labelCounterPtr >= 0) this.labelCounterStack[this.labelCounterPtr]--;
+}
+protected void consumeToken(int token) {
+       int previous = this.previousToken;
+       int previousIdentifierPtr = this.previousIdentifierPtr;
+       super.consumeToken(token);
+
+       // if in field initializer (directly or not), on the completion identifier and not in recovery mode yet
+       // then position end of file at cursor location (so that we have the same behavior as
+       // in method bodies)
+       if (token == TokenNameIdentifier
+                       && this.identifierStack[this.identifierPtr] == assistIdentifier()
+                       && this.currentElement == null
+                       && this.insideFieldInitialization()) {
+               this.scanner.eofPosition = cursorLocation < Integer.MAX_VALUE ? cursorLocation+1 : cursorLocation;
+       }
+       
+       // if in a method or if in a field initializer 
+       if (this.inMethodStack[this.inMethodPtr] || this.inFieldInitializationStack[this.inFieldInitializationPtr]) {
+               switch (token) {
+                       case TokenNameDOT:
+                               switch (previous) {
+//                                     case TokenNamethis: // eg. this[.]fred()
+//                                             this.invocationType = EXPLICIT_RECEIVER;
+//                                             break;
+//                                     case TokenNamesuper: // eg. super[.]fred()
+//                                             this.invocationType = SUPER_RECEIVER;
+//                                             break;
+                                       case TokenNameIdentifier: // eg. bar[.]fred()
+                                               if (!this.betweenNewAndLeftBraket) { // eg. not new z.y[.]X()
+                                                       if (this.identifierPtr != previousIdentifierPtr) { // if identifier has been consumed, eg. this.x[.]fred()
+                                                               this.invocationType = EXPLICIT_RECEIVER;
+                                                       } else {
+                                                               this.invocationType = NAME_RECEIVER;
+                                                       }
+                                               }
+                                               break;
+                               }
+                               break;
+                       case TokenNameIdentifier:
+                               if (previous == TokenNameDOT) { // eg. foo().[fred]()
+                                       // if current identifier is the empty completion one
+                                       if (identifierStack[identifierPtr] == CompletionScanner.EmptyCompletionIdentifier){
+                                               this.completionBehindDot = true;
+                                       }
+                                       if (this.invocationType != SUPER_RECEIVER // eg. not super.[fred]()
+                                               && this.invocationType != NAME_RECEIVER // eg. not bar.[fred]()
+                                               && this.invocationType != ALLOCATION // eg. not new foo.[Bar]()
+                                               && this.invocationType != QUALIFIED_ALLOCATION) { // eg. not fred().new foo.[Bar]()
+
+                                               this.invocationType = EXPLICIT_RECEIVER;
+                                               this.qualifier = this.expressionPtr;
+                                       }
+                               }
+                               break;  
+                       case TokenNamenew:
+                               this.betweenNewAndLeftBraket = true;
+                               this.qualifier = this.expressionPtr; // NB: even if there is no qualification, set it to the expression ptr so that the number of arguments are correctly computed
+                               if (previous == TokenNameDOT) { // eg. fred().[new] X()
+                                       this.invocationType = QUALIFIED_ALLOCATION;
+                               } else { // eg. [new] X()
+                                       this.invocationType = ALLOCATION;
+                               }
+                               break;
+//                     case TokenNamethis:
+//                             if (previous == TokenNameDOT) { // eg. fred().[this]()
+//                                     this.invocationType = QUALIFIED_ALLOCATION;
+//                                     this.qualifier = this.expressionPtr;
+//                             }
+//                             break;
+//                     case TokenNamesuper:
+//                             if (previous == TokenNameDOT) { // eg. fred().[super]()
+//                                     this.invocationType = QUALIFIED_ALLOCATION;
+//                                     this.qualifier = this.expressionPtr;
+//                             }
+//                             break;
+//                     case TokenNamecatch:
+//                             this.betweenCatchAndRightParen = true;
+//                             break;
+                       case TokenNameLPAREN:
+                               this.betweenNewAndLeftBraket = false;
+                               this.bracketDepth++;
+                               if (this.invocationType == NO_RECEIVER || this.invocationType == NAME_RECEIVER) {
+                                       this.qualifier = this.expressionPtr; // remenber the last expression so that arguments are correctly computed
+                               }
+                               switch (previous) {
+                                       case TokenNameIdentifier: // eg. fred[(]) or foo.fred[(])
+                                               this.pushOnInvocationStacks(this.invocationType, this.qualifier);
+                                               this.invocationType = NO_RECEIVER;
+                                               break;
+//                                     case TokenNamethis: // explicit constructor invocation, eg. this[(]1, 2)
+//                                             this.pushOnInvocationStacks(
+//                                                     (this.invocationType == QUALIFIED_ALLOCATION) ? QUALIFIED_ALLOCATION : ALLOCATION, 
+//                                                     this.qualifier);
+//                                             this.invocationType = NO_RECEIVER;
+//                                             break;
+//                                     case TokenNamesuper: // explicit constructor invocation, eg. super[(]1, 2)
+//                                             this.pushOnInvocationStacks(
+//                                                     (this.invocationType == QUALIFIED_ALLOCATION) ? QUALIFIED_ALLOCATION : ALLOCATION, 
+//                                                     this.qualifier);
+//                                             this.invocationType = NO_RECEIVER;
+//                                             break;
+                               }
+                               break;
+                       case TokenNameLBRACE:
+                               this.betweenNewAndLeftBraket = false;
+                               this.bracketDepth++;
+                               this.pushBlockInvocationPtr();
+                               break;
+                       case TokenNameLBRACKET:
+                               this.betweenNewAndLeftBraket = false;
+                               this.bracketDepth++;
+                               break; 
+                       case TokenNameRBRACE:
+                               this.bracketDepth--;
+                               if (this.blockInvocationPtr >= 0) this.blockInvocationPtr--;
+                               break;
+                       case TokenNameRBRACKET:
+                               this.bracketDepth--;
+                               break; 
+                       case TokenNameRPAREN:
+                               this.betweenCatchAndRightParen = false;
+                               this.bracketDepth--;
+                               break;
+                       case TokenNameCOLON:
+                               if (previous == TokenNameIdentifier) {
+                                       if (this.labelCounterPtr >= 0) this.labelCounterStack[this.labelCounterPtr]++;
+                               }
+                               break;
+//                     case TokenNamethrow:
+//                             this.throwBracketDepth= bracketDepth;
+//                             break;
+               }
+       }
+}
+/**
+ * Return whether the given ast node contains the completion node.
+ */
+private boolean containsCompletionNode(AstNode ast) {
+       if (this.assistNode == null || ast instanceof Literal) {
+               return false;
+       }
+       if (this.assistNode == ast) {
+               return true;
+       }
+       if (ast instanceof Reference || ast instanceof TypeReference) {
+               return ast == this.assistNode;
+       }
+       if (ast instanceof Assignment) {
+               Assignment assign = (Assignment)ast;
+               return containsCompletionNode(assign.lhs) || containsCompletionNode(assign.expression);
+       }
+       if (ast instanceof UnaryExpression) {
+               UnaryExpression unary = (UnaryExpression)ast;
+               return containsCompletionNode(unary.expression);
+       }
+       if (ast instanceof BinaryExpression) {
+               BinaryExpression binary = (BinaryExpression)ast;
+               return containsCompletionNode(binary.left) || containsCompletionNode(binary.right);
+       }
+       if (ast instanceof InstanceOfExpression) {
+               InstanceOfExpression instanceOfExpr = (InstanceOfExpression)ast;
+               return containsCompletionNode(instanceOfExpr.expression) || containsCompletionNode(instanceOfExpr.type);
+       }
+       if (ast instanceof ConditionalExpression) {
+               ConditionalExpression conditional = (ConditionalExpression)ast;
+               return containsCompletionNode(conditional.condition) || containsCompletionNode(conditional.valueIfTrue) || containsCompletionNode(conditional.valueIfFalse);
+       }
+       if (ast instanceof AllocationExpression) {
+               AllocationExpression alloc = (AllocationExpression)ast;
+               return containsCompletionNode(alloc.type);
+       }
+       if (ast instanceof CastExpression) {
+               CastExpression cast = (CastExpression)ast;
+               return containsCompletionNode(cast.expression) || containsCompletionNode(cast.type);
+       }
+       if (ast instanceof ExplicitConstructorCall) {
+               ExplicitConstructorCall call = (ExplicitConstructorCall)ast;
+               Expression[] arguments = call.arguments;
+               if (arguments != null) {
+                       for (int i = 0; i < arguments.length; i++) {
+                               if (containsCompletionNode(arguments[i])) {
+                                       return true;
+                               }
+                       }
+                       return false;
+               }
+       }
+       return false;
+}
+public ImportReference createAssistImportReference(char[][] tokens, long[] positions){
+       return new CompletionOnImportReference(tokens, positions);
+}
+public ImportReference createAssistPackageReference(char[][] tokens, long[] positions){
+       return new CompletionOnPackageReference(tokens, positions);
+}
+public NameReference createQualifiedAssistNameReference(char[][] previousIdentifiers, char[] name, long[] positions){
+       return new CompletionOnQualifiedNameReference(
+                                       previousIdentifiers, 
+                                       name, 
+                                       positions);     
+}
+public TypeReference createQualifiedAssistTypeReference(char[][] previousIdentifiers, char[] name, long[] positions){
+       return this.betweenCatchAndRightParen || this.nextTypeReferenceIsException // check for exception scenario 
+                               ? new CompletionOnQualifiedExceptionReference(
+                                       previousIdentifiers,  
+                                       name, 
+                                       positions)
+                               : this.nextTypeReferenceIsInterface
+                                       ? new CompletionOnQualifiedInterfaceReference(
+                                               previousIdentifiers, 
+                                               name, 
+                                               positions)
+                                       : this.nextTypeReferenceIsClass
+                                               ? new CompletionOnQualifiedClassReference(
+                                                       previousIdentifiers, 
+                                                       name, 
+                                                       positions)
+                                               : new CompletionOnQualifiedTypeReference(
+                                                       previousIdentifiers, 
+                                                       name, 
+                                                       positions);     
+}
+public NameReference createSingleAssistNameReference(char[] name, long position) {
+       return new CompletionOnSingleNameReference(name, position);
+}
+public TypeReference createSingleAssistTypeReference(char[] name, long position) {
+       return this.betweenCatchAndRightParen || this.nextTypeReferenceIsException // check for exception scenario 
+               ? new CompletionOnExceptionReference(name, position) 
+               : this.nextTypeReferenceIsInterface
+                       ? new CompletionOnInterfaceReference(name, position) 
+                       : this.nextTypeReferenceIsClass
+                               ? new CompletionOnClassReference(name, position) 
+                               : new CompletionOnSingleTypeReference(name, position);
+}
+public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int cursorLocation) {
+
+       this.cursorLocation = cursorLocation;
+       CompletionScanner completionScanner = (CompletionScanner)this.scanner;
+       completionScanner.completionIdentifier = null;
+       completionScanner.cursorLocation = cursorLocation;
+       return this.dietParse(sourceUnit, compilationResult);
+}
+/*
+ * Flush parser/scanner state regarding to code assist
+ */
+public void flushAssistState() {
+
+       super.flushAssistState();
+       this.isOrphanCompletionNode = false;
+       CompletionScanner completionScanner = (CompletionScanner)this.scanner;
+       completionScanner.completedIdentifierStart = 0;
+       completionScanner.completedIdentifierEnd = -1;
+}
+protected NameReference getUnspecifiedReferenceOptimized() {
+       if (this.identifierLengthStack[this.identifierLengthPtr] > 1) { // reducing a qualified name
+               // potential receiver is being poped, so reset potential receiver
+               this.invocationType = NO_RECEIVER;
+       }
+       return super.getUnspecifiedReferenceOptimized();
+}
+/**
+ * Return whether the given ast node has information interresting for code completion.
+ */
+private boolean hasCompletionInformation(AstNode ast) {
+       return (
+               ast instanceof AbstractMethodDeclaration ||
+               ast instanceof AbstractVariableDeclaration ||
+               ast instanceof LabeledStatement ||
+               ast instanceof TypeDeclaration);
+}
+public void initialize() {
+       super.initialize();
+       this.initializeForBlockStatements();
+       this.labelCounterPtr = -1;
+}
+/*
+ * Initializes the state of the parser that is about to go for BlockStatements.
+ */
+private void initializeForBlockStatements() {
+       this.previousToken = -1;
+       this.previousIdentifierPtr = -1;
+       this.completionBehindDot = false;
+       this.betweenNewAndLeftBraket = false;
+       this.betweenCatchAndRightParen = false;
+       this.bracketDepth = 0;
+       this.throwBracketDepth = -1;
+       this.invocationType = NO_RECEIVER;
+       this.qualifier = -1;
+       this.blockInvocationPtr = -1;
+}
+public void initializeScanner(){
+       this.scanner = new CompletionScanner(this.assertMode);
+}
+/**
+ * Returns whether the completion is just after an array type
+ * eg. String[].[cursor]
+ */
+private boolean isAfterArrayType() {
+       // TBD: The following relies on the fact that array dimensions are small: it says that if the
+       //      top of the intStack is less than 11, then it must be a dimension 
+       //      (smallest position of array type in a compilation unit is 11 as in "class X{Y[]")
+       if ((this.intPtr > -1) && (this.intStack[this.intPtr] < 11)) {
+               return true;
+       }
+       return false;
+}
+private boolean isEmptyNameCompletion() {
+       return
+               this.assistNode != null && 
+               this.assistNode instanceof CompletionOnSingleNameReference &&
+               (((CompletionOnSingleNameReference)this.assistNode).token.length == 0);
+}
+public CompilationUnitDeclaration parse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int cursorLocation) {
+
+       this.cursorLocation = cursorLocation;
+       CompletionScanner completionScanner = (CompletionScanner)this.scanner;
+       completionScanner.completionIdentifier = null;
+       completionScanner.cursorLocation = cursorLocation;
+       return this.parse(sourceUnit, compilationResult);
+}
+/*
+ * Prepares the state of the parser to go for BlockStatements.
+ */
+protected void prepareForBlockStatements() {
+       super.prepareForBlockStatements();
+       this.initializeForBlockStatements();
+}
+protected void pushBlockInvocationPtr() {
+       try {
+               this.blockInvocationStack[++this.blockInvocationPtr] = this.invocationPtr+1;
+       } catch (IndexOutOfBoundsException e) {
+               int oldStackLength = this.blockInvocationStack.length;
+               int[] oldStack = this.blockInvocationStack;
+               this.blockInvocationStack = new int[oldStackLength + StackIncrement];
+               System.arraycopy(oldStack, 0, this.blockInvocationStack, 0, oldStackLength);
+               this.blockInvocationStack[this.blockInvocationPtr] = this.invocationPtr+1;
+       }
+}
+/**
+ * Creates a completion on member access node and push it
+ * on the expression stack.
+ */
+private void pushCompletionOnMemberAccessOnExpressionStack(boolean isSuperAccess) {
+       char[] source = identifierStack[identifierPtr];
+       long pos = identifierPositionStack[identifierPtr--];
+       CompletionOnMemberAccess fr = new CompletionOnMemberAccess(source, pos);
+       this.assistNode = fr;
+       this.lastCheckPoint = fr.sourceEnd + 1;
+       identifierLengthPtr--;
+       if (isSuperAccess) { //considerates the fieldReference beginning at the 'super' ....    
+               fr.sourceStart = intStack[intPtr--];
+               fr.receiver = new SuperReference(fr.sourceStart, endPosition);
+               pushOnExpressionStack(fr);
+       } else { //optimize push/pop
+               if ((fr.receiver = expressionStack[expressionPtr]).isThis()) { //fieldreference begins at the this
+                       fr.sourceStart = fr.receiver.sourceStart;
+               }
+               expressionStack[expressionPtr] = fr;
+       }
+}
+protected void pushNewLabelCounter() {
+       try {
+               this.labelCounterStack[++this.labelCounterPtr] = 0;
+       } catch (IndexOutOfBoundsException e) {
+               int oldStackLength = this.labelCounterStack.length;
+               int[] oldStack = this.labelCounterStack;
+               this.labelCounterStack = new int[oldStackLength + StackIncrement];
+               System.arraycopy(oldStack, 0, this.labelCounterStack, 0, oldStackLength);
+               this.labelCounterStack[this.labelCounterPtr] = 0;
+       }
+}
+/**
+ * Pushes the given invocation type (one of the invocation type constants) on the invocation type stack,
+ * and the given qualifier (an expression pointer to the expression stack) on the qualifier stack.
+ */
+protected void pushOnInvocationStacks(int invocationType, int qualifierExprPtr) {
+       // NB: invocationPtr has already been incremented by a call to pushOnSelectorStack()
+       try {
+               this.invocationTypeStack[this.invocationPtr] = invocationType;
+               this.qualifierStack[this.invocationPtr] = qualifierExprPtr;
+       } catch (IndexOutOfBoundsException e) {
+               int oldStackLength = this.invocationTypeStack.length;
+               int oldInvocationTypeStack[] = this.invocationTypeStack;
+               int oldQualifierStack[] = this.qualifierStack;
+               this.invocationTypeStack = new int[oldStackLength + StackIncrement];
+               this.qualifierStack = new int[oldStackLength + StackIncrement];
+               System.arraycopy(oldInvocationTypeStack, 0, this.invocationTypeStack, 0, oldStackLength);
+               System.arraycopy(oldQualifierStack, 0, this.qualifierStack, 0, oldStackLength);
+               this.invocationTypeStack[this.invocationPtr] = invocationType;
+               this.qualifierStack[this.invocationPtr] = qualifierExprPtr;
+       }
+}
+public void recordCompletionOnReference(){
+
+       if (currentElement instanceof RecoveredType){
+               RecoveredType recoveredType = (RecoveredType)currentElement;
+
+               /* filter out cases where scanner is still inside type header */
+               if (!recoveredType.foundOpeningBrace) return;
+               
+               /* generate a pseudo field with a completion on type reference */       
+               currentElement.add(
+                       new CompletionOnFieldType(this.getTypeReference(0), false), 0);
+               return;
+       }
+       if (!diet) return; // only record references attached to types
+
+}
+protected void reportSyntaxError(int act, int currentKind, int stateStackTop) {
+
+       /* Intercept error state on EOF inside method bodies, due to 
+          cursor location being used as an EOF position.
+       */
+       if (!diet && currentToken == TokenNameEOF) return;
+       super.reportSyntaxError(act, currentKind, stateStackTop);
+}
+/*
+ * Reset internal state after completion is over
+ */
+public void reset() {
+       super.reset();
+       this.cursorLocation = 0;
+}
+/*
+ * Reset internal state after completion is over
+ */
+public void resetAfterCompletion() {
+       this.cursorLocation = 0;
+       this.flushAssistState();
+}
+/*
+ * Reset context so as to resume to regular parse loop
+ * If unable to reset for resuming, answers false.
+ *
+ * Move checkpoint location, reset internal stacks and
+ * decide which grammar goal is activated.
+ */
+protected boolean resumeAfterRecovery() {
+       if (this.assistNode != null) {
+               /* if reached [eof] inside method body, but still inside nested type,
+                       or inside a field initializer, should continue in diet mode until 
+                       the end of the method body or compilation unit */
+               if ((scanner.eofPosition == cursorLocation+1)
+                       && (!(referenceContext instanceof CompilationUnitDeclaration) 
+                               || insideFieldInitialization())) {
+
+                       /*      disabled since does not handle possible field/message refs, i.e. Obj[ASSIST HERE]ect.registerNatives()              
+                       // consume extra tokens which were part of the qualified reference
+                       //   so that the replaced source comprises them as well 
+                       if (this.assistNode instanceof NameReference){
+                               int oldEof = scanner.eofPosition;
+                               scanner.eofPosition = currentElement.topElement().sourceEnd()+1;
+                               scanner.currentPosition = this.cursorLocation+1;
+                               int token = -1;
+                               try {
+                                       do {
+                                               // first token might not have to be a dot
+                                               if (token >= 0 || !this.completionBehindDot){
+                                                       if ((token = scanner.getNextToken()) != TokenNameDOT) break;
+                                               }
+                                               if ((token = scanner.getNextToken()) != TokenNameIdentifier) break;
+                                               this.assistNode.sourceEnd = scanner.currentPosition - 1;
+                                       } while (token != TokenNameEOF);
+                               } catch (InvalidInputException e){
+                               } finally {
+                                       scanner.eofPosition = oldEof;
+                               }
+                       }
+                       */                      
+                       /* restart in diet mode for finding sibling constructs */
+                       if (currentElement.enclosingType() != null){
+                               lastCheckPoint = this.assistNode.sourceEnd+1;
+                               int end = currentElement.topElement().sourceEnd();
+                               scanner.eofPosition = end < Integer.MAX_VALUE ? end + 1 : end;
+                       } else {
+                               this.resetStacks();
+                               return false;   
+                       }
+               }
+       }
+       return super.resumeAfterRecovery();
+}
+public void setAssistIdentifier(char[] assistIdent){
+       ((CompletionScanner)scanner).completionIdentifier = assistIdent;
+}
+/**
+ * Stores the labels left on the identifier stack if they have not been stored yet.
+ */
+private void storeLabelsIfNeeded() {
+//     int counter = this.labelCounterPtr >= 0 ? this.labelCounterStack[this.labelCounterPtr] : 0;
+//     if (this.labels == null && this.identifierPtr >= 0) {
+//             this.labels = new char[counter][];
+//             System.arraycopy(this.identifierStack, this.identifierPtr - counter + 1, this.labels, 0, counter);
+//     }
+//     this.identifierPtr -= counter;
+//     this.identifierLengthPtr -= counter; // labels have not been concatenated yet
+}
+/*
+ * Update recovery state based on current parser/scanner state
+ */
+protected void updateRecoveryState() {
+
+       /* expose parser state to recovery state */
+       currentElement.updateFromParserState();
+
+       /* may be able to retrieve completionNode as an orphan, and then attach it */
+       this.completionIdentifierCheck();
+       this.attachOrphanCompletionNode();
+       
+       // if an assist node has been found and a recovered element exists,
+       // mark enclosing blocks as to be preserved
+       if (this.assistNode != null && this.currentElement != null) {
+               currentElement.preserveEnclosingBlocks();
+       }
+       
+       /* check and update recovered state based on current token,
+               this action is also performed when shifting token after recovery
+               got activated once. 
+       */
+       this.recoveryTokenCheck();
+}
+
+protected LocalDeclaration createLocalDeclaration(Expression initialization, char[] name, int sourceStart, int sourceEnd) {
+       if (this.indexOfAssistIdentifier() < 0) {
+               return super.createLocalDeclaration(initialization, name, sourceStart, sourceEnd);
+       } else {
+               CompletionOnLocalName local = new CompletionOnLocalName(initialization, name, sourceStart, sourceEnd);
+               this.assistNode = local;
+               this.lastCheckPoint = sourceEnd + 1;
+               return local;
+       }
+}
+
+protected FieldDeclaration createFieldDeclaration(Expression initialization, char[] name, int sourceStart, int sourceEnd) {
+       if (this.indexOfAssistIdentifier() < 0) {
+               return super.createFieldDeclaration(initialization, name, sourceStart, sourceEnd);
+       } else {
+               CompletionOnFieldName field = new CompletionOnFieldName(initialization, name, sourceStart, sourceEnd);
+               this.assistNode = field;
+               this.lastCheckPoint = sourceEnd + 1;
+               return field;
+       }
+}
+
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionScanner.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/CompletionScanner.java
new file mode 100644 (file)
index 0000000..d3b2156
--- /dev/null
@@ -0,0 +1,707 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.complete;
+
+/*
+ * Scanner aware of a cursor location so as to discard trailing portions of identifiers
+ * containing the cursor location.
+ *
+ * Cursor location denotes the position of the last character behind which completion
+ * got requested:
+ *  -1 means completion at the very beginning of the source
+ *     0  means completion behind the first character
+ *  n  means completion behind the n-th character
+ */
+import net.sourceforge.phpdt.core.compiler.InvalidInputException;
+import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
+
+public class CompletionScanner extends Scanner {
+
+       public char[] completionIdentifier;
+       public int cursorLocation;
+               
+       /* Source positions of the completedIdentifier
+        * if inside actual identifier, end goes to the actual identifier 
+        * end, i.e. beyond cursor location
+        */
+       public int completedIdentifierStart = 0;
+       public int completedIdentifierEnd = -1;
+
+       public static final char[] EmptyCompletionIdentifier = {};
+public CompletionScanner(boolean assertMode) {
+       super(false, false, false, assertMode);
+}
+/* 
+ * Truncate the current identifier if it is containing the cursor location. Since completion is performed
+ * on an identifier prefix.
+ *
+ */
+public char[] getCurrentIdentifierSource() {
+
+       if (completionIdentifier == null){
+               if (cursorLocation < startPosition && currentPosition == startPosition){ // fake empty identifier got issued
+                       // remember actual identifier positions
+                       completedIdentifierStart = startPosition;
+                       completedIdentifierEnd = completedIdentifierStart - 1;                  
+                       return completionIdentifier = EmptyCompletionIdentifier;                                        
+               }
+               if (cursorLocation+1 >= startPosition && cursorLocation < currentPosition){
+                       // remember actual identifier positions
+                       completedIdentifierStart = startPosition;
+                       completedIdentifierEnd = currentPosition - 1;
+                       if (withoutUnicodePtr != 0){                    // check unicode scenario
+                               System.arraycopy(withoutUnicodeBuffer, 1, completionIdentifier = new char[withoutUnicodePtr], 0, withoutUnicodePtr);
+                       } else {
+                               int length = cursorLocation + 1 - startPosition;
+                               // no char[] sharing around completionIdentifier, we want it to be unique so as to use identity checks  
+                               System.arraycopy(source, startPosition, (completionIdentifier = new char[length]), 0, length);
+                       }
+                       return completionIdentifier;
+               }
+       }
+       return super.getCurrentIdentifierSource();
+}
+/* 
+ * Identifier splitting for unicodes.
+ * Only store the current unicode if we did not pass the cursorLocation.
+ * Note: this does not handle cases where the cursor is in the middle of a unicode
+ */
+public boolean getNextCharAsJavaIdentifierPart() {
+
+       int temp = currentPosition;
+       try {
+               if (((currentCharacter = source[currentPosition++]) == '\\')
+                       && (source[currentPosition] == 'u')) {
+                       //-------------unicode traitement ------------
+                       int c1, c2, c3, c4;
+                       int unicodeSize = 6;
+                       currentPosition++;
+                       while (source[currentPosition] == 'u') {
+                               currentPosition++;
+                               unicodeSize++;
+                       }
+
+                       if (((c1 = Character.getNumericValue(source[currentPosition++])) > 15
+                               || c1 < 0)
+                               || ((c2 = Character.getNumericValue(source[currentPosition++])) > 15 || c2 < 0)
+                               || ((c3 = Character.getNumericValue(source[currentPosition++])) > 15 || c3 < 0)
+                               || ((c4 = Character.getNumericValue(source[currentPosition++])) > 15 || c4 < 0)) {
+                               currentPosition = temp;
+                               return false;
+                       }
+
+                       currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+                       if (!Character.isJavaIdentifierPart(currentCharacter)) {
+                               currentPosition = temp;
+                               return false;
+                       }
+
+                       //need the unicode buffer
+                       if (withoutUnicodePtr == 0) {
+                               //buffer all the entries that have been left aside....
+                               withoutUnicodePtr = currentPosition - unicodeSize - startPosition;
+                               System.arraycopy(
+                                       source, 
+                                       startPosition, 
+                                       withoutUnicodeBuffer, 
+                                       1, 
+                                       withoutUnicodePtr); 
+                       }
+                       if (temp < cursorLocation && cursorLocation < currentPosition-1){
+                               throw new InvalidCursorLocation(InvalidCursorLocation.NO_COMPLETION_INSIDE_UNICODE);
+                       }
+                       // store the current unicode, only if we did not pass the cursorLocation
+                       // Note: this does not handle cases where the cursor is in the middle of a unicode
+                       if ((completionIdentifier != null)
+                               || (startPosition <= cursorLocation+1 && cursorLocation >= currentPosition-1)){
+                               withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
+                       }
+                       return true;
+               } //-------------end unicode traitement--------------
+               else {
+                       if (!Character.isJavaIdentifierPart(currentCharacter)) {
+                               currentPosition = temp;
+                               return false;
+                       }
+
+                       if (withoutUnicodePtr != 0){
+                               // store the current unicode, only if we did not pass the cursorLocation
+                               // Note: this does not handle cases where the cursor is in the middle of a unicode
+                               if ((completionIdentifier != null)
+                                       || (startPosition <= cursorLocation+1 && cursorLocation >= currentPosition-1)){
+                                       withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
+                               }
+                       }
+                       return true;
+               }
+       } catch (IndexOutOfBoundsException e) {
+               currentPosition = temp;
+               return false;
+       }
+}
+public int getNextToken() throws InvalidInputException {
+
+       this.wasAcr = false;
+       if (diet) {
+               jumpOverMethodBody();
+               diet = false;
+               return currentPosition > source.length ? TokenNameEOF : TokenNameRBRACE;
+       }
+       try {
+               while (true) { //loop for jumping over comments
+                       withoutUnicodePtr = 0;
+                       //start with a new token (even comment written with unicode )
+
+                       // ---------Consume white space and handles startPosition---------
+                       int whiteStart = currentPosition;
+                       boolean isWhiteSpace;
+                       do {
+                               startPosition = currentPosition;
+                               if (((currentCharacter = source[currentPosition++]) == '\\')
+                                       && (source[currentPosition] == 'u')) {
+                                       isWhiteSpace = jumpOverUnicodeWhiteSpace();
+                               } else {
+                                       if (recordLineSeparator
+                                               && ((currentCharacter == '\r') || (currentCharacter == '\n')))
+                                               pushLineSeparator();
+                                       isWhiteSpace = 
+                                               (currentCharacter == ' ') || Character.isWhitespace(currentCharacter); 
+                               }
+                               /* completion requesting strictly inside blanks */
+                               if ((whiteStart != currentPosition)
+                                       //&& (previousToken == TokenNameDOT)
+                                       && (completionIdentifier == null)
+                                       && (whiteStart <= cursorLocation+1)
+                                       && (cursorLocation < startPosition)
+                                       && !Character.isJavaIdentifierStart(currentCharacter)){
+                                       currentPosition = startPosition; // for next token read
+                                       return TokenNameIdentifier;
+                               }
+                       } while (isWhiteSpace);
+                       if (tokenizeWhiteSpace && (whiteStart != currentPosition - 1)) {
+                               // reposition scanner in case we are interested by spaces as tokens
+                               currentPosition--;
+                               startPosition = whiteStart;
+                               return TokenNameWHITESPACE;
+                       }
+                       //little trick to get out in the middle of a source computation
+                       if (currentPosition > eofPosition){
+                               /* might be completing at eof (e.g. behind a dot) */
+                               if (completionIdentifier == null && 
+                                       startPosition == cursorLocation + 1){
+                                       currentPosition = startPosition; // for being detected as empty free identifier
+                                       return TokenNameIdentifier;
+                               }                               
+                               return TokenNameEOF;
+                       }
+
+                       // ---------Identify the next token-------------
+
+                       switch (currentCharacter) {
+                               case '(' :
+                                       return TokenNameLPAREN;
+                               case ')' :
+                                       return TokenNameRPAREN;
+                               case '{' :
+                                       return TokenNameLBRACE;
+                               case '}' :
+                                       return TokenNameRBRACE;
+                               case '[' :
+                                       return TokenNameLBRACKET;
+                               case ']' :
+                                       return TokenNameRBRACKET;
+                               case ';' :
+                                       return TokenNameSEMICOLON;
+                               case ',' :
+                                       return TokenNameCOMMA;
+                               case '.' :
+                                       if (startPosition <= cursorLocation 
+                                           && cursorLocation < currentPosition){
+                                               return TokenNameDOT; // completion inside .<|>12
+                                   }
+                                       if (getNextCharAsDigit())
+                                               return scanNumber(true);
+                                       return TokenNameDOT;
+                               case '+' :
+                                       {
+                                               int test;
+                                               if ((test = getNextChar('+', '=')) == 0)
+                                                       return TokenNamePLUS_PLUS;
+                                               if (test > 0)
+                                                       return TokenNamePLUS_EQUAL;
+                                               return TokenNamePLUS;
+                                       }
+                               case '-' :
+                                       {
+                                               int test;
+                                               if ((test = getNextChar('-', '=')) == 0)
+                                                       return TokenNameMINUS_MINUS;
+                                               if (test > 0)
+                                                       return TokenNameMINUS_EQUAL;
+                                               return TokenNameMINUS;
+                                       }
+                               case '~' :
+                                       return TokenNameTWIDDLE;
+                               case '!' :
+                                       if (getNextChar('='))
+                                               return TokenNameNOT_EQUAL;
+                                       return TokenNameNOT;
+                               case '*' :
+                                       if (getNextChar('='))
+                                               return TokenNameMULTIPLY_EQUAL;
+                                       return TokenNameMULTIPLY;
+                               case '%' :
+                                       if (getNextChar('='))
+                                               return TokenNameREMAINDER_EQUAL;
+                                       return TokenNameREMAINDER;
+                               case '<' :
+                                       {
+                                               int test;
+                                               if ((test = getNextChar('=', '<')) == 0)
+                                                       return TokenNameLESS_EQUAL;
+                                               if (test > 0) {
+                                                       if (getNextChar('='))
+                                                               return TokenNameLEFT_SHIFT_EQUAL;
+                                                       return TokenNameLEFT_SHIFT;
+                                               }
+                                               return TokenNameLESS;
+                                       }
+                               case '>' :
+                                       {
+                                               int test;
+                                               if ((test = getNextChar('=', '>')) == 0)
+                                                       return TokenNameGREATER_EQUAL;
+                                               if (test > 0) {
+                                                       if ((test = getNextChar('=', '>')) == 0)
+                                                               return TokenNameRIGHT_SHIFT_EQUAL;
+                                                       if (test > 0) {
+                                                               if (getNextChar('='))
+                                                                       return TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL;
+                                                               return TokenNameUNSIGNED_RIGHT_SHIFT;
+                                                       }
+                                                       return TokenNameRIGHT_SHIFT;
+                                               }
+                                               return TokenNameGREATER;
+                                       }
+                               case '=' :
+                                       if (getNextChar('='))
+                                               return TokenNameEQUAL_EQUAL;
+                                       return TokenNameEQUAL;
+                               case '&' :
+                                       {
+                                               int test;
+                                               if ((test = getNextChar('&', '=')) == 0)
+                                                       return TokenNameAND_AND;
+                                               if (test > 0)
+                                                       return TokenNameAND_EQUAL;
+                                               return TokenNameAND;
+                                       }
+                               case '|' :
+                                       {
+                                               int test;
+                                               if ((test = getNextChar('|', '=')) == 0)
+                                                       return TokenNameOR_OR;
+                                               if (test > 0)
+                                                       return TokenNameOR_EQUAL;
+                                               return TokenNameOR;
+                                       }
+                               case '^' :
+                                       if (getNextChar('='))
+                                               return TokenNameXOR_EQUAL;
+                                       return TokenNameXOR;
+                               case '?' :
+                                       return TokenNameQUESTION;
+                               case ':' :
+                                       return TokenNameCOLON;
+                               case '\'' :
+                                       {
+                                               int test;
+                                               if ((test = getNextChar('\n', '\r')) == 0) {
+                                                       throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
+                                               }
+                                               if (test > 0) {
+                                                       // relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
+                                                       for (int lookAhead = 0; lookAhead < 3; lookAhead++) {
+                                                               if (currentPosition + lookAhead == source.length)
+                                                                       break;
+                                                               if (source[currentPosition + lookAhead] == '\n')
+                                                                       break;
+                                                               if (source[currentPosition + lookAhead] == '\'') {
+                                                                       currentPosition += lookAhead + 1;
+                                                                       break;
+                                                               }
+                                                       }
+                                                       throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
+                                               }
+                                       }
+                                       if (getNextChar('\'')) {
+                                               // relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
+                                               for (int lookAhead = 0; lookAhead < 3; lookAhead++) {
+                                                       if (currentPosition + lookAhead == source.length)
+                                                               break;
+                                                       if (source[currentPosition + lookAhead] == '\n')
+                                                               break;
+                                                       if (source[currentPosition + lookAhead] == '\'') {
+                                                               currentPosition += lookAhead + 1;
+                                                               break;
+                                                       }
+                                               }
+                                               throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
+                                       }
+                                       if (getNextChar('\\'))
+                                               scanEscapeCharacter();
+                                       else { // consume next character
+                                               unicodeAsBackSlash = false;
+                                               if (((currentCharacter = source[currentPosition++]) == '\\')
+                                                       && (source[currentPosition] == 'u')) {
+                                                       getNextUnicodeChar();
+                                               } else {
+                                                       if (withoutUnicodePtr != 0) {
+                                                               withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
+                                                       }
+                                               }
+                                       }
+                                       if (getNextChar('\''))
+                                               return TokenNameCharacterLiteral;
+                                       // relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
+                                       for (int lookAhead = 0; lookAhead < 20; lookAhead++) {
+                                               if (currentPosition + lookAhead == source.length)
+                                                       break;
+                                               if (source[currentPosition + lookAhead] == '\n')
+                                                       break;
+                                               if (source[currentPosition + lookAhead] == '\'') {
+                                                       currentPosition += lookAhead + 1;
+                                                       break;
+                                               }
+                                       }
+                                       throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
+                               case '"' :
+                                       try {
+                                               // consume next character
+                                               unicodeAsBackSlash = false;
+                                               if (((currentCharacter = source[currentPosition++]) == '\\')
+                                                       && (source[currentPosition] == 'u')) {
+                                                       getNextUnicodeChar();
+                                               } else {
+                                                       if (withoutUnicodePtr != 0) {
+                                                               withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
+                                                       }
+                                               }
+
+                                               while (currentCharacter != '"') {
+                                                       /**** \r and \n are not valid in string literals ****/
+                                                       if ((currentCharacter == '\n') || (currentCharacter == '\r')) {
+                                                               // relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
+                                                               for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
+                                                                       if (currentPosition + lookAhead == source.length)
+                                                                               break;
+                                                                       if (source[currentPosition + lookAhead] == '\n')
+                                                                               break;
+                                                                       if (source[currentPosition + lookAhead] == '\"') {
+                                                                               currentPosition += lookAhead + 1;
+                                                                               break;
+                                                                       }
+                                                               }
+                                                               throw new InvalidInputException(INVALID_CHAR_IN_STRING);
+                                                       }
+                                                       if (currentCharacter == '\\') {
+                                                               int escapeSize = currentPosition;
+                                                               boolean backSlashAsUnicodeInString = unicodeAsBackSlash;
+                                                               //scanEscapeCharacter make a side effect on this value and we need the previous value few lines down this one
+                                                               scanEscapeCharacter();
+                                                               escapeSize = currentPosition - escapeSize;
+                                                               if (withoutUnicodePtr == 0) {
+                                                                       //buffer all the entries that have been left aside....
+                                                                       withoutUnicodePtr = currentPosition - escapeSize - 1 - startPosition;
+                                                                       System.arraycopy(
+                                                                               source, 
+                                                                               startPosition, 
+                                                                               withoutUnicodeBuffer, 
+                                                                               1, 
+                                                                               withoutUnicodePtr); 
+                                                                       withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
+                                                               } else { //overwrite the / in the buffer
+                                                                       withoutUnicodeBuffer[withoutUnicodePtr] = currentCharacter;
+                                                                       if (backSlashAsUnicodeInString) { //there are TWO \ in the stream where only one is correct
+                                                                               withoutUnicodePtr--;
+                                                                       }
+                                                               }
+                                                       }
+                                                       // consume next character
+                                                       unicodeAsBackSlash = false;
+                                                       if (((currentCharacter = source[currentPosition++]) == '\\')
+                                                               && (source[currentPosition] == 'u')) {
+                                                               getNextUnicodeChar();
+                                                       } else {
+                                                               if (withoutUnicodePtr != 0) {
+                                                                       withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
+                                                               }
+                                                       }
+
+                                               }
+                                       } catch (IndexOutOfBoundsException e) {
+                                               throw new InvalidInputException(UNTERMINATED_STRING);
+                                       } catch (InvalidInputException e) {
+                                               if (e.getMessage().equals(INVALID_ESCAPE)) {
+                                                       // relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
+                                                       for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
+                                                               if (currentPosition + lookAhead == source.length)
+                                                                       break;
+                                                               if (source[currentPosition + lookAhead] == '\n')
+                                                                       break;
+                                                               if (source[currentPosition + lookAhead] == '\"') {
+                                                                       currentPosition += lookAhead + 1;
+                                                                       break;
+                                                               }
+                                                       }
+
+                                               }
+                                               throw e; // rethrow
+                                       }
+                                       if (startPosition <= cursorLocation && cursorLocation <= currentPosition-1){
+                                               throw new InvalidCursorLocation(InvalidCursorLocation.NO_COMPLETION_INSIDE_STRING);
+                                       }
+                                       return TokenNameStringLiteral;
+                               case '/' :
+                                       {
+                                               int test;
+                                               if ((test = getNextChar('/', '*')) == 0) { //line comment 
+                                                       try { //get the next char 
+                                                               if (((currentCharacter = source[currentPosition++]) == '\\')
+                                                                       && (source[currentPosition] == 'u')) {
+                                                                       //-------------unicode traitement ------------
+                                                                       int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
+                                                                       currentPosition++;
+                                                                       while (source[currentPosition] == 'u') {
+                                                                               currentPosition++;
+                                                                       }
+                                                                       if ((c1 = Character.getNumericValue(source[currentPosition++])) > 15
+                                                                               || c1 < 0
+                                                                               || (c2 = Character.getNumericValue(source[currentPosition++])) > 15
+                                                                               || c2 < 0
+                                                                               || (c3 = Character.getNumericValue(source[currentPosition++])) > 15
+                                                                               || c3 < 0
+                                                                               || (c4 = Character.getNumericValue(source[currentPosition++])) > 15
+                                                                               || c4 < 0) {
+                                                                               throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
+                                                                       } else {
+                                                                               currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+                                                                       }
+                                                               }
+
+                                                               //handle the \\u case manually into comment
+                                                               if (currentCharacter == '\\') {
+                                                                       if (source[currentPosition] == '\\')
+                                                                               currentPosition++;
+                                                               } //jump over the \\
+                                                               while (currentCharacter != '\r' && currentCharacter != '\n') {
+                                                                       //get the next char 
+                                                                       if (((currentCharacter = source[currentPosition++]) == '\\')
+                                                                               && (source[currentPosition] == 'u')) {
+                                                                               //-------------unicode traitement ------------
+                                                                               int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
+                                                                               currentPosition++;
+                                                                               while (source[currentPosition] == 'u') {
+                                                                                       currentPosition++;
+                                                                               }
+                                                                               if ((c1 = Character.getNumericValue(source[currentPosition++])) > 15
+                                                                                       || c1 < 0
+                                                                                       || (c2 = Character.getNumericValue(source[currentPosition++])) > 15
+                                                                                       || c2 < 0
+                                                                                       || (c3 = Character.getNumericValue(source[currentPosition++])) > 15
+                                                                                       || c3 < 0
+                                                                                       || (c4 = Character.getNumericValue(source[currentPosition++])) > 15
+                                                                                       || c4 < 0) {
+                                                                                       throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
+                                                                               } else {
+                                                                                       currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+                                                                               }
+                                                                       }
+                                                                       //handle the \\u case manually into comment
+                                                                       if (currentCharacter == '\\') {
+                                                                               if (source[currentPosition] == '\\')
+                                                                                       currentPosition++;
+                                                                       } //jump over the \\
+                                                               }
+                                                               recordComment(false);
+                                                               if (startPosition <= cursorLocation && cursorLocation < currentPosition-1){
+                                                                       throw new InvalidCursorLocation(InvalidCursorLocation.NO_COMPLETION_INSIDE_COMMENT);
+                                                               }
+                                                               if (recordLineSeparator
+                                                                       && ((currentCharacter == '\r') || (currentCharacter == '\n')))
+                                                                       pushLineSeparator();
+                                                               if (tokenizeComments) {
+                                                                       currentPosition--; // reset one character behind
+                                                                       return TokenNameCOMMENT_LINE;
+                                                               }
+                                                       } catch (IndexOutOfBoundsException e) { //an eof will them be generated
+                                                               if (tokenizeComments) {
+                                                                       currentPosition--; // reset one character behind
+                                                                       return TokenNameCOMMENT_LINE;
+                                                               }
+                                                       }
+                                                       break;
+                                               }
+                                               if (test > 0) { //traditional and annotation comment
+                                                       boolean isJavadoc = false, star = false;
+                                                       // consume next character
+                                                       unicodeAsBackSlash = false;
+                                                       if (((currentCharacter = source[currentPosition++]) == '\\')
+                                                               && (source[currentPosition] == 'u')) {
+                                                               getNextUnicodeChar();
+                                                       } else {
+                                                               if (withoutUnicodePtr != 0) {
+                                                                       withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
+                                                               }
+                                                       }
+
+                                                       if (currentCharacter == '*') {
+                                                               isJavadoc = true;
+                                                               star = true;
+                                                       }
+                                                       if (recordLineSeparator
+                                                               && ((currentCharacter == '\r') || (currentCharacter == '\n')))
+                                                               pushLineSeparator();
+                                                       try { //get the next char 
+                                                               if (((currentCharacter = source[currentPosition++]) == '\\')
+                                                                       && (source[currentPosition] == 'u')) {
+                                                                       //-------------unicode traitement ------------
+                                                                       int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
+                                                                       currentPosition++;
+                                                                       while (source[currentPosition] == 'u') {
+                                                                               currentPosition++;
+                                                                       }
+                                                                       if ((c1 = Character.getNumericValue(source[currentPosition++])) > 15
+                                                                               || c1 < 0
+                                                                               || (c2 = Character.getNumericValue(source[currentPosition++])) > 15
+                                                                               || c2 < 0
+                                                                               || (c3 = Character.getNumericValue(source[currentPosition++])) > 15
+                                                                               || c3 < 0
+                                                                               || (c4 = Character.getNumericValue(source[currentPosition++])) > 15
+                                                                               || c4 < 0) {
+                                                                               throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
+                                                                       } else {
+                                                                               currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+                                                                       }
+                                                               }
+                                                               //handle the \\u case manually into comment
+                                                               if (currentCharacter == '\\') {
+                                                                       if (source[currentPosition] == '\\')
+                                                                               currentPosition++;
+                                                               } //jump over the \\
+                                                               // empty comment is not a javadoc /**/
+                                                               if (currentCharacter == '/') { 
+                                                                       isJavadoc = false;
+                                                               }
+                                                               //loop until end of comment */ 
+                                                               while ((currentCharacter != '/') || (!star)) {
+                                                                       if (recordLineSeparator
+                                                                               && ((currentCharacter == '\r') || (currentCharacter == '\n')))
+                                                                               pushLineSeparator();
+                                                                       star = currentCharacter == '*';
+                                                                       //get next char
+                                                                       if (((currentCharacter = source[currentPosition++]) == '\\')
+                                                                               && (source[currentPosition] == 'u')) {
+                                                                               //-------------unicode traitement ------------
+                                                                               int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
+                                                                               currentPosition++;
+                                                                               while (source[currentPosition] == 'u') {
+                                                                                       currentPosition++;
+                                                                               }
+                                                                               if ((c1 = Character.getNumericValue(source[currentPosition++])) > 15
+                                                                                       || c1 < 0
+                                                                                       || (c2 = Character.getNumericValue(source[currentPosition++])) > 15
+                                                                                       || c2 < 0
+                                                                                       || (c3 = Character.getNumericValue(source[currentPosition++])) > 15
+                                                                                       || c3 < 0
+                                                                                       || (c4 = Character.getNumericValue(source[currentPosition++])) > 15
+                                                                                       || c4 < 0) {
+                                                                                       throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
+                                                                               } else {
+                                                                                       currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+                                                                               }
+                                                                       }
+                                                                       //handle the \\u case manually into comment
+                                                                       if (currentCharacter == '\\') {
+                                                                               if (source[currentPosition] == '\\')
+                                                                                       currentPosition++;
+                                                                       } //jump over the \\
+                                                               }
+                                                               recordComment(isJavadoc);
+                                                               if (startPosition <= cursorLocation && cursorLocation < currentPosition-1){
+                                                                       throw new InvalidCursorLocation(InvalidCursorLocation.NO_COMPLETION_INSIDE_COMMENT);
+                                                               }
+                                                               if (tokenizeComments) {
+                                                                       if (isJavadoc)
+                                                                               return TokenNameCOMMENT_JAVADOC;
+                                                                       return TokenNameCOMMENT_BLOCK;
+                                                               }
+                                                       } catch (IndexOutOfBoundsException e) {
+                                                               throw new InvalidInputException(UNTERMINATED_COMMENT);
+                                                       }
+                                                       break;
+                                               }
+                                               if (getNextChar('='))
+                                                       return TokenNameDIVIDE_EQUAL;
+                                               return TokenNameDIVIDE;
+                                       }
+                               case '\u001a' :
+                                       if (atEnd())
+                                               return TokenNameEOF;
+                                       //the atEnd may not be <currentPosition == source.length> if source is only some part of a real (external) stream
+                                       throw new InvalidInputException("Ctrl-Z"); //$NON-NLS-1$
+
+                               default :
+                                       if (Character.isJavaIdentifierStart(currentCharacter))
+                                               return scanIdentifierOrKeyword();
+                                       if (Character.isDigit(currentCharacter))
+                                               return scanNumber(false);
+                                       return TokenNameERROR;
+                       }
+               }
+       } //-----------------end switch while try--------------------
+       catch (IndexOutOfBoundsException e) {
+       }
+       /* might be completing at very end of file (e.g. behind a dot) */
+       if (completionIdentifier == null && 
+               startPosition == cursorLocation + 1){
+               currentPosition = startPosition; // for being detected as empty free identifier
+               return TokenNameIdentifier;
+       }
+       return TokenNameEOF;
+}
+/*
+ * In case we actually read a keyword, but the cursor is located inside,
+ * we pretend we read an identifier.
+ */
+public int scanIdentifierOrKeyword() throws InvalidInputException {
+
+       int id = super.scanIdentifierOrKeyword();
+
+       // convert completed keyword into an identifier
+       if (id != TokenNameIdentifier
+               && startPosition <= cursorLocation+1 
+               && cursorLocation < currentPosition){
+               return TokenNameIdentifier;
+       }
+       return id;
+}
+public int scanNumber(boolean dotPrefix) throws InvalidInputException {
+       
+       int token = super.scanNumber(dotPrefix);
+
+       // consider completion just before a number to be ok, will insert before it
+       if (startPosition <= cursorLocation && cursorLocation < currentPosition){  
+               throw new InvalidCursorLocation(InvalidCursorLocation.NO_COMPLETION_INSIDE_NUMBER);
+       }
+       return token;
+}
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/InvalidCursorLocation.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/complete/InvalidCursorLocation.java
new file mode 100644 (file)
index 0000000..295dd81
--- /dev/null
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.complete;
+
+/**
+ * Thrown whenever cursor location is not inside a consistent token
+ * i.e. inside a string, number, unicode, comments etc...
+ */
+public class InvalidCursorLocation extends RuntimeException {
+
+       public String irritant;
+
+       /* Possible irritants */
+       public static final String NO_COMPLETION_INSIDE_UNICODE = "No Completion Inside Unicode"; //$NON-NLS-1$
+       public static final String NO_COMPLETION_INSIDE_COMMENT = "No Completion Inside Comment";      //$NON-NLS-1$
+       public static final String NO_COMPLETION_INSIDE_STRING = "No Completion Inside String";        //$NON-NLS-1$
+       public static final String NO_COMPLETION_INSIDE_NUMBER = "No Completion Inside Number";        //$NON-NLS-1$
+    
+public InvalidCursorLocation(String irritant){
+       this.irritant = irritant;
+}
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/impl/AssistOptions.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/impl/AssistOptions.java
new file mode 100644 (file)
index 0000000..76fbddd
--- /dev/null
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.impl;
+
+import java.util.Map;
+
+public class AssistOptions {
+       /**
+        * Option IDs
+        */
+       public static final String OPTION_PerformVisibilityCheck =
+               "org.eclipse.jdt.core.codeComplete.visibilityCheck";    //$NON-NLS-1$
+       public static final String OPTION_ForceImplicitQualification =
+               "org.eclipse.jdt.core.codeComplete.forceImplicitQualification";         //$NON-NLS-1$
+       public static final String ENABLED = "enabled"; //$NON-NLS-1$
+       public static final String DISABLED = "disabled"; //$NON-NLS-1$
+
+       public boolean checkVisibility = false;
+       public boolean forceImplicitQualification = false;
+
+       /** 
+        * Initializing the assist options with default settings
+        */
+       public AssistOptions() {
+       }
+
+       /** 
+        * Initializing the assist options with external settings
+        */
+       public AssistOptions(Map settings) {
+               if (settings == null)
+                       return;
+
+               // filter options which are related to the assist component
+               Object[] entries = settings.entrySet().toArray();
+               for (int i = 0, max = entries.length; i < max; i++) {
+                       Map.Entry entry = (Map.Entry) entries[i];
+                       if (!(entry.getKey() instanceof String))
+                               continue;
+                       if (!(entry.getValue() instanceof String))
+                               continue;
+                       String optionID = (String) entry.getKey();
+                       String optionValue = (String) entry.getValue();
+
+                       if (optionID.equals(OPTION_PerformVisibilityCheck)) {
+                               if (optionValue.equals(ENABLED)) {
+                                       this.checkVisibility = true;
+                               } else
+                                       if (optionValue.equals(DISABLED)) {
+                                               this.checkVisibility = false;
+                                       }
+                               continue;
+                       } else if (optionID.equals(OPTION_ForceImplicitQualification)) {
+                               if (optionValue.equals(ENABLED)) {
+                                       this.forceImplicitQualification = true;
+                               } else
+                                       if (optionValue.equals(DISABLED)) {
+                                               this.forceImplicitQualification = false;
+                                       }
+                               continue;
+                       } 
+               }
+       }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/impl/AssistParser.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/impl/AssistParser.java
new file mode 100644 (file)
index 0000000..b97679f
--- /dev/null
@@ -0,0 +1,1009 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.impl;
+
+/*
+ * Parser extension for code assist task
+ *
+ */
+
+import net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.AstNode;
+import net.sourceforge.phpdt.internal.compiler.ast.Block;
+import net.sourceforge.phpdt.internal.compiler.ast.CompilationUnitDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.ConstructorDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.ExplicitConstructorCall;
+import net.sourceforge.phpdt.internal.compiler.ast.Expression;
+import net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.ImportReference;
+import net.sourceforge.phpdt.internal.compiler.ast.Initializer;
+import net.sourceforge.phpdt.internal.compiler.ast.LocalDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.MessageSend;
+import net.sourceforge.phpdt.internal.compiler.ast.MethodDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.NameReference;
+import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.TypeReference;
+import net.sourceforge.phpdt.internal.compiler.parser.Parser;
+import net.sourceforge.phpdt.internal.compiler.parser.RecoveredElement;
+import net.sourceforge.phpdt.internal.compiler.parser.RecoveredField;
+import net.sourceforge.phpdt.internal.compiler.parser.RecoveredInitializer;
+import net.sourceforge.phpdt.internal.compiler.parser.RecoveredMethod;
+import net.sourceforge.phpdt.internal.compiler.parser.RecoveredType;
+import net.sourceforge.phpdt.internal.compiler.parser.RecoveredUnit;
+import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilation;
+import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
+
+public abstract class AssistParser extends Parser {
+
+       public AstNode assistNode;
+       public boolean isOrphanCompletionNode;
+               
+       /* recovery */
+       int[] blockStarts = new int[30];
+
+       // the previous token read by the scanner
+       protected int previousToken;
+
+       // the index in the identifier stack of the previous identifier
+       protected int previousIdentifierPtr;
+       
+       // the stacks of selectors for invocations (ie. method invocations, allocation expressions and
+       // explicit constructor invocations)
+       // the selector stack contains pointers to the identifier stack or one of the selector constants below
+       protected int invocationPtr;
+       protected int[] selectorStack = new int[StackIncrement];
+
+       // selector constants
+       protected static final int THIS_CONSTRUCTOR = -1;
+       protected static final int SUPER_CONSTRUCTOR = -2;
+
+       // whether the parser is in a field initializer
+       // (false is pushed each time a new type is entered,
+       //  it is changed to true when the initializer is entered,
+       //  it is changed back to false when the initializer is exited,
+       //  and it is poped when the type is exited)
+       protected int inFieldInitializationPtr;
+       protected boolean[] inFieldInitializationStack = new boolean[StackIncrement];
+
+       // whether the parser is in a method, constructor or initializer
+       // (false is pushed each time a new type is entered,
+       //  it is changed to true when the method is entered,
+       //  it is changed back to false when the method is exited,
+       //  and it is poped when the type is exited)
+       protected int inMethodPtr;
+       protected boolean[] inMethodStack = new boolean[StackIncrement];
+public AssistParser(ProblemReporter problemReporter, boolean assertMode) {
+       super(problemReporter, true, assertMode);
+}
+public abstract char[] assistIdentifier();
+public int bodyEnd(AbstractMethodDeclaration method){
+       return method.declarationSourceEnd;
+}
+public int bodyEnd(Initializer initializer){
+       return initializer.declarationSourceEnd;
+}
+/*
+ * Build initial recovery state.
+ * Recovery state is inferred from the current state of the parser (reduced node stack).
+ */
+public RecoveredElement buildInitialRecoveryState(){
+
+       /* recovery in unit structure */
+       if (referenceContext instanceof CompilationUnitDeclaration){
+               RecoveredElement element = super.buildInitialRecoveryState();
+               flushAssistState();
+               initInMethodAndInFieldInitializationStack(element);
+               return element;
+       }
+
+       /* recovery in method body */
+       lastCheckPoint = 0;
+
+       RecoveredElement element = null;
+       if (referenceContext instanceof AbstractMethodDeclaration){
+               element = new RecoveredMethod((AbstractMethodDeclaration) referenceContext, null, 0, this);
+               lastCheckPoint = ((AbstractMethodDeclaration) referenceContext).bodyStart;
+       } else {
+               /* Initializer bodies are parsed in the context of the type declaration, we must thus search it inside */
+               if (referenceContext instanceof TypeDeclaration){
+                       TypeDeclaration type = (TypeDeclaration) referenceContext;
+                       for (int i = 0; i < type.fields.length; i++){
+                               FieldDeclaration field = type.fields[i];                                        
+                               if (!field.isField()
+                                               && field.declarationSourceStart <= scanner.initialPosition
+                                               && scanner.initialPosition <= field.declarationSourceEnd
+                                               && scanner.eofPosition <= field.declarationSourceEnd+1){
+                                       element = new RecoveredInitializer((Initializer) field, null, 1, this);
+                                       lastCheckPoint = field.declarationSourceStart;                                  
+                                       break;
+                               }
+                       }
+               } 
+       }
+
+       if (element == null) return element;
+
+       /* add initial block */
+       Block block = new Block(0);
+       int lastStart = blockStarts[0];
+       block.sourceStart = lastStart;
+       element = element.add(block, 1);
+       int blockIndex = 1;     // ignore first block start, since manually rebuilt here
+
+       for(int i = 0; i <= astPtr; i++){
+               AstNode node = astStack[i];
+
+               /* check for intermediate block creation, so recovery can properly close them afterwards */
+               int nodeStart = node.sourceStart;
+               for (int j = blockIndex; j <= realBlockPtr; j++){
+                       if (blockStarts[j] > nodeStart){
+                               blockIndex = j; // shift the index to the new block
+                               break;
+                       }
+                       if (blockStarts[j] != lastStart){ // avoid multiple block if at same position
+                               block = new Block(0);
+                               block.sourceStart = lastStart = blockStarts[j];
+                               element = element.add(block, 1);
+                       }
+                       blockIndex = j+1; // shift the index to the new block
+               }
+               if (node instanceof LocalDeclaration){
+                       LocalDeclaration local = (LocalDeclaration) node;
+                       if (local.declarationSourceEnd == 0){
+                               element = element.add(local, 0);
+                               if (local.initialization == null){
+                                       lastCheckPoint = local.sourceEnd + 1;
+                               } else {
+                                       lastCheckPoint = local.initialization.sourceEnd + 1;
+                               }
+                       } else {
+                               element = element.add(local, 0);
+                               lastCheckPoint = local.declarationSourceEnd + 1;
+                       }
+                       continue;
+               }               
+               if (node instanceof AbstractMethodDeclaration){
+                       AbstractMethodDeclaration method = (AbstractMethodDeclaration) node;
+                       if (method.declarationSourceEnd == 0){
+                               element = element.add(method, 0);
+                               lastCheckPoint = method.bodyStart;
+                       } else {
+                               element = element.add(method, 0);
+                               lastCheckPoint = method.declarationSourceEnd + 1;
+                       }
+                       continue;
+               }
+               if (node instanceof Initializer){
+                       Initializer initializer = (Initializer) node;
+                       if (initializer.declarationSourceEnd == 0){
+                               element = element.add(initializer, 1);
+                               lastCheckPoint = initializer.bodyStart;                         
+                       } else {
+                               element = element.add(initializer, 0);
+                               lastCheckPoint = initializer.declarationSourceEnd + 1;
+                       }
+                       continue;
+               }               
+               if (node instanceof FieldDeclaration){
+                       FieldDeclaration field = (FieldDeclaration) node;
+                       if (field.declarationSourceEnd == 0){
+                               element = element.add(field, 0);
+                               if (field.initialization == null){
+                                       lastCheckPoint = field.sourceEnd + 1;
+                               } else {
+                                       lastCheckPoint = field.initialization.sourceEnd + 1;
+                               }
+                       } else {
+                               element = element.add(field, 0);
+                               lastCheckPoint = field.declarationSourceEnd + 1;
+                       }
+                       continue;
+               }
+               if (node instanceof TypeDeclaration){
+                       TypeDeclaration type = (TypeDeclaration) node;
+                       if (type.declarationSourceEnd == 0){
+                               element = element.add(type, 0); 
+                               lastCheckPoint = type.bodyStart;
+                       } else {
+                               element = element.add(type, 0);                         
+                               lastCheckPoint = type.declarationSourceEnd + 1;
+                       }
+                       continue;
+               }
+               if (node instanceof ImportReference){
+                       ImportReference importRef = (ImportReference) node;
+                       element = element.add(importRef, 0);
+                       lastCheckPoint = importRef.declarationSourceEnd + 1;
+               }
+       }
+       if (this.currentToken == TokenNameRBRACE) {
+               this.currentToken = 0; // closing brace has already been taken care of
+       }
+
+       /* might need some extra block (after the last reduced node) */
+       int pos = this.assistNode == null ? lastCheckPoint : this.assistNode.sourceStart;
+       for (int j = blockIndex; j <= realBlockPtr; j++){
+               if ((blockStarts[j] < pos) && (blockStarts[j] != lastStart)){ // avoid multiple block if at same position
+                       block = new Block(0);
+                       block.sourceStart = lastStart = blockStarts[j];
+                       element = element.add(block, 1);
+               }
+       }
+       
+       initInMethodAndInFieldInitializationStack(element);
+       return element;
+}
+protected void consumeClassBodyDeclarationsopt() {
+       super.consumeClassBodyDeclarationsopt();
+       this.inFieldInitializationPtr--;
+       this.inMethodPtr--;
+}
+protected void consumeClassBodyopt() {
+       super.consumeClassBodyopt();
+       this.invocationPtr--; // NB: This can be decremented below -1 only if in diet mode and not in field initializer
+}
+protected void consumeClassHeader() {
+       super.consumeClassHeader();
+       this.pushNotInInitializer();
+       this.pushNotInMethod();
+}
+protected void consumeConstructorBody() {
+       super.consumeConstructorBody();
+       this.inMethodStack[this.inMethodPtr] = false;
+}
+protected void consumeConstructorHeader() {
+       super.consumeConstructorHeader();
+       this.inMethodStack[this.inMethodPtr] = true;
+}
+protected void consumeEmptyClassBodyDeclarationsopt() {
+       super.consumeEmptyClassBodyDeclarationsopt();
+       this.inFieldInitializationPtr--;
+       this.inMethodPtr--;
+}
+protected void consumeEnterAnonymousClassBody() {
+       super.consumeEnterAnonymousClassBody();
+       this.invocationPtr--; // NB: This can be decremented below -1 only if in diet mode and not in field initializer
+       this.pushNotInInitializer();
+       this.pushNotInMethod();
+}
+protected void consumeExplicitConstructorInvocation(int flag, int recFlag) {
+       super.consumeExplicitConstructorInvocation(flag, recFlag);
+       this.invocationPtr--; // NB: This can be decremented below -1 only if in diet mode and not in field initializer
+}
+protected void consumeForceNoDiet() {
+       super.consumeForceNoDiet();
+       // if we are not in a method (ie. we are not in a local variable initializer)
+       // then we are entering a field initializer
+       if (!this.inMethodStack[this.inMethodPtr]) {
+               this.inFieldInitializationStack[this.inFieldInitializationPtr] = true;
+       }
+}
+protected void consumeInterfaceHeader() {
+       super.consumeInterfaceHeader();
+       this.pushNotInInitializer();
+       this.pushNotInMethod();
+}
+protected void consumeInterfaceMemberDeclarationsopt() {
+       super.consumeInterfaceMemberDeclarationsopt();
+       this.inFieldInitializationPtr--;
+       this.inMethodPtr--;
+}
+protected void consumeMethodBody() {
+       super.consumeMethodBody();
+       this.inMethodStack[this.inMethodPtr] = false;
+}
+protected void consumeMethodHeader() {
+       super.consumeMethodHeader();
+       this.inMethodStack[this.inMethodPtr] = true;
+}
+protected void consumeMethodInvocationName() {
+       super.consumeMethodInvocationName();
+       this.invocationPtr--; // NB: This can be decremented below -1 only if in diet mode and not in field initializer
+       MessageSend messageSend = (MessageSend)expressionStack[expressionPtr];
+       if (messageSend == assistNode){
+               this.lastCheckPoint = messageSend.sourceEnd + 1;
+       }
+}
+protected void consumeMethodInvocationPrimary() {
+       super.consumeMethodInvocationPrimary();
+       this.invocationPtr--; // NB: This can be decremented below -1 only if in diet mode and not in field initializer
+       MessageSend messageSend = (MessageSend)expressionStack[expressionPtr];
+       if (messageSend == assistNode){
+               this.lastCheckPoint = messageSend.sourceEnd + 1;
+       }
+}
+protected void consumeMethodInvocationSuper() {
+       super.consumeMethodInvocationSuper();
+       this.invocationPtr--; // NB: This can be decremented below -1 only if in diet mode and not in field initializer 
+       MessageSend messageSend = (MessageSend)expressionStack[expressionPtr];
+       if (messageSend == assistNode){
+               this.lastCheckPoint = messageSend.sourceEnd + 1;
+       }
+}
+protected void consumeNestedMethod() {
+       super.consumeNestedMethod();
+       this.inMethodStack[this.inMethodPtr] = true;
+}
+protected void consumeOpenBlock() {
+       // OpenBlock ::= $empty
+
+       super.consumeOpenBlock();
+       try {
+               blockStarts[realBlockPtr] = scanner.startPosition;
+       } catch (IndexOutOfBoundsException e) {
+               //realBlockPtr is correct 
+               int oldStackLength = blockStarts.length;
+               int oldStack[] = blockStarts;
+               blockStarts = new int[oldStackLength + StackIncrement];
+               System.arraycopy(oldStack, 0, blockStarts, 0, oldStackLength);
+               blockStarts[realBlockPtr] = scanner.startPosition;
+       }
+}
+protected void consumePackageDeclarationName() {
+       // PackageDeclarationName ::= 'package' Name
+       /* build an ImportRef build from the last name 
+       stored in the identifier stack. */
+
+       int index;
+
+       /* no need to take action if not inside assist identifiers */
+       if ((index = indexOfAssistIdentifier()) < 0) {
+               super.consumePackageDeclarationName();
+               return;
+       }
+       /* retrieve identifiers subset and whole positions, the assist node positions
+               should include the entire replaced source. */
+       int length = identifierLengthStack[identifierLengthPtr];
+       char[][] subset = identifierSubSet(index+1); // include the assistIdentifier
+       identifierLengthPtr--;
+       identifierPtr -= length;
+       long[] positions = new long[length];
+       System.arraycopy(
+               identifierPositionStack, 
+               identifierPtr + 1, 
+               positions, 
+               0, 
+               length); 
+
+       /* build specific assist node on package statement */
+       ImportReference reference = this.createAssistPackageReference(subset, positions);
+       assistNode = reference;
+       this.lastCheckPoint = reference.sourceEnd + 1;
+       compilationUnit.currentPackage = reference; 
+
+       if (currentToken == TokenNameSEMICOLON){
+               reference.declarationSourceEnd = scanner.currentPosition - 1;
+       } else {
+               reference.declarationSourceEnd = (int) positions[length-1];
+       }
+       //endPosition is just before the ;
+       reference.declarationSourceStart = intStack[intPtr--];
+       // flush annotations defined prior to import statements
+       reference.declarationSourceEnd = this.flushAnnotationsDefinedPriorTo(reference.declarationSourceEnd);
+
+       // recovery
+       if (currentElement != null){
+               lastCheckPoint = reference.declarationSourceEnd+1;
+               restartRecovery = true; // used to avoid branching back into the regular automaton              
+       }       
+}
+protected void consumeRestoreDiet() {
+       super.consumeRestoreDiet();
+       // if we are not in a method (ie. we were not in a local variable initializer)
+       // then we are exiting a field initializer
+       if (!this.inMethodStack[this.inMethodPtr]) {
+               this.inFieldInitializationStack[this.inFieldInitializationPtr] = false;
+       }
+}
+protected void consumeSingleTypeImportDeclarationName() {
+       // SingleTypeImportDeclarationName ::= 'import' Name
+       /* push an ImportRef build from the last name 
+       stored in the identifier stack. */
+
+       int index;
+
+       /* no need to take action if not inside assist identifiers */
+       if ((index = indexOfAssistIdentifier()) < 0) {
+               super.consumeSingleTypeImportDeclarationName();
+               return;
+       }
+       /* retrieve identifiers subset and whole positions, the assist node positions
+               should include the entire replaced source. */
+       int length = identifierLengthStack[identifierLengthPtr];
+       char[][] subset = identifierSubSet(index+1); // include the assistIdentifier
+       identifierLengthPtr--;
+       identifierPtr -= length;
+       long[] positions = new long[length];
+       System.arraycopy(
+               identifierPositionStack, 
+               identifierPtr + 1, 
+               positions, 
+               0, 
+               length); 
+
+       /* build specific assist node on import statement */
+       ImportReference reference = this.createAssistImportReference(subset, positions);
+       assistNode = reference;
+       this.lastCheckPoint = reference.sourceEnd + 1;
+
+       pushOnAstStack(reference);
+
+       if (currentToken == TokenNameSEMICOLON){
+               reference.declarationSourceEnd = scanner.currentPosition - 1;
+       } else {
+               reference.declarationSourceEnd = (int) positions[length-1];
+       }
+       //endPosition is just before the ;
+       reference.declarationSourceStart = intStack[intPtr--];
+       // flush annotations defined prior to import statements
+       reference.declarationSourceEnd = this.flushAnnotationsDefinedPriorTo(reference.declarationSourceEnd);
+
+       // recovery
+       if (currentElement != null){
+               lastCheckPoint = reference.declarationSourceEnd+1;
+               currentElement = currentElement.add(reference, 0);
+               lastIgnoredToken = -1;
+               restartRecovery = true; // used to avoid branching back into the regular automaton              
+       }
+}
+protected void consumeStaticInitializer() {
+       super.consumeStaticInitializer();
+       this.inMethodStack[this.inMethodPtr] = false;
+}
+protected void consumeStaticOnly() {
+       super.consumeStaticOnly();
+       this.inMethodStack[this.inMethodPtr] = true;
+}
+protected void consumeToken(int token) {
+       super.consumeToken(token);
+       // register message send selector only if inside a method or if looking at a field initializer 
+       // and if the current token is an open parenthesis
+       if ((this.inMethodStack[this.inMethodPtr] || this.inFieldInitializationStack[this.inFieldInitializationPtr]) && token == TokenNameLPAREN) {
+               switch (this.previousToken) {
+                       case TokenNameIdentifier:
+                               this.pushOnSelectorStack(this.identifierPtr);
+                               break;
+//                     case TokenNamethis: // explicit constructor invocation, eg. this(1, 2)
+//                             this.pushOnSelectorStack(THIS_CONSTRUCTOR);
+//                             break;
+//                     case TokenNamesuper: // explicit constructor invocation, eg. super(1, 2)
+//                             this.pushOnSelectorStack(SUPER_CONSTRUCTOR);
+//                             break;
+               }
+       }
+       this.previousToken = token;
+       if (token == TokenNameIdentifier) {
+               this.previousIdentifierPtr = this.identifierPtr;
+       }
+}
+protected void consumeTypeImportOnDemandDeclarationName() {
+       // TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
+       /* push an ImportRef build from the last name 
+       stored in the identifier stack. */
+
+       int index;
+
+       /* no need to take action if not inside assist identifiers */
+       if ((index = indexOfAssistIdentifier()) < 0) {
+               super.consumeTypeImportOnDemandDeclarationName();
+               return;
+       }
+       /* retrieve identifiers subset and whole positions, the assist node positions
+               should include the entire replaced source. */
+       int length = identifierLengthStack[identifierLengthPtr];
+       char[][] subset = identifierSubSet(index+1); // include the assistIdentifier
+       identifierLengthPtr--;
+       identifierPtr -= length;
+       long[] positions = new long[length];
+       System.arraycopy(
+               identifierPositionStack, 
+               identifierPtr + 1, 
+               positions, 
+               0, 
+               length); 
+
+       /* build specific assist node on import statement */
+       ImportReference reference = this.createAssistImportReference(subset, positions);
+       reference.onDemand = true;
+       assistNode = reference;
+       this.lastCheckPoint = reference.sourceEnd + 1;
+
+       pushOnAstStack(reference);
+
+       if (currentToken == TokenNameSEMICOLON){
+               reference.declarationSourceEnd = scanner.currentPosition - 1;
+       } else {
+               reference.declarationSourceEnd = (int) positions[length-1];
+       }
+       //endPosition is just before the ;
+       reference.declarationSourceStart = intStack[intPtr--];
+       // flush annotations defined prior to import statements
+       reference.declarationSourceEnd = this.flushAnnotationsDefinedPriorTo(reference.declarationSourceEnd);
+
+       // recovery
+       if (currentElement != null){
+               lastCheckPoint = reference.declarationSourceEnd+1;
+               currentElement = currentElement.add(reference, 0);
+               lastIgnoredToken = -1;
+               restartRecovery = true; // used to avoid branching back into the regular automaton              
+       }
+}
+public abstract ImportReference createAssistImportReference(char[][] tokens, long[] positions);
+public abstract ImportReference createAssistPackageReference(char[][] tokens, long[] positions);
+public abstract NameReference createQualifiedAssistNameReference(char[][] previousIdentifiers, char[] name, long[] positions);
+public abstract TypeReference createQualifiedAssistTypeReference(char[][] previousIdentifiers, char[] name, long[] positions);
+public abstract NameReference createSingleAssistNameReference(char[] name, long position);
+public abstract TypeReference createSingleAssistTypeReference(char[] name, long position);
+/*
+ * Flush parser/scanner state regarding to code assist
+ */
+public void flushAssistState(){
+       this.assistNode = null;
+       this.isOrphanCompletionNode = false;
+       this.setAssistIdentifier(null);
+}
+/*
+ * Build specific type reference nodes in case the cursor is located inside the type reference
+ */
+protected TypeReference getTypeReference(int dim) {
+
+       int index;
+
+       /* no need to take action if not inside completed identifiers */
+       if ((index = indexOfAssistIdentifier()) < 0) {
+               return super.getTypeReference(dim);
+       }
+
+       /* retrieve identifiers subset and whole positions, the assist node positions
+               should include the entire replaced source. */
+       int length = identifierLengthStack[identifierLengthPtr];
+       char[][] subset = identifierSubSet(index);
+       identifierLengthPtr--;
+       identifierPtr -= length;
+       long[] positions = new long[length];
+       System.arraycopy(
+               identifierPositionStack, 
+               identifierPtr + 1, 
+               positions, 
+               0, 
+               length); 
+
+       /* build specific assist on type reference */
+       TypeReference reference;
+       if (index == 0) {
+               /* assist inside first identifier */
+               reference = this.createSingleAssistTypeReference(
+                                               assistIdentifier(), 
+                                               positions[0]);
+       } else {
+               /* assist inside subsequent identifier */
+               reference =     this.createQualifiedAssistTypeReference(
+                                               subset,  
+                                               assistIdentifier(), 
+                                               positions);
+       }
+       assistNode = reference;
+       this.lastCheckPoint = reference.sourceEnd + 1;
+       return reference;
+}
+/*
+ * Copy of code from superclass with the following change:
+ * In the case of qualified name reference if the cursor location is on the 
+ * qualified name reference, then create a CompletionOnQualifiedNameReference 
+ * instead.
+ */
+protected NameReference getUnspecifiedReferenceOptimized() {
+
+       int completionIndex;
+
+       /* no need to take action if not inside completed identifiers */
+       if ((completionIndex = indexOfAssistIdentifier()) < 0) {
+               return super.getUnspecifiedReferenceOptimized();
+       }
+
+       /* retrieve identifiers subset and whole positions, the completion node positions
+               should include the entire replaced source. */
+       int length = identifierLengthStack[identifierLengthPtr];
+       char[][] subset = identifierSubSet(completionIndex);
+       identifierLengthPtr--;
+       identifierPtr -= length;
+       long[] positions = new long[length];
+       System.arraycopy(
+               identifierPositionStack, 
+               identifierPtr + 1, 
+               positions, 
+               0, 
+               length);
+
+       /* build specific completion on name reference */
+       NameReference reference;
+       if (completionIndex == 0) {
+               /* completion inside first identifier */
+               reference = this.createSingleAssistNameReference(assistIdentifier(), positions[0]);
+       } else {
+               /* completion inside subsequent identifier */
+               reference = this.createQualifiedAssistNameReference(subset, assistIdentifier(), positions);
+       };
+       reference.bits &= ~AstNode.RestrictiveFlagMASK;
+       reference.bits |= LOCAL | FIELD;
+       
+       assistNode = reference;
+       lastCheckPoint = reference.sourceEnd + 1;
+       return reference;
+}
+public void goForBlockStatementsopt() {
+       //tells the scanner to go for block statements opt parsing
+
+       firstToken = TokenNameTWIDDLE;
+       scanner.recordLineSeparator = false;
+}
+public void goForConstructorBlockStatementsopt() {
+       //tells the scanner to go for constructor block statements opt parsing
+
+       firstToken = TokenNameNOT;
+       scanner.recordLineSeparator = false;
+}
+/*
+ * Retrieve a partial subset of a qualified name reference up to the completion point.
+ * It does not pop the actual awaiting identifiers, so as to be able to retrieve position
+ * information afterwards.
+ */
+protected char[][] identifierSubSet(int subsetLength){
+
+       if (subsetLength == 0) return null;
+       
+       char[][] subset;
+       System.arraycopy(
+               identifierStack,
+               identifierPtr - identifierLengthStack[identifierLengthPtr] + 1,
+               (subset = new char[subsetLength][]),
+               0,
+               subsetLength);
+       return subset;
+}
+/*
+ * Iterate the most recent group of awaiting identifiers (grouped for qualified name reference (eg. aa.bb.cc)
+ * so as to check whether one of them is the assist identifier.
+ * If so, then answer the index of the assist identifier (0 being the first identifier of the set).
+ *     eg. aa(0).bb(1).cc(2)
+ * If no assist identifier was found, answers -1.
+ */
+protected int indexOfAssistIdentifier(){
+
+       if (identifierLengthPtr < 0){
+               return -1; // no awaiting identifier
+       }
+
+       char[] assistIdentifier ;
+       if ((assistIdentifier = this.assistIdentifier()) == null){
+               return -1; // no assist identifier found yet
+       }
+
+       // iterate awaiting identifiers backwards
+       int length = identifierLengthStack[identifierLengthPtr];
+       for (int i = 0; i < length; i++){ 
+               if (identifierStack[identifierPtr - i] == assistIdentifier){
+                       return length - i - 1;
+               }
+       }
+       // none of the awaiting identifiers is the completion one
+       return -1;
+}
+public void initialize() {
+       super.initialize();
+       this.flushAssistState();
+       this.invocationPtr = -1;
+       this.inMethodStack[this.inMethodPtr = 0] = false;
+       this.inFieldInitializationStack[this.inFieldInitializationPtr = 0] = false;
+       this.previousIdentifierPtr = -1;
+}
+public abstract void initializeScanner();
+
+protected void initInMethodAndInFieldInitializationStack(RecoveredElement currentElement) {
+
+       int length = currentElement.depth() + 1;
+       int ptr = length;
+       boolean[] methodStack = new boolean[length];
+       boolean[] fieldInitializationStack = new boolean[length];
+       boolean inMethod = false;
+       boolean inFieldInitializer = false;
+       
+       RecoveredElement element = currentElement;
+       while(element != null){
+               if(element instanceof RecoveredMethod ||
+                       element instanceof RecoveredInitializer) {
+                       if(element.parent == null) {
+                               methodStack[--ptr] = true;
+                               fieldInitializationStack[ptr] = false;
+                       }
+                       inMethod = true;
+               } else if(element instanceof RecoveredField){
+                       inFieldInitializer = element.sourceEnd() == 0;
+               } else if(element instanceof RecoveredType){
+                       methodStack[--ptr] = inMethod;
+                       fieldInitializationStack[ptr] = inFieldInitializer;
+       
+                       inMethod = false;
+                       inFieldInitializer = false;
+               } else if(element instanceof RecoveredUnit) {
+                       methodStack[--ptr] = false;
+                       fieldInitializationStack[ptr] = false;
+               }
+               element = element.parent;
+       }
+       
+       inMethodPtr = length - ptr - 1;
+       inFieldInitializationPtr = inMethodPtr;
+       System.arraycopy(methodStack, ptr, inMethodStack, 0, inMethodPtr + 1);
+       System.arraycopy(fieldInitializationStack, ptr, inFieldInitializationStack, 0, inFieldInitializationPtr + 1);
+       
+}
+
+/**
+ * Returns whether we are directly or indirectly inside a field initializer.
+ */
+protected boolean insideFieldInitialization() {
+       for (int i = this.inFieldInitializationPtr; i >= 0; i--) {
+               if (this.inFieldInitializationStack[i]) {
+                       return true;
+               }
+       }
+       return false;
+}
+/**
+ * Parse the block statements inside the given method declaration and try to complete at the
+ * cursor location.
+ */
+public void parseBlockStatements(AbstractMethodDeclaration md, CompilationUnitDeclaration unit) {
+       if (md instanceof MethodDeclaration) {
+               parseBlockStatements((MethodDeclaration) md, unit);
+       } else if (md instanceof ConstructorDeclaration) {
+               parseBlockStatements((ConstructorDeclaration) md, unit);
+       }
+}
+/**
+ * Parse the block statements inside the given constructor declaration and try to complete at the
+ * cursor location.
+ */
+public void parseBlockStatements(ConstructorDeclaration cd, CompilationUnitDeclaration unit) {
+       //only parse the method body of cd
+       //fill out its statements
+
+       //convert bugs into parse error
+
+       initialize();
+       
+       // simulate goForConstructorBody except that we don't want to balance brackets because they are not going to be balanced
+       goForConstructorBlockStatementsopt();
+
+       referenceContext = cd;
+       compilationUnit = unit;
+
+       scanner.resetTo(cd.bodyStart, bodyEnd(cd));
+       consumeNestedMethod();
+       try {
+               parse();
+       } catch (AbortCompilation ex) {
+               lastAct = ERROR_ACTION;
+       }
+}
+/**
+ * Parse the block statements inside the given initializer and try to complete at the
+ * cursor location.
+ */
+public void parseBlockStatements(
+       Initializer ini,
+       TypeDeclaration type, 
+       CompilationUnitDeclaration unit) {
+
+       initialize();
+
+       // simulate goForInitializer except that we don't want to balance brackets because they are not going to be balanced
+       goForBlockStatementsopt();
+       
+       referenceContext = type;
+       compilationUnit = unit;
+
+       scanner.resetTo(ini.sourceStart, bodyEnd(ini)); // just after the beginning {
+       consumeNestedMethod();
+       try {
+               parse();
+       } catch (AbortCompilation ex) {
+               lastAct = ERROR_ACTION;
+       } finally {
+               nestedMethod[nestedType]--;
+       }
+}
+/**
+ * Parse the block statements inside the given method declaration and try to complete at the
+ * cursor location.
+ */
+public void parseBlockStatements(MethodDeclaration md, CompilationUnitDeclaration unit) {
+       //only parse the method body of md
+       //fill out method statements
+
+       //convert bugs into parse error
+
+       if (md.isAbstract())
+               return;
+       if (md.isNative())
+               return;
+       if ((md.modifiers & AccSemicolonBody) != 0)
+               return;
+
+       initialize();
+
+       // simulate goForMethodBody except that we don't want to balance brackets because they are not going to be balanced
+       goForBlockStatementsopt();
+
+       referenceContext = md;
+       compilationUnit = unit;
+       
+       scanner.resetTo(md.bodyStart, bodyEnd(md)); // reset the scanner to parser from { down to the cursor location
+       consumeNestedMethod();
+       try {
+               parse();
+       } catch (AbortCompilation ex) {
+               lastAct = ERROR_ACTION;
+       } finally {
+               nestedMethod[nestedType]--;             
+       }
+}
+/*
+ * Prepares the state of the parser to go for BlockStatements.
+ */
+protected void prepareForBlockStatements() {
+       this.nestedMethod[this.nestedType = 0] = 1;
+       this.variablesCounter[this.nestedType] = 0;
+       this.realBlockStack[this.realBlockPtr = 1] = 0;
+       this.invocationPtr = -1;
+}
+/*
+ * Pushes 'false' on the inInitializerStack.
+ */
+protected void pushNotInInitializer() {
+       try {
+               this.inFieldInitializationStack[++this.inFieldInitializationPtr] = false;
+       } catch (IndexOutOfBoundsException e) {
+               //except in test's cases, it should never raise
+               int oldStackLength = this.inFieldInitializationStack.length;
+               System.arraycopy(this.inFieldInitializationStack , 0, (this.inFieldInitializationStack = new boolean[oldStackLength + StackIncrement]), 0, oldStackLength);
+               this.inFieldInitializationStack[this.inFieldInitializationPtr] = false;
+       }
+}
+/*
+ * Pushes 'false' on the inMethodStack.
+ */
+protected void pushNotInMethod() {
+       try {
+               this.inMethodStack[++this.inMethodPtr] = false;
+       } catch (IndexOutOfBoundsException e) {
+               //except in test's cases, it should never raise
+               int oldStackLength = this.inMethodStack.length;
+               System.arraycopy(this.inMethodStack , 0, (this.inMethodStack = new boolean[oldStackLength + StackIncrement]), 0, oldStackLength);
+               this.inMethodStack[this.inMethodPtr] = false;
+       }
+}
+/**
+ * Pushes the given the given selector (an identifier pointer to the identifier stack) on the selector stack.
+ */
+protected void pushOnSelectorStack(int selectorIdPtr) {
+       if (this.invocationPtr < -1) return;
+       try {
+               this.selectorStack[++this.invocationPtr] = selectorIdPtr;
+       } catch (IndexOutOfBoundsException e) {
+               int oldStackLength = this.selectorStack.length;
+               int oldSelectorStack[] = this.selectorStack;
+               this.selectorStack = new int[oldStackLength + StackIncrement];
+               System.arraycopy(oldSelectorStack, 0, this.selectorStack, 0, oldStackLength);
+               this.selectorStack[this.invocationPtr] = selectorIdPtr;
+       }
+}
+public void reset(){
+       this.flushAssistState();
+}
+/*
+ * Reset context so as to resume to regular parse loop
+ */
+protected void resetStacks() {
+       super.resetStacks();
+       this.inFieldInitializationStack[this.inFieldInitializationPtr = 0] = false;
+       this.inMethodStack[this.inMethodPtr = 0] = false;
+}
+/*
+ * Reset context so as to resume to regular parse loop
+ * If unable to reset for resuming, answers false.
+ *
+ * Move checkpoint location, reset internal stacks and
+ * decide which grammar goal is activated.
+ */
+protected boolean resumeAfterRecovery() {
+
+       // reset internal stacks 
+       astPtr = -1;
+       astLengthPtr = -1;
+       expressionPtr = -1;
+       expressionLengthPtr = -1;
+       identifierPtr = -1;     
+       identifierLengthPtr     = -1;
+       intPtr = -1;
+       dimensions = 0 ;
+       recoveredStaticInitializerStart = 0;
+
+       // if in diet mode, reset the diet counter because we're going to restart outside an initializer.
+       if (diet) dietInt = 0;
+
+       /* attempt to move checkpoint location */
+       if (!this.moveRecoveryCheckpoint()) return false;
+
+       initInMethodAndInFieldInitializationStack(currentElement);
+
+       // only look for headers
+       if (referenceContext instanceof CompilationUnitDeclaration
+               || this.assistNode != null){
+               
+               if(inMethodStack[inMethodPtr] &&
+                       insideFieldInitialization() &&
+                       this.assistNode == null
+                       ){ 
+                       this.prepareForBlockStatements();
+                       goForBlockStatementsOrMethodHeaders();
+               } else {
+                       nestedMethod[nestedType = 0] = 0;
+                       variablesCounter[nestedType] = 0;
+                       realBlockStack[realBlockPtr = 0] = 0;
+                       goForHeaders();
+                       diet = true; // passed this point, will not consider method bodies
+               }
+               return true;
+       }
+       if (referenceContext instanceof AbstractMethodDeclaration
+               || referenceContext instanceof TypeDeclaration){
+                       
+               if (currentElement instanceof RecoveredType){
+                       nestedMethod[nestedType = 0] = 0;
+                       variablesCounter[nestedType] = 0;
+                       realBlockStack[realBlockPtr = 0] = 0;
+                       goForHeaders();
+               } else {
+                       this.prepareForBlockStatements();
+                       goForBlockStatementsOrMethodHeaders();
+               }
+               return true;
+       }
+       // does not know how to restart
+       return false;
+}
+public abstract void setAssistIdentifier(char[] assistIdent);
+/**
+ * If the given ast node is inside an explicit constructor call
+ * then wrap it with a fake constructor call.
+ * Returns the wrapped completion node or the completion node itself.
+ */
+protected AstNode wrapWithExplicitConstructorCallIfNeeded(AstNode ast) {
+       int selector;
+       if (ast != null && this.invocationPtr >= 0 && ast instanceof Expression &&
+                       (((selector = this.selectorStack[this.invocationPtr]) == THIS_CONSTRUCTOR) ||
+                       (selector == SUPER_CONSTRUCTOR))) {
+               ExplicitConstructorCall call = new ExplicitConstructorCall(
+                       (selector == THIS_CONSTRUCTOR) ? 
+                               ExplicitConstructorCall.This : 
+                               ExplicitConstructorCall.Super
+               );
+               call.arguments = new Expression[] {(Expression)ast};
+               call.sourceStart = ast.sourceStart;
+               call.sourceEnd = ast.sourceEnd;
+               return call;
+       } else {
+               return ast;
+       }
+}
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/impl/Engine.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/impl/Engine.java
new file mode 100644 (file)
index 0000000..35a3dc9
--- /dev/null
@@ -0,0 +1,192 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.impl;
+
+import java.util.Map;
+
+import net.sourceforge.phpdt.internal.codeassist.ISearchableNameEnvironment;
+import net.sourceforge.phpdt.internal.compiler.*;
+import net.sourceforge.phpdt.internal.compiler.env.*;
+
+import net.sourceforge.phpdt.internal.compiler.ast.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+import net.sourceforge.phpdt.internal.compiler.parser.*;
+import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+
+
+public abstract class Engine implements ITypeRequestor {
+
+       public LookupEnvironment lookupEnvironment;
+       
+       protected CompilationUnitScope unitScope;
+       protected ISearchableNameEnvironment nameEnvironment;
+
+       public AssistOptions options;
+       public CompilerOptions compilerOptions; 
+       
+       public Engine(Map settings){
+               this.options = new AssistOptions(settings);
+               this.compilerOptions = new CompilerOptions(settings);
+       }
+       
+       /**
+        * Add an additional binary type
+        */
+       public void accept(IBinaryType binaryType, PackageBinding packageBinding) {
+               lookupEnvironment.createBinaryTypeFrom(binaryType, packageBinding);
+       }
+
+       /**
+        * Add an additional compilation unit.
+        */
+       public void accept(ICompilationUnit sourceUnit) {
+               CompilationResult result = new CompilationResult(sourceUnit, 1, 1, this.compilerOptions.maxProblemsPerUnit);
+               CompilationUnitDeclaration parsedUnit =
+                       this.getParser().dietParse(sourceUnit, result);
+
+
+               lookupEnvironment.buildTypeBindings(parsedUnit);
+               lookupEnvironment.completeTypeBindings(parsedUnit, true);
+       }
+
+       /**
+        * Add additional source types (the first one is the requested type, the rest is formed by the
+        * secondary types defined in the same compilation unit).
+        */
+       public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding) {
+               CompilationResult result =
+                       new CompilationResult(sourceTypes[0].getFileName(), 1, 1, this.compilerOptions.maxProblemsPerUnit);
+               CompilationUnitDeclaration unit =
+                       SourceTypeConverter.buildCompilationUnit(
+                               sourceTypes,
+                               true,
+                               true,
+                               lookupEnvironment.problemReporter,
+                               result);
+
+               if (unit != null) {
+                       lookupEnvironment.buildTypeBindings(unit);
+                       lookupEnvironment.completeTypeBindings(unit, true);
+               }
+       }
+
+       public abstract AssistParser getParser();
+       
+       protected boolean mustQualifyType(
+               char[] packageName,
+               char[] typeName) {
+
+               // If there are no types defined into the current CU yet.
+               if (unitScope == null)
+                       return true;
+                       
+               char[][] compoundPackageName = CharOperation.splitOn('.', packageName);
+               char[] readableTypeName = CharOperation.concat(packageName, typeName, '.');
+
+               if (CharOperation.equals(unitScope.fPackage.compoundName, compoundPackageName))
+                       return false;
+
+               ImportBinding[] imports = unitScope.imports;
+               if (imports != null){
+                       for (int i = 0, length = imports.length; i < length; i++) {
+                               if (imports[i].onDemand) {
+                                       if (CharOperation.equals(imports[i].compoundName, compoundPackageName)) {
+                                               for (int j = 0; j < imports.length; j++) {
+                                                       if(i != j){
+                                                               if(imports[j].onDemand) {
+                                                                       if(nameEnvironment.findType(typeName, imports[j].compoundName) != null){
+                                                                               return true;
+                                                                       }
+                                                               } else {
+                                                                       if(CharOperation.equals(CharOperation.lastSegment(imports[j].readableName(), '.'), typeName)) {
+                                                                               return true;    
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                               return false; // how do you match p1.p2.A.* ?
+                                       }
+       
+                               } else
+       
+                                       if (CharOperation.equals(imports[i].readableName(), readableTypeName)) {
+                                               return false;
+                                       }
+                       }
+               }
+               return true;
+       }
+
+       protected void parseMethod(CompilationUnitDeclaration unit, int position) {
+               for (int i = unit.types.length; --i >= 0;) {
+                       TypeDeclaration type = unit.types[i];
+                       if (type.declarationSourceStart < position
+                               && type.declarationSourceEnd >= position) {
+                               getParser().scanner.setSource(
+                                       unit.compilationResult.compilationUnit.getContents());
+                               parseMethod(type, unit, position);
+                               return;
+                       }
+               }
+       }
+
+       private void parseMethod(
+               TypeDeclaration type,
+               CompilationUnitDeclaration unit,
+               int position) {
+               //members
+               TypeDeclaration[] memberTypes = type.memberTypes;
+               if (memberTypes != null) {
+                       for (int i = memberTypes.length; --i >= 0;) {
+                               TypeDeclaration memberType = memberTypes[i];
+                               if (memberType.bodyStart > position)
+                                       continue;
+                               if (memberType.declarationSourceEnd >= position) {
+                                       parseMethod(memberType, unit, position);
+                                       return;
+                               }
+                       }
+               }
+               //methods
+               AbstractMethodDeclaration[] methods = type.methods;
+               if (methods != null) {
+                       for (int i = methods.length; --i >= 0;) {
+                               AbstractMethodDeclaration method = methods[i];
+                               if (method.bodyStart > position)
+                                       continue;
+                               if (method.declarationSourceEnd >= position) {
+                                       getParser().parseBlockStatements(method, unit);
+                                       return;
+                               }
+                       }
+               }
+               //initializers
+               FieldDeclaration[] fields = type.fields;
+               if (fields != null) {
+                       for (int i = fields.length; --i >= 0;) {
+                               if (!(fields[i] instanceof Initializer))
+                                       continue;
+                               Initializer initializer = (Initializer) fields[i];
+                               if (initializer.bodyStart > position)
+                                       continue;
+                               if (initializer.declarationSourceEnd >= position) {
+                                       getParser().parseBlockStatements(initializer, type, unit);
+                                       return;
+                               }
+                       }
+               }
+       }
+
+       protected void reset() {
+               lookupEnvironment.reset();
+       }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionNodeFound.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionNodeFound.java
new file mode 100644 (file)
index 0000000..6d8a66f
--- /dev/null
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.select;
+
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+public class SelectionNodeFound extends RuntimeException {
+       public Binding binding;
+public SelectionNodeFound() {
+       this(null); // we found a problem in the selection node
+}
+public SelectionNodeFound(Binding binding) {
+       this.binding = binding;
+}
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnArgumentName.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnArgumentName.java
new file mode 100644 (file)
index 0000000..06a6783
--- /dev/null
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.select;
+
+import net.sourceforge.phpdt.internal.compiler.ast.Argument;
+import net.sourceforge.phpdt.internal.compiler.ast.TypeReference;
+import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
+import net.sourceforge.phpdt.internal.compiler.lookup.MethodScope;
+import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
+
+public class SelectionOnArgumentName extends Argument {
+       public SelectionOnArgumentName(char[] name , long posNom , TypeReference tr , int modifiers){
+               super(name, posNom, tr, modifiers);
+       }
+       
+       public void resolve(BlockScope scope) {
+               super.resolve(scope);
+               throw new SelectionNodeFound(binding);
+       }
+       
+       public void bind(MethodScope scope, TypeBinding typeBinding, boolean used) {
+               super.bind(scope, typeBinding, used);
+               
+               throw new SelectionNodeFound(binding);
+       }
+       
+       public String toString(int tab) {
+               String s = tabString(tab);
+               s += "<SelectionOnArgumentName:"; //$NON-NLS-1$
+               if (type != null) s += type.toString() + " "; //$NON-NLS-1$
+               s += new String(name());
+               if (initialization != null) s += " = " + initialization.toStringExpression(); //$NON-NLS-1$
+               s += ">"; //$NON-NLS-1$
+               return s;
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnExplicitConstructorCall.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnExplicitConstructorCall.java
new file mode 100644 (file)
index 0000000..6dc4365
--- /dev/null
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.select;
+
+/*
+ * Selection node build by the parser in any case it was intending to
+ * reduce an explicit constructor call containing the cursor.
+ * e.g.
+ *
+ *     class X {
+ *    void foo() {
+ *      Y.[start]super[end](1, 2)
+ *    }
+ *  }
+ *
+ *     ---> class X {
+ *         void foo() {
+ *           <SelectOnExplicitConstructorCall:Y.super(1, 2)>
+ *         }
+ *       }
+ *
+ */
+
+import net.sourceforge.phpdt.internal.compiler.ast.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+public class SelectionOnExplicitConstructorCall extends ExplicitConstructorCall {
+public SelectionOnExplicitConstructorCall(int accessMode) {
+       super(accessMode);
+}
+public void resolve(BlockScope scope) {
+       super.resolve(scope);
+
+       // tolerate some error cases
+       if (binding == null || 
+                       !(binding.isValidBinding() ||
+                               binding.problemId() == ProblemReasons.NotVisible))
+               throw new SelectionNodeFound();
+       else
+               throw new SelectionNodeFound(binding);
+}
+public String toString(int tab) {
+       String s = tabString(tab);
+       s += "<SelectOnExplicitConstructorCall:"; //$NON-NLS-1$
+       if (qualification != null)
+               s = s + qualification.toStringExpression() + "."; //$NON-NLS-1$
+       if (accessMode == This) {
+               s = s + "this("; //$NON-NLS-1$
+       } else {
+               s = s + "super("; //$NON-NLS-1$
+       }
+       if (arguments != null) {
+               for (int i = 0; i < arguments.length; i++) {
+                       s += arguments[i].toStringExpression();
+                       if (i != arguments.length - 1) {
+                               s += ", "; //$NON-NLS-1$
+                       }
+               };
+       }
+       s += ")>"; //$NON-NLS-1$
+       return s;
+}
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnFieldReference.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnFieldReference.java
new file mode 100644 (file)
index 0000000..c5545c0
--- /dev/null
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.select;
+
+/*
+ * Selection node build by the parser in any case it was intending to
+ * reduce a field reference containing the cursor.
+ * e.g.
+ *
+ *     class X {
+ *    void foo() {
+ *      bar().[start]fred[end]
+ *    }
+ *  }
+ *
+ *     ---> class X {
+ *         void foo() {
+ *           <SelectOnFieldReference:bar().fred>
+ *         }
+ *       }
+ *
+ */
+import net.sourceforge.phpdt.internal.compiler.ast.FieldReference;
+import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
+import net.sourceforge.phpdt.internal.compiler.lookup.ProblemReasons;
+import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
+
+public class SelectionOnFieldReference extends FieldReference {
+public SelectionOnFieldReference(char[] source , long pos) {
+       super(source, pos);
+}
+public TypeBinding resolveType(BlockScope scope) {
+       super.resolveType(scope);
+
+               // tolerate some error cases
+               if (binding == null || 
+                               !(binding.isValidBinding() || 
+                                       binding.problemId() == ProblemReasons.NotVisible
+                                       || binding.problemId() == ProblemReasons.InheritedNameHidesEnclosingName
+                                       || binding.problemId() == ProblemReasons.NonStaticReferenceInConstructorInvocation
+                                       || binding.problemId() == ProblemReasons.NonStaticReferenceInStaticContext))
+               throw new SelectionNodeFound();
+       else
+               throw new SelectionNodeFound(binding);
+}
+public String toStringExpression(){
+       return  "<SelectionOnFieldReference:"  //$NON-NLS-1$
+                       + super.toStringExpression() 
+                       + ">"; //$NON-NLS-1$
+}
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnFieldType.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnFieldType.java
new file mode 100644 (file)
index 0000000..aaa85c6
--- /dev/null
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.select;
+
+import net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.TypeReference;
+
+public class SelectionOnFieldType extends FieldDeclaration {
+       public SelectionOnFieldType(TypeReference type) {
+               super();
+               this.sourceStart = type.sourceStart;
+               this.sourceEnd = type.sourceEnd;
+               this.type = type;
+               this.name = NoChar;
+       }
+       public String toString(int tab) {
+               return type.toString(tab);
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnImportReference.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnImportReference.java
new file mode 100644 (file)
index 0000000..210eeb2
--- /dev/null
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.select;
+
+/*
+ * Selection node build by the parser in any case it was intending to
+ * reduce an import reference containing the assist identifier.
+ * e.g.
+ *
+ *  import java.[start]io[end].*;
+ *     class X {
+ *    void foo() {
+ *    }
+ *  }
+ *
+ *     ---> <SelectOnImport:java.io>
+ *              class X {
+ *         void foo() {
+ *         }
+ *       }
+ *
+ */
+import net.sourceforge.phpdt.internal.compiler.ast.ImportReference;
+
+public class SelectionOnImportReference extends ImportReference {
+
+public SelectionOnImportReference(char[][] tokens , long[] positions) {
+       super(tokens, positions, false);
+}
+public String toString(int tab, boolean withOnDemand) {
+
+       StringBuffer buffer = new StringBuffer(tabString(tab));
+       buffer. append("<SelectOnImport:"); //$NON-NLS-1$
+       for (int i = 0; i < tokens.length; i++) {
+               buffer.append(tokens[i]);
+               if (i < (tokens.length - 1)) {
+                       buffer.append("."); //$NON-NLS-1$
+               }
+       }
+       buffer.append(">"); //$NON-NLS-1$
+       return buffer.toString();
+}
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnLocalName.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnLocalName.java
new file mode 100644 (file)
index 0000000..da3cc76
--- /dev/null
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.select;
+
+import net.sourceforge.phpdt.internal.compiler.ast.Expression;
+import net.sourceforge.phpdt.internal.compiler.ast.LocalDeclaration;
+import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
+
+public class SelectionOnLocalName extends LocalDeclaration{
+       public SelectionOnLocalName(Expression expr, char[] name,       int sourceStart, int sourceEnd) {
+               super(expr, name, sourceStart, sourceEnd);
+       }
+       
+       public void resolve(BlockScope scope) {
+               super.resolve(scope);
+               throw new SelectionNodeFound(binding);
+       }
+       
+       public String toString(int tab) {
+               String s = tabString(tab);
+               s += "<SelectionOnLocalName:"; //$NON-NLS-1$
+               if (modifiers != AccDefault) {
+                       s += modifiersString(modifiers);
+               }
+               s += type.toString(0) + " " + new String(name()); //$NON-NLS-1$
+               if (initialization != null) s += " = " + initialization.toStringExpression(); //$NON-NLS-1$
+               s+= ">";//$NON-NLS-1$
+               return s;       
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnMessageSend.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnMessageSend.java
new file mode 100644 (file)
index 0000000..70c5128
--- /dev/null
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.select;
+
+/*
+ * Selection node build by the parser in any case it was intending to
+ * reduce a message send containing the cursor.
+ * e.g.
+ *
+ *     class X {
+ *    void foo() {
+ *      this.[start]bar[end](1, 2)
+ *    }
+ *  }
+ *
+ *     ---> class X {
+ *         void foo() {
+ *           <SelectOnMessageSend:this.bar(1, 2)>
+ *         }
+ *       }
+ *
+ */
+
+import net.sourceforge.phpdt.internal.compiler.ast.MessageSend;
+import net.sourceforge.phpdt.internal.compiler.ast.ThisReference;
+import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
+import net.sourceforge.phpdt.internal.compiler.lookup.ProblemReasons;
+import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
+
+public class SelectionOnMessageSend extends MessageSend {
+
+       public TypeBinding resolveType(BlockScope scope) {
+               super.resolveType(scope);
+
+               // tolerate some error cases
+               if(binding == null ||
+                                       !(binding.isValidBinding() || 
+                                               binding.problemId() == ProblemReasons.NotVisible
+                                               || binding.problemId() == ProblemReasons.InheritedNameHidesEnclosingName
+                                               || binding.problemId() == ProblemReasons.NonStaticReferenceInConstructorInvocation
+                                               || binding.problemId() == ProblemReasons.NonStaticReferenceInStaticContext)) {
+                       throw new SelectionNodeFound();
+               } else {
+                       throw new SelectionNodeFound(binding);
+               }
+       }
+
+       public String toStringExpression() {
+               String s = "<SelectOnMessageSend:"; //$NON-NLS-1$
+               if (receiver != ThisReference.ThisImplicit)
+                       s = s + receiver.toStringExpression() + "."; //$NON-NLS-1$
+               s = s + new String(selector) + "("; //$NON-NLS-1$
+               if (arguments != null) {
+                       for (int i = 0; i < arguments.length; i++) {
+                               s += arguments[i].toStringExpression();
+                               if (i != arguments.length - 1) {
+                                       s += ", "; //$NON-NLS-1$
+                               }
+                       };
+               }
+               s = s + ")>"; //$NON-NLS-1$
+               return s;
+       }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnPackageReference.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnPackageReference.java
new file mode 100644 (file)
index 0000000..87a344b
--- /dev/null
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.select;
+
+/*
+ * Selection node build by the parser in any case it was intending to
+ * reduce an package statement containing the assist identifier.
+ * e.g.
+ *
+ *  package java.[start]io[end];
+ *     class X {
+ *    void foo() {
+ *    }
+ *  }
+ *
+ *     ---> <SelectOnPackage:java.io>
+ *              class X {
+ *         void foo() {
+ *         }
+ *       }
+ *
+ */
+import net.sourceforge.phpdt.internal.compiler.ast.ImportReference;
+
+public class SelectionOnPackageReference extends ImportReference {
+public SelectionOnPackageReference(char[][] tokens , long[] positions) {
+       super(tokens, positions, true);
+}
+public String toString(int tab, boolean withOnDemand) {
+       StringBuffer buffer = new StringBuffer(tabString(tab));
+       buffer. append("<SelectOnPackage:"); //$NON-NLS-1$
+       for (int i = 0; i < tokens.length; i++) {
+               buffer.append(tokens[i]);
+               if (i < (tokens.length - 1)) {
+                       buffer.append("."); //$NON-NLS-1$
+               }
+       }
+       buffer.append(">"); //$NON-NLS-1$
+       return buffer.toString();
+}
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnQualifiedAllocationExpression.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnQualifiedAllocationExpression.java
new file mode 100644 (file)
index 0000000..d679001
--- /dev/null
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.select;
+
+/*
+ * Selection node build by the parser in any case it was intending to
+ * reduce an allocation expression containing the cursor.
+ * If the allocation expression is not qualified, the enclosingInstance field
+ * is null.
+ * e.g.
+ *
+ *     class X {
+ *    void foo() {
+ *      new [start]Bar[end](1, 2)
+ *    }
+ *  }
+ *
+ *     ---> class X {
+ *         void foo() {
+ *           <SelectOnAllocationExpression:new Bar(1, 2)>
+ *         }
+ *       }
+ *
+ */
+
+import net.sourceforge.phpdt.internal.compiler.ast.AnonymousLocalTypeDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.ConstructorDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.QualifiedAllocationExpression;
+import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
+import net.sourceforge.phpdt.internal.compiler.lookup.ProblemReasons;
+import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
+public class SelectionOnQualifiedAllocationExpression extends QualifiedAllocationExpression {
+public SelectionOnQualifiedAllocationExpression() {
+}
+public SelectionOnQualifiedAllocationExpression(AnonymousLocalTypeDeclaration anonymous) {
+       anonymousType = anonymous ;
+}
+public TypeBinding resolveType(BlockScope scope) {
+       super.resolveType(scope);
+
+       // tolerate some error cases
+       if (binding == null || 
+                       !(binding.isValidBinding() || 
+                               binding.problemId() == ProblemReasons.NotVisible))
+               throw new SelectionNodeFound();
+       if (anonymousType == null)
+               throw new SelectionNodeFound(binding);
+
+       // if selecting a type for an anonymous type creation, we have to
+       // find its target super constructor (if extending a class) or its target 
+       // super interface (if extending an interface)
+       if (anonymousType.binding.superInterfaces == NoSuperInterfaces) {
+               // find the constructor binding inside the super constructor call
+               ConstructorDeclaration constructor = (ConstructorDeclaration) anonymousType.declarationOf(binding);
+               throw new SelectionNodeFound(constructor.constructorCall.binding);
+       } else {
+               // open on the only superinterface
+               throw new SelectionNodeFound(anonymousType.binding.superInterfaces[0]);
+       }
+}
+public String toStringExpression(int tab) {
+       return 
+               ((this.enclosingInstance == null) ? 
+                       "<SelectOnAllocationExpression:" :  //$NON-NLS-1$
+                       "<SelectOnQualifiedAllocationExpression:") +  //$NON-NLS-1$
+               super.toStringExpression(tab) + ">"; //$NON-NLS-1$
+}
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnQualifiedNameReference.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnQualifiedNameReference.java
new file mode 100644 (file)
index 0000000..3fd7a85
--- /dev/null
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.select;
+
+/*
+ * Selection node build by the parser in any case it was intending to
+ * reduce a qualified name reference containing the assist identifier.
+ * e.g.
+ *
+ *     class X {
+ *    Y y;
+ *    void foo() {
+ *      y.fred.[start]ba[end]
+ *    }
+ *  }
+ *
+ *     ---> class X {
+ *         Y y;
+ *         void foo() {
+ *           <SelectOnName:y.fred.ba>
+ *         }
+ *       }
+ *
+ */
+
+import net.sourceforge.phpdt.internal.compiler.ast.QualifiedNameReference;
+import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
+import net.sourceforge.phpdt.internal.compiler.lookup.FieldBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.ProblemFieldBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.ProblemReasons;
+import net.sourceforge.phpdt.internal.compiler.lookup.ProblemReferenceBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
+import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
+
+public class SelectionOnQualifiedNameReference extends QualifiedNameReference {
+       public long[] sourcePositions; // positions of each token, the last one being the positions of the completion identifier
+public SelectionOnQualifiedNameReference(char[][] previousIdentifiers, char[] selectionIdentifier, long[] positions) {
+       super(
+               CharOperation.arrayConcat(previousIdentifiers, selectionIdentifier),
+               (int) (positions[0] >>> 32),
+               (int) positions[positions.length - 1]);
+       this.sourcePositions = positions;
+}
+public TypeBinding resolveType(BlockScope scope) {
+       // it can be a package, type, member type, local variable or field
+       binding = scope.getBinding(tokens, this);
+       if (!binding.isValidBinding()) {
+               if (binding instanceof ProblemFieldBinding) {
+                       // tolerate some error cases
+                       if (binding.problemId() == ProblemReasons.NotVisible
+                                       || binding.problemId() == ProblemReasons.InheritedNameHidesEnclosingName
+                                       || binding.problemId() == ProblemReasons.NonStaticReferenceInConstructorInvocation
+                                       || binding.problemId() == ProblemReasons.NonStaticReferenceInStaticContext) {
+                               throw new SelectionNodeFound(binding);
+                       }
+                       scope.problemReporter().invalidField(this, (FieldBinding) binding);
+               } else if (binding instanceof ProblemReferenceBinding) {
+                       // tolerate some error cases
+                       if (binding.problemId() == ProblemReasons.NotVisible){
+                               throw new SelectionNodeFound(binding);
+                       }
+                       scope.problemReporter().invalidType(this, (TypeBinding) binding);
+               } else {
+                       scope.problemReporter().unresolvableReference(this, binding);
+               }
+               throw new SelectionNodeFound();
+       }
+       throw new SelectionNodeFound(binding);
+}
+public String toStringExpression() {
+
+       StringBuffer buffer = new StringBuffer("<SelectOnName:"); //$NON-NLS-1$
+       for (int i = 0, length = tokens.length; i < length; i++) {
+               buffer.append(tokens[i]);
+               if (i != length - 1)
+                       buffer.append("."); //$NON-NLS-1$
+       }
+       buffer.append(">"); //$NON-NLS-1$
+       return buffer.toString();
+}
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnQualifiedSuperReference.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnQualifiedSuperReference.java
new file mode 100644 (file)
index 0000000..b6cfe20
--- /dev/null
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.select;
+
+/*
+ * Selection node build by the parser in any case it was intending to
+ * reduce a qualified super reference containing the assist identifier.
+ * e.g.
+ *
+ *     class X extends Z {
+ *    class Y {
+ *     void foo() {
+ *             X.[start]super[end].bar();
+ *      }
+ *    }
+ *  }
+ *
+ *     ---> class X {
+ *                class Y {
+ *           void foo() {
+ *             <SelectOnQualifiedSuper:X.super>
+ *           }
+ *         }
+ *       }
+ *
+ */
+
+import net.sourceforge.phpdt.internal.compiler.ast.QualifiedSuperReference;
+import net.sourceforge.phpdt.internal.compiler.ast.TypeReference;
+import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
+import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
+
+public class SelectionOnQualifiedSuperReference extends QualifiedSuperReference {
+public SelectionOnQualifiedSuperReference(TypeReference name, int pos, int sourceEnd) {
+       super(name, pos, sourceEnd);
+}
+public TypeBinding resolveType(BlockScope scope) {
+       TypeBinding binding = super.resolveType(scope);
+
+       if (binding == null || !binding.isValidBinding())
+               throw new SelectionNodeFound();
+       else
+               throw new SelectionNodeFound(binding);
+}
+public String toStringExpression(){
+       
+       StringBuffer buffer = new StringBuffer("<SelectOnQualifiedSuper:"); //$NON-NLS-1$
+       buffer.append(super.toStringExpression());
+       buffer.append(">"); //$NON-NLS-1$
+       return buffer.toString();
+}
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnQualifiedTypeReference.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnQualifiedTypeReference.java
new file mode 100644 (file)
index 0000000..5d49dfb
--- /dev/null
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.select;
+
+/*
+ * Selection node build by the parser in any case it was intending to
+ * reduce a type reference containing the completion identifier as part
+ * of a qualified name.
+ * e.g.
+ *
+ *     class X extends java.lang.[start]Object[end]
+ *
+ *     ---> class X extends <SelectOnType:java.lang.Object>
+ *
+ */
+import net.sourceforge.phpdt.internal.compiler.ast.QualifiedTypeReference;
+import net.sourceforge.phpdt.internal.compiler.lookup.Binding;
+import net.sourceforge.phpdt.internal.compiler.lookup.ProblemReasons;
+import net.sourceforge.phpdt.internal.compiler.lookup.Scope;
+import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
+import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
+
+public class SelectionOnQualifiedTypeReference extends QualifiedTypeReference {
+public SelectionOnQualifiedTypeReference(char[][] previousIdentifiers, char[] selectionIdentifier, long[] positions) {
+       super(
+               CharOperation.arrayConcat(previousIdentifiers, selectionIdentifier),
+               positions);
+}
+public void aboutToResolve(Scope scope) {
+       getTypeBinding(scope.parent); // step up from the ClassScope
+}
+public TypeBinding getTypeBinding(Scope scope) {
+       // it can be a package, type or member type
+       Binding binding = scope.getTypeOrPackage(tokens);
+       if (!binding.isValidBinding()) {
+                       // tolerate some error cases
+                       if (binding.problemId() == ProblemReasons.NotVisible){
+                               throw new SelectionNodeFound(binding);
+                       }
+               scope.problemReporter().invalidType(this, (TypeBinding) binding);
+               throw new SelectionNodeFound();
+       }
+
+       throw new SelectionNodeFound(binding);
+}
+public String toStringExpression(int tab) {
+
+       StringBuffer buffer = new StringBuffer();
+       buffer.append("<SelectOnType:"); //$NON-NLS-1$
+       for (int i = 0, length = tokens.length; i < length; i++) {
+               buffer.append(tokens[i]);
+               if (i != length - 1)
+                       buffer.append("."); //$NON-NLS-1$
+       }
+       buffer.append(">"); //$NON-NLS-1$
+       return buffer.toString();
+}
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnSingleNameReference.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnSingleNameReference.java
new file mode 100644 (file)
index 0000000..9589df2
--- /dev/null
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.select;
+
+/*
+ * Selection node build by the parser in any case it was intending to
+ * reduce a single name reference containing the assist identifier.
+ * e.g.
+ *
+ *     class X {
+ *    void foo() {
+ *      [start]ba[end]
+ *    }
+ *  }
+ *
+ *     ---> class X {
+ *         void foo() {
+ *           <SelectOnName:ba>
+ *         }
+ *       }
+ *
+ */
+
+import net.sourceforge.phpdt.internal.compiler.ast.SingleNameReference;
+import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
+import net.sourceforge.phpdt.internal.compiler.lookup.FieldBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.ProblemFieldBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.ProblemReasons;
+import net.sourceforge.phpdt.internal.compiler.lookup.ProblemReferenceBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
+public class SelectionOnSingleNameReference extends SingleNameReference {
+public SelectionOnSingleNameReference(char[] source, long pos) {
+       super(source, pos);
+}
+public TypeBinding resolveType(BlockScope scope) {
+       // it can be a package, type, member type, local variable or field
+       binding = scope.getBinding(token, VARIABLE | TYPE | PACKAGE, this);
+       if (!binding.isValidBinding()) {
+               if (binding instanceof ProblemFieldBinding) {
+                       // tolerate some error cases
+                       if (binding.problemId() == ProblemReasons.NotVisible
+                                       || binding.problemId() == ProblemReasons.InheritedNameHidesEnclosingName
+                                       || binding.problemId() == ProblemReasons.NonStaticReferenceInConstructorInvocation
+                                       || binding.problemId() == ProblemReasons.NonStaticReferenceInStaticContext){
+                               throw new SelectionNodeFound(binding);
+                       }
+                       scope.problemReporter().invalidField(this, (FieldBinding) binding);
+               } else if (binding instanceof ProblemReferenceBinding) {
+                       // tolerate some error cases
+                       if (binding.problemId() == ProblemReasons.NotVisible){
+                               throw new SelectionNodeFound(binding);
+                       }                       
+                       scope.problemReporter().invalidType(this, (TypeBinding) binding);
+               } else {
+                       scope.problemReporter().unresolvableReference(this, binding);
+               }
+               throw new SelectionNodeFound();
+       }
+
+       throw new SelectionNodeFound(binding);
+}
+public String toStringExpression() {
+       return "<SelectOnName:" + super.toStringExpression() + ">"; //$NON-NLS-2$ //$NON-NLS-1$
+}
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnSingleTypeReference.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnSingleTypeReference.java
new file mode 100644 (file)
index 0000000..7b4e42c
--- /dev/null
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.select;
+
+/*
+ * Selection node build by the parser in any case it was intending to
+ * reduce a type reference containing the selection identifier as a single
+ * name reference.
+ * e.g.
+ *
+ *     class X extends [start]Object[end]
+ *
+ *     ---> class X extends <SelectOnType:Object>
+ *
+ */
+import net.sourceforge.phpdt.internal.compiler.ast.SingleTypeReference;
+import net.sourceforge.phpdt.internal.compiler.lookup.Binding;
+import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
+import net.sourceforge.phpdt.internal.compiler.lookup.ProblemReasons;
+import net.sourceforge.phpdt.internal.compiler.lookup.ReferenceBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.Scope;
+import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
+
+public class SelectionOnSingleTypeReference extends SingleTypeReference {
+public SelectionOnSingleTypeReference(char[] source, long pos) {
+       super(source, pos);
+}
+public void aboutToResolve(Scope scope) {
+       getTypeBinding(scope.parent); // step up from the ClassScope
+}
+public TypeBinding getTypeBinding(Scope scope) {
+       // it can be a package, type or member type
+       Binding binding = scope.getTypeOrPackage(new char[][] {token});
+       if (!binding.isValidBinding()) {
+               scope.problemReporter().invalidType(this, (TypeBinding) binding);
+               throw new SelectionNodeFound();
+       }
+
+       throw new SelectionNodeFound(binding);
+}
+public TypeBinding resolveTypeEnclosing(BlockScope scope, ReferenceBinding enclosingType) {
+       super.resolveTypeEnclosing(scope, enclosingType);
+
+               // tolerate some error cases
+               if (binding == null || 
+                               !(binding.isValidBinding() || 
+                                       binding.problemId() == ProblemReasons.NotVisible))
+               throw new SelectionNodeFound();
+       else
+               throw new SelectionNodeFound(binding);
+}
+public String toStringExpression(int tab){
+
+       return "<SelectOnType:" + new String(token) + ">" ; //$NON-NLS-2$ //$NON-NLS-1$
+}
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnSuperReference.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionOnSuperReference.java
new file mode 100644 (file)
index 0000000..13582bf
--- /dev/null
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.select;
+
+/*
+ * Selection node build by the parser in any case it was intending to
+ * reduce a super reference containing the assist identifier.
+ * e.g.
+ *
+ *     class X extends Z {
+ *    class Y {
+ *     void foo() {
+ *             [start]super[end].bar();
+ *      }
+ *    }
+ *  }
+ *
+ *     ---> class X {
+ *                class Y {
+ *           void foo() {
+ *             <SelectOnQualifiedSuper:super>
+ *           }
+ *         }
+ *       }
+ *
+ */
+
+import net.sourceforge.phpdt.internal.compiler.ast.SuperReference;
+import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
+import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
+
+public class SelectionOnSuperReference extends SuperReference {
+
+public SelectionOnSuperReference(int pos, int sourceEnd) {
+       super(pos, sourceEnd);
+}
+public TypeBinding resolveType(BlockScope scope) {
+       TypeBinding binding = super.resolveType(scope);
+
+       if (binding == null || !binding.isValidBinding())
+               throw new SelectionNodeFound();
+       else
+               throw new SelectionNodeFound(binding);
+}
+public String toStringExpression(){
+
+       return "<SelectOnSuper:"+super.toStringExpression()+">"; //$NON-NLS-2$ //$NON-NLS-1$
+       
+}
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionParser.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionParser.java
new file mode 100644 (file)
index 0000000..99f38b0
--- /dev/null
@@ -0,0 +1,686 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.select;
+
+/*
+ * Parser able to build specific completion parse nodes, given a cursorLocation.
+ *
+ * Cursor location denotes the position of the last character behind which completion
+ * got requested:
+ *  -1 means completion at the very beginning of the source
+ *     0  means completion behind the first character
+ *  n  means completion behind the n-th character
+ */
+import net.sourceforge.phpdt.internal.compiler.*;
+import net.sourceforge.phpdt.internal.compiler.env.*;
+
+import net.sourceforge.phpdt.internal.codeassist.impl.*;
+import net.sourceforge.phpdt.internal.compiler.ast.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
+import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
+import net.sourceforge.phpdt.internal.compiler.parser.*;
+import net.sourceforge.phpdt.internal.compiler.problem.*;
+import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
+
+public class SelectionParser extends AssistParser {
+
+       /* public fields */
+
+       public int selectionStart, selectionEnd;
+
+       public static final char[] SUPER = "super".toCharArray(); //$NON-NLS-1$
+       public static final char[] THIS = "this".toCharArray(); //$NON-NLS-1$
+       
+public SelectionParser(ProblemReporter problemReporter, boolean assertMode) {
+       super(problemReporter, assertMode);
+}
+public char[] assistIdentifier(){
+       return ((SelectionScanner)scanner).selectionIdentifier;
+}
+protected void attachOrphanCompletionNode(){
+       if (isOrphanCompletionNode){
+               AstNode orphan = this.assistNode;
+               isOrphanCompletionNode = false;
+               
+               
+               /* if in context of a type, then persists the identifier into a fake field return type */
+               if (currentElement instanceof RecoveredType){
+                       RecoveredType recoveredType = (RecoveredType)currentElement;
+                       /* filter out cases where scanner is still inside type header */
+                       if (recoveredType.foundOpeningBrace) {
+                               /* generate a pseudo field with a completion on type reference */       
+                               if (orphan instanceof TypeReference){
+                                       currentElement = currentElement.add(new SelectionOnFieldType((TypeReference)orphan), 0);
+                                       return;
+                               }
+                       }
+               }
+               
+               Statement statement = (Statement)wrapWithExplicitConstructorCallIfNeeded(orphan);
+               currentElement = currentElement.add(statement, 0);
+               currentToken = 0; // given we are not on an eof, we do not want side effects caused by looked-ahead token
+       }
+}
+
+private boolean checkRecoveredType() {
+       if (currentElement instanceof RecoveredType){
+               /* check if current awaiting identifier is the completion identifier */
+               if (this.indexOfAssistIdentifier() < 0) return false;
+
+               if ((lastErrorEndPosition >= selectionStart)
+                       && (lastErrorEndPosition <= selectionEnd+1)){
+                       return false;
+               }
+               RecoveredType recoveredType = (RecoveredType)currentElement;
+               /* filter out cases where scanner is still inside type header */
+               if (recoveredType.foundOpeningBrace) {
+                       this.assistNode = this.getTypeReference(0);
+                       this.lastCheckPoint = this.assistNode.sourceEnd + 1;
+                       this.isOrphanCompletionNode = true;
+                       return true;
+               }
+       }
+       return false;
+}
+protected void classInstanceCreation(boolean alwaysQualified) {
+       
+       // ClassInstanceCreationExpression ::= 'new' ClassType '(' ArgumentListopt ')' ClassBodyopt
+
+       // ClassBodyopt produces a null item on the astStak if it produces NO class body
+       // An empty class body produces a 0 on the length stack.....
+
+       int length;
+       if (((length = astLengthStack[astLengthPtr]) == 1)
+               && (astStack[astPtr] == null)) {
+
+               if (this.indexOfAssistIdentifier() < 0) {
+                       super.classInstanceCreation(alwaysQualified);
+                       return;
+               }
+               QualifiedAllocationExpression alloc;
+               astPtr--;
+               astLengthPtr--;
+               alloc = new SelectionOnQualifiedAllocationExpression();
+               alloc.sourceEnd = endPosition; //the position has been stored explicitly
+
+               if ((length = expressionLengthStack[expressionLengthPtr--]) != 0) {
+                       expressionPtr -= length;
+                       System.arraycopy(
+                               expressionStack, 
+                               expressionPtr + 1, 
+                               alloc.arguments = new Expression[length], 
+                               0, 
+                               length); 
+               }
+               // trick to avoid creating a selection on type reference
+               char [] oldIdent = this.assistIdentifier();
+               this.setAssistIdentifier(null);                 
+               alloc.type = getTypeReference(0);
+               this.setAssistIdentifier(oldIdent);
+               
+               //the default constructor with the correct number of argument
+               //will be created and added by the TC (see createsInternalConstructorWithBinding)
+               alloc.sourceStart = intStack[intPtr--];
+               pushOnExpressionStack(alloc);
+
+               this.assistNode = alloc;
+               this.lastCheckPoint = alloc.sourceEnd + 1;
+               if (!diet){
+                       this.restartRecovery    = true; // force to restart in recovery mode
+                       this.lastIgnoredToken = -1;     
+               }
+               this.isOrphanCompletionNode = true;
+       } else {
+               super.classInstanceCreation(alwaysQualified);
+       }
+}
+
+protected void consumeArrayCreationExpression() {
+       // ArrayCreationExpression ::= 'new' PrimitiveType DimWithOrWithOutExprs ArrayInitializeropt
+       // ArrayCreationExpression ::= 'new' ClassOrInterfaceType DimWithOrWithOutExprs ArrayInitializeropt
+
+       super.consumeArrayCreationExpression();
+
+       ArrayAllocationExpression alloc = (ArrayAllocationExpression)expressionStack[expressionPtr];
+       if (alloc.type == assistNode){
+               if (!diet){
+                       this.restartRecovery    = true; // force to restart in recovery mode
+                       this.lastIgnoredToken = -1;     
+               }
+               this.isOrphanCompletionNode = true;
+       }
+}
+protected void consumeEnterAnonymousClassBody() {
+       // EnterAnonymousClassBody ::= $empty
+
+       if (this.indexOfAssistIdentifier() < 0) {
+               super.consumeEnterAnonymousClassBody();
+               return;
+       }
+       QualifiedAllocationExpression alloc;
+       AnonymousLocalTypeDeclaration anonymousType = 
+               new AnonymousLocalTypeDeclaration(this.compilationUnit.compilationResult); 
+       alloc = 
+               anonymousType.allocation = new SelectionOnQualifiedAllocationExpression(anonymousType); 
+       markCurrentMethodWithLocalType();
+       pushOnAstStack(anonymousType);
+
+       alloc.sourceEnd = rParenPos; //the position has been stored explicitly
+       int argumentLength;
+       if ((argumentLength = expressionLengthStack[expressionLengthPtr--]) != 0) {
+               expressionPtr -= argumentLength;
+               System.arraycopy(
+                       expressionStack, 
+                       expressionPtr + 1, 
+                       alloc.arguments = new Expression[argumentLength], 
+                       0, 
+                       argumentLength); 
+       }
+       // trick to avoid creating a selection on type reference
+       char [] oldIdent = this.assistIdentifier();
+       this.setAssistIdentifier(null);                 
+       alloc.type = getTypeReference(0);
+       this.setAssistIdentifier(oldIdent);             
+
+       anonymousType.sourceEnd = alloc.sourceEnd;
+       //position at the type while it impacts the anonymous declaration
+       anonymousType.sourceStart = anonymousType.declarationSourceStart = alloc.type.sourceStart;
+       alloc.sourceStart = intStack[intPtr--];
+       pushOnExpressionStack(alloc);
+
+       assistNode = alloc;
+       this.lastCheckPoint = alloc.sourceEnd + 1;
+       if (!diet){
+               this.restartRecovery    = true; // force to restart in recovery mode
+               this.lastIgnoredToken = -1;     
+       }
+       this.isOrphanCompletionNode = true;
+               
+       anonymousType.bodyStart = scanner.currentPosition;      
+       listLength = 0; // will be updated when reading super-interfaces
+       // recovery
+       if (currentElement != null){ 
+               lastCheckPoint = anonymousType.bodyStart;
+               currentElement = currentElement.add(anonymousType, 0); // the recoveryTokenCheck will deal with the open brace
+               lastIgnoredToken = -1;          
+       }
+}
+protected void consumeEnterVariable() {
+       // EnterVariable ::= $empty
+       // do nothing by default
+
+       super.consumeEnterVariable();
+
+       AbstractVariableDeclaration variable = (AbstractVariableDeclaration) astStack[astPtr];
+       if (variable.type == assistNode){
+               if (!diet){
+                       this.restartRecovery    = true; // force to restart in recovery mode
+                       this.lastIgnoredToken = -1;     
+               }
+               isOrphanCompletionNode = false; // already attached inside variable decl
+       }
+}
+
+protected void consumeExitVariableWithInitialization() {
+       super.consumeExitVariableWithInitialization();
+       
+       // does not keep the initialization if selection is not inside
+       AbstractVariableDeclaration variable = (AbstractVariableDeclaration) astStack[astPtr];
+       int start = variable.initialization.sourceStart;
+       int end =  variable.initialization.sourceEnd;
+       if ((selectionStart < start) &&  (selectionEnd < start) ||
+               (selectionStart > end) && (selectionEnd > end)) {
+               variable.initialization = null;
+       }
+}
+
+protected void consumeFieldAccess(boolean isSuperAccess) {
+       // FieldAccess ::= Primary '.' 'Identifier'
+       // FieldAccess ::= 'super' '.' 'Identifier'
+
+       if (this.indexOfAssistIdentifier() < 0) {
+               super.consumeFieldAccess(isSuperAccess);
+               return;
+       } 
+       FieldReference fieldReference = 
+               new SelectionOnFieldReference(
+                       identifierStack[identifierPtr], 
+                       identifierPositionStack[identifierPtr--]);
+       identifierLengthPtr--;
+       if (isSuperAccess) { //considerates the fieldReferenceerence beginning at the 'super' ....      
+               fieldReference.sourceStart = intStack[intPtr--];
+               fieldReference.receiver = new SuperReference(fieldReference.sourceStart, endPosition);
+               pushOnExpressionStack(fieldReference);
+       } else { //optimize push/pop
+               if ((fieldReference.receiver = expressionStack[expressionPtr]).isThis()) { //fieldReferenceerence begins at the this
+                       fieldReference.sourceStart = fieldReference.receiver.sourceStart;
+               }
+               expressionStack[expressionPtr] = fieldReference;
+       }
+       assistNode = fieldReference;
+       this.lastCheckPoint = fieldReference.sourceEnd + 1;
+       if (!diet){
+               this.restartRecovery    = true; // force to restart in recovery mode
+               this.lastIgnoredToken = -1;
+       }
+       this.isOrphanCompletionNode = true;     
+}
+protected void consumeFormalParameter() {
+       if (this.indexOfAssistIdentifier() < 0) {
+               super.consumeFormalParameter();
+       } else {
+
+               identifierLengthPtr--;
+               char[] name = identifierStack[identifierPtr];
+               long namePositions = identifierPositionStack[identifierPtr--];
+               TypeReference type = getTypeReference(intStack[intPtr--] + intStack[intPtr--]);
+               intPtr -= 2;
+               Argument arg = 
+                       new SelectionOnArgumentName(
+                               name, 
+                               namePositions, 
+                               type, 
+                               intStack[intPtr + 1] & ~AccDeprecated); // modifiers
+               pushOnAstStack(arg);
+               
+               assistNode = arg;
+               this.lastCheckPoint = (int) namePositions;
+               isOrphanCompletionNode = true;
+               
+               if (!diet){
+                       this.restartRecovery    = true; // force to restart in recovery mode
+                       this.lastIgnoredToken = -1;     
+               }
+
+               /* if incomplete method header, listLength counter will not have been reset,
+                       indicating that some arguments are available on the stack */
+               listLength++;
+       }       
+}
+protected void consumeInstanceOfExpression(int op) {
+       if (indexOfAssistIdentifier() < 0) {
+               super.consumeInstanceOfExpression(op);
+       } else {
+               getTypeReference(intStack[intPtr--]);
+               this.isOrphanCompletionNode = true;
+               this.restartRecovery = true;
+               this.lastIgnoredToken = -1;
+       }
+}
+protected void consumeMethodInvocationName() {
+       // MethodInvocation ::= Name '(' ArgumentListopt ')'
+
+       // when the name is only an identifier...we have a message send to "this" (implicit)
+
+       char[] selector = identifierStack[identifierPtr];
+       int accessMode;
+       if(selector == this.assistIdentifier()) {
+               if(CharOperation.equals(selector, SUPER)) {
+                       accessMode = ExplicitConstructorCall.Super;
+               } else if(CharOperation.equals(selector, THIS)) {
+                       accessMode = ExplicitConstructorCall.This;
+               } else {
+                       super.consumeMethodInvocationName();
+                       return;
+               }
+       } else {
+               super.consumeMethodInvocationName();
+               return;
+       }
+       
+       final ExplicitConstructorCall constructorCall = new SelectionOnExplicitConstructorCall(accessMode);
+       constructorCall.sourceEnd = rParenPos;
+       constructorCall.sourceStart = (int) (identifierPositionStack[identifierPtr] >>> 32);
+       int length;
+       if ((length = expressionLengthStack[expressionLengthPtr--]) != 0) {
+               expressionPtr -= length;
+               System.arraycopy(expressionStack, expressionPtr + 1, constructorCall.arguments = new Expression[length], 0, length);
+       }
+
+       if (!diet){
+               pushOnAstStack(constructorCall);
+               this.restartRecovery    = true; // force to restart in recovery mode
+               this.lastIgnoredToken = -1;
+       } else {
+               pushOnExpressionStack(new Expression(){
+                       public TypeBinding resolveType(BlockScope scope) {
+                               constructorCall.resolve(scope);
+                               return null;
+                       }
+               });
+       }
+       this.assistNode = constructorCall;      
+       this.lastCheckPoint = constructorCall.sourceEnd + 1;
+       this.isOrphanCompletionNode = true;
+}
+protected void consumeMethodInvocationPrimary() {
+       //optimize the push/pop
+       //MethodInvocation ::= Primary '.' 'Identifier' '(' ArgumentListopt ')'
+
+       char[] selector = identifierStack[identifierPtr];
+       int accessMode;
+       if(selector == this.assistIdentifier()) {
+               if(CharOperation.equals(selector, SUPER)) {
+                       accessMode = ExplicitConstructorCall.Super;
+               } else if(CharOperation.equals(selector, THIS)) {
+                       accessMode = ExplicitConstructorCall.This;
+               } else {
+                       super.consumeMethodInvocationPrimary();
+                       return;
+               }
+       } else {
+               super.consumeMethodInvocationPrimary();
+               return;
+       }
+       
+       final ExplicitConstructorCall constructorCall = new SelectionOnExplicitConstructorCall(accessMode);
+       constructorCall.sourceEnd = rParenPos;
+       int length;
+       if ((length = expressionLengthStack[expressionLengthPtr--]) != 0) {
+               expressionPtr -= length;
+               System.arraycopy(expressionStack, expressionPtr + 1, constructorCall.arguments = new Expression[length], 0, length);
+       }
+       constructorCall.qualification = expressionStack[expressionPtr--];
+       constructorCall.sourceStart = constructorCall.qualification.sourceStart;
+       
+       if (!diet){
+               pushOnAstStack(constructorCall);
+               this.restartRecovery    = true; // force to restart in recovery mode
+               this.lastIgnoredToken = -1;
+       } else {
+               pushOnExpressionStack(new Expression(){
+                       public TypeBinding resolveType(BlockScope scope) {
+                               constructorCall.resolve(scope);
+                               return null;
+                       }
+               });
+       }
+       
+       this.assistNode = constructorCall;
+       this.lastCheckPoint = constructorCall.sourceEnd + 1;
+       this.isOrphanCompletionNode = true;
+}
+protected void consumeTypeImportOnDemandDeclarationName() {
+       // TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
+       /* push an ImportRef build from the last name 
+       stored in the identifier stack. */
+
+       int index;
+
+       /* no need to take action if not inside assist identifiers */
+       if ((index = indexOfAssistIdentifier()) < 0) {
+               super.consumeTypeImportOnDemandDeclarationName();
+               return;
+       }
+       /* retrieve identifiers subset and whole positions, the assist node positions
+               should include the entire replaced source. */
+       int length = identifierLengthStack[identifierLengthPtr];
+       char[][] subset = identifierSubSet(index+1); // include the assistIdentifier
+       identifierLengthPtr--;
+       identifierPtr -= length;
+       long[] positions = new long[length];
+       System.arraycopy(
+               identifierPositionStack, 
+               identifierPtr + 1, 
+               positions, 
+               0, 
+               length); 
+
+       /* build specific assist node on import statement */
+       ImportReference reference = this.createAssistImportReference(subset, positions);
+       reference.onDemand = true;
+       assistNode = reference;
+       this.lastCheckPoint = reference.sourceEnd + 1;
+       
+       pushOnAstStack(reference);
+
+       if (currentToken == TokenNameSEMICOLON){
+               reference.declarationSourceEnd = scanner.currentPosition - 1;
+       } else {
+               reference.declarationSourceEnd = (int) positions[length-1];
+       }
+       //endPosition is just before the ;
+       reference.declarationSourceStart = intStack[intPtr--];
+       // flush annotations defined prior to import statements
+       reference.declarationSourceEnd = this.flushAnnotationsDefinedPriorTo(reference.declarationSourceEnd);
+
+       // recovery
+       if (currentElement != null){
+               lastCheckPoint = reference.declarationSourceEnd+1;
+               currentElement = currentElement.add(reference, 0);
+               lastIgnoredToken = -1;
+               restartRecovery = true; // used to avoid branching back into the regular automaton              
+       }
+}
+public ImportReference createAssistImportReference(char[][] tokens, long[] positions){
+       return new SelectionOnImportReference(tokens, positions);
+}
+public ImportReference createAssistPackageReference(char[][] tokens, long[] positions){
+       return new SelectionOnPackageReference(tokens, positions);
+}
+protected LocalDeclaration createLocalDeclaration(Expression initialization,char[] name,int sourceStart,int sourceEnd) {
+       if (this.indexOfAssistIdentifier() < 0) {
+               return super.createLocalDeclaration(initialization, name, sourceStart, sourceEnd);
+       } else {
+               SelectionOnLocalName local = new SelectionOnLocalName(initialization, name, sourceStart, sourceEnd);
+               this.assistNode = local;
+               this.lastCheckPoint = sourceEnd + 1;
+               if (!diet){
+                       this.restartRecovery    = true; // force to restart in recovery mode
+                       this.lastIgnoredToken = -1;     
+               }
+               return local;
+       }
+}
+public NameReference createQualifiedAssistNameReference(char[][] previousIdentifiers, char[] name, long[] positions){
+       return new SelectionOnQualifiedNameReference(
+                                       previousIdentifiers, 
+                                       name, 
+                                       positions);     
+}
+public TypeReference createQualifiedAssistTypeReference(char[][] previousIdentifiers, char[] name, long[] positions){
+       return new SelectionOnQualifiedTypeReference(
+                                       previousIdentifiers, 
+                                       name, 
+                                       positions);     
+}
+public NameReference createSingleAssistNameReference(char[] name, long position) {
+       return new SelectionOnSingleNameReference(name, position);
+}
+public TypeReference createSingleAssistTypeReference(char[] name, long position) {
+       return new SelectionOnSingleTypeReference(name, position);
+}
+public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int selectionStart, int selectionEnd) {
+
+       this.selectionStart = selectionStart;
+       this.selectionEnd = selectionEnd;       
+       SelectionScanner selectionScanner = (SelectionScanner)this.scanner;
+       selectionScanner.selectionIdentifier = null;
+       selectionScanner.selectionStart = selectionStart;
+       selectionScanner.selectionEnd = selectionEnd;   
+       return this.dietParse(sourceUnit, compilationResult);
+}
+protected NameReference getUnspecifiedReference() {
+       /* build a (unspecified) NameReference which may be qualified*/
+
+       int completionIndex;
+
+       /* no need to take action if not inside completed identifiers */
+       if ((completionIndex = indexOfAssistIdentifier()) < 0) {
+               return super.getUnspecifiedReference();
+       }
+
+       int length = identifierLengthStack[identifierLengthPtr];
+       if (CharOperation.equals(assistIdentifier(), SUPER)){
+               Reference reference;
+               if (completionIndex > 0){ // qualified super
+                       // discard 'super' from identifier stacks
+                       identifierLengthStack[identifierLengthPtr] = completionIndex;
+                       int ptr = identifierPtr -= (length - completionIndex);
+                       reference = 
+                               new SelectionOnQualifiedSuperReference(
+                                       getTypeReference(0), 
+                                       (int)(identifierPositionStack[ptr+1] >>> 32),
+                                       (int) identifierPositionStack[ptr+1]);
+               } else { // standard super
+                       identifierPtr -= length;
+                       identifierLengthPtr--;
+                       reference = new SelectionOnSuperReference((int)(identifierPositionStack[identifierPtr+1] >>> 32), (int) identifierPositionStack[identifierPtr+1]);
+               }
+               pushOnAstStack(reference);
+               this.assistNode = reference;    
+               this.lastCheckPoint = reference.sourceEnd + 1;
+               if (!diet || dietInt != 0){
+                       this.restartRecovery    = true; // force to restart in recovery mode
+                       this.lastIgnoredToken = -1;             
+               }
+               this.isOrphanCompletionNode = true;
+               return new SingleNameReference(new char[0], 0); // dummy reference
+       }
+       NameReference nameReference;
+       /* retrieve identifiers subset and whole positions, the completion node positions
+               should include the entire replaced source. */
+       char[][] subset = identifierSubSet(completionIndex);
+       identifierLengthPtr--;
+       identifierPtr -= length;
+       long[] positions = new long[length];
+       System.arraycopy(
+               identifierPositionStack, 
+               identifierPtr + 1, 
+               positions, 
+               0, 
+               length);
+       /* build specific completion on name reference */
+       if (completionIndex == 0) {
+               /* completion inside first identifier */
+               nameReference = this.createSingleAssistNameReference(assistIdentifier(), positions[0]);
+       } else {
+               /* completion inside subsequent identifier */
+               nameReference = this.createQualifiedAssistNameReference(subset, assistIdentifier(), positions);
+       }
+       assistNode = nameReference;
+       this.lastCheckPoint = nameReference.sourceEnd + 1;
+       if (!diet){
+               this.restartRecovery    = true; // force to restart in recovery mode
+               this.lastIgnoredToken = -1;     
+       }
+       this.isOrphanCompletionNode = true;
+       return nameReference;
+}
+/*
+ * Copy of code from superclass with the following change:
+ * In the case of qualified name reference if the cursor location is on the 
+ * qualified name reference, then create a CompletionOnQualifiedNameReference 
+ * instead.
+ */
+protected NameReference getUnspecifiedReferenceOptimized() {
+
+       int index = indexOfAssistIdentifier();
+       NameReference reference = super.getUnspecifiedReferenceOptimized();
+
+       if (index >= 0){
+               if (!diet){
+                       this.restartRecovery    = true; // force to restart in recovery mode
+                       this.lastIgnoredToken = -1;             
+               }
+               this.isOrphanCompletionNode = true;
+       }
+       return reference;
+}
+public void initializeScanner(){
+       this.scanner = new SelectionScanner(this.assertMode);
+}
+protected MessageSend newMessageSend() {
+       // '(' ArgumentListopt ')'
+       // the arguments are on the expression stack
+
+       char[] selector = identifierStack[identifierPtr];
+       if (selector != this.assistIdentifier()){
+               return super.newMessageSend();
+       }       
+       MessageSend messageSend = new SelectionOnMessageSend();
+       int length;
+       if ((length = expressionLengthStack[expressionLengthPtr--]) != 0) {
+               expressionPtr -= length;
+               System.arraycopy(
+                       expressionStack, 
+                       expressionPtr + 1, 
+                       messageSend.arguments = new Expression[length], 
+                       0, 
+                       length); 
+       };
+       assistNode = messageSend;
+       if (!diet){
+               this.restartRecovery    = true; // force to restart in recovery mode
+               this.lastIgnoredToken = -1;     
+       }
+       
+       this.isOrphanCompletionNode = true;
+       return messageSend;
+}
+public CompilationUnitDeclaration parse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int selectionStart, int selectionEnd) {
+
+       this.selectionStart = selectionStart;
+       this.selectionEnd = selectionEnd;       
+       SelectionScanner selectionScanner = (SelectionScanner)this.scanner;
+       selectionScanner.selectionIdentifier = null;
+       selectionScanner.selectionStart = selectionStart;
+       selectionScanner.selectionEnd = selectionEnd;   
+       return this.parse(sourceUnit, compilationResult);
+}
+/*
+ * Reset context so as to resume to regular parse loop
+ * If unable to reset for resuming, answers false.
+ *
+ * Move checkpoint location, reset internal stacks and
+ * decide which grammar goal is activated.
+ */
+protected boolean resumeAfterRecovery() {
+
+       /* if reached assist node inside method body, but still inside nested type,
+               should continue in diet mode until the end of the method body */
+       if (this.assistNode != null
+               && !(referenceContext instanceof CompilationUnitDeclaration)){
+               currentElement.preserveEnclosingBlocks();
+               if (currentElement.enclosingType() == null){
+                       this.resetStacks();
+                       return false;
+               }
+       }
+       return super.resumeAfterRecovery();                     
+}
+
+public void selectionIdentifierCheck(){
+       if (checkRecoveredType()) return;
+}
+public void setAssistIdentifier(char[] assistIdent){
+       ((SelectionScanner)scanner).selectionIdentifier = assistIdent;
+}
+/*
+ * Update recovery state based on current parser/scanner state
+ */
+protected void updateRecoveryState() {
+
+       /* expose parser state to recovery state */
+       currentElement.updateFromParserState();
+
+       /* may be able to retrieve completionNode as an orphan, and then attach it */
+       this.selectionIdentifierCheck();
+       this.attachOrphanCompletionNode();
+       
+       /* check and update recovered state based on current token,
+               this action is also performed when shifting token after recovery
+               got activated once. 
+       */
+       this.recoveryTokenCheck();
+}
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionScanner.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/codeassist/select/SelectionScanner.java
new file mode 100644 (file)
index 0000000..fafb5e7
--- /dev/null
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.codeassist.select;
+
+/*
+ * Scanner aware of a selection range. If finding an identifier which source range is exactly
+ * the same, then will record it so that the parser can make use of it.
+ *
+ * Source positions are zero-based and inclusive.
+ */
+import net.sourceforge.phpdt.core.compiler.InvalidInputException;
+import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
+
+public class SelectionScanner extends Scanner {
+
+       public char[] selectionIdentifier;
+       public int selectionStart, selectionEnd;
+/* 
+ * Truncate the current identifier if it is containing the cursor location. Since completion is performed
+ * on an identifier prefix.
+ *
+ */
+public SelectionScanner(boolean assertMode) {
+       super(false, false, false, assertMode);
+}
+
+public char[] getCurrentIdentifierSource() {
+
+       if (selectionIdentifier == null){
+               if (selectionStart == startPosition && selectionEnd == currentPosition-1){
+                       if (withoutUnicodePtr != 0){                    // check unicode scenario
+                               System.arraycopy(withoutUnicodeBuffer, 1, selectionIdentifier = new char[withoutUnicodePtr], 0, withoutUnicodePtr);
+                       } else {
+                               int length = currentPosition - startPosition;
+                               // no char[] sharing around completionIdentifier, we want it to be unique so as to use identity checks  
+                               System.arraycopy(source, startPosition, (selectionIdentifier = new char[length]), 0, length);
+                       }
+                       return selectionIdentifier;
+               }
+       }
+       return super.getCurrentIdentifierSource();
+}
+/*
+ * In case we actually read a keyword which corresponds to the selected
+ * range, we pretend we read an identifier.
+ */
+public int scanIdentifierOrKeyword() throws InvalidInputException {
+
+       int id = super.scanIdentifierOrKeyword();
+
+       // convert completed keyword into an identifier
+       if (id != TokenNameIdentifier
+               && startPosition == selectionStart 
+               && currentPosition == selectionEnd+1){
+               return TokenNameIdentifier;
+       }
+       return id;
+}
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/BasicCompilationUnit.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/BasicCompilationUnit.java
new file mode 100644 (file)
index 0000000..cbc4cbb
--- /dev/null
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.core;
+
+import java.io.File;
+import java.io.IOException;
+
+import net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit;
+import net.sourceforge.phpdt.internal.compiler.util.Util;
+
+/**
+ * A basic implementation of <code>ICompilationUnit</code>
+ * for use in the <code>SourceMapper</code>.
+ * @see ICompilationUnit
+ */
+public class BasicCompilationUnit implements ICompilationUnit {
+       protected char[] contents;
+       protected char[] fileName;
+       protected char[][] packageName;
+       protected char[] mainTypeName;
+       protected String encoding;
+       
+public BasicCompilationUnit(char[] contents, char[][] packageName, String fileName, String encoding) {
+       this.contents = contents;
+       this.fileName = fileName.toCharArray();
+       this.packageName = packageName;
+
+       int start = fileName.lastIndexOf("/") + 1; //$NON-NLS-1$
+       if (start == 0 || start < fileName.lastIndexOf("\\")) //$NON-NLS-1$
+               start = fileName.lastIndexOf("\\") + 1; //$NON-NLS-1$
+
+       int end = fileName.lastIndexOf("."); //$NON-NLS-1$
+       if (end == -1)
+               end = fileName.length();
+
+       this.mainTypeName = fileName.substring(start, end).toCharArray();
+       this.encoding = encoding;
+}
+public char[] getContents() {
+       if (this.contents != null)
+               return this.contents;   // answer the cached source
+
+       // otherwise retrieve it
+       try {
+               return Util.getFileCharContent(new File(new String(fileName)), this.encoding);
+       } catch (IOException e) {
+       }
+       return new char[0];
+}
+public char[] getFileName() {
+       return this.fileName;
+}
+public char[] getMainTypeName() {
+       return this.mainTypeName;
+}
+public char[][] getPackageName() {
+       return this.packageName;
+}
+public String toString(){
+       return "CompilationUnit: "+new String(fileName); //$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 (file)
index 0000000..ef69dd2
--- /dev/null
@@ -0,0 +1,128 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     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 <code>true</code> 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 (file)
index 0000000..3945211
--- /dev/null
@@ -0,0 +1,327 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.core;
+
+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;
+
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.IJavaModelStatus;
+import net.sourceforge.phpdt.core.IJavaModelStatusConstants;
+//import net.sourceforge.phpdt.core.IPackageFragment;
+//import net.sourceforge.phpdt.core.JavaCore;
+
+/**
+ * @see IJavaModelStatus
+ */
+
+public class JavaModelStatus extends Status implements IJavaModelStatus, IJavaModelStatusConstants, IResourceStatus {
+
+       /**
+        * The elements related to the failure, or <code>null</code>
+        * if no elements are involved.
+        */
+       protected IJavaElement[] fElements = new IJavaElement[0];
+       /**
+        * The path related to the failure, or <code>null</code>
+        * if no path is involved.
+        */
+       protected IPath fPath;
+       /**
+        * The <code>String</code> related to the failure, or <code>null</code>
+        * if no <code>String</code> is involved.
+        */
+       protected String fString;
+       /**
+        * Empty children
+        */
+       protected final static IStatus[] fgEmptyChildren = new IStatus[] {};
+       protected IStatus[] fChildren= fgEmptyChildren;
+
+       /**
+        * Singleton OK object
+        */
+       public static final IJavaModelStatus VERIFIED_OK = new JavaModelStatus(OK);
+
+       /**
+        * Constructs an Java model status with no corresponding elements.
+        */
+       public JavaModelStatus() {
+               // no code for an multi-status
+               super(ERROR, PHPeclipsePlugin.PLUGIN_ID, 0, "JavaModelStatus", null); //$NON-NLS-1$
+       }
+       /**
+        * Constructs an Java model status with no corresponding elements.
+        */
+       public JavaModelStatus(int code) {
+               super(ERROR, PHPeclipsePlugin.PLUGIN_ID, code, "JavaModelStatus", null); //$NON-NLS-1$
+               fElements= JavaElementInfo.fgEmptyChildren;
+       }
+//     /**
+//      * Constructs an Java model status with the given corresponding
+//      * elements.
+//      */
+//     public JavaModelStatus(int code, IJavaElement[] elements) {
+//             super(ERROR, JavaCore.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) {
+//             super(ERROR, JavaCore.PLUGIN_ID, code, "JavaModelStatus", null); //$NON-NLS-1$
+//             fElements= JavaElementInfo.fgEmptyChildren;
+//             fPath= null;
+//             fString = string;
+//     }
+//     /**
+//      * Constructs an Java model status with no corresponding elements.
+//      */
+       public JavaModelStatus(int code, Throwable throwable) {
+               super(ERROR, PHPeclipsePlugin.PLUGIN_ID, code, "JavaModelStatus", throwable); //$NON-NLS-1$
+               fElements= JavaElementInfo.fgEmptyChildren;
+       }
+//     /**
+//      * Constructs an Java model status with no corresponding elements.
+//      */
+//     public JavaModelStatus(int code, IPath path) {
+//             super(ERROR, JavaCore.PLUGIN_ID, code, "JavaModelStatus", null); //$NON-NLS-1$
+//             fElements= JavaElementInfo.fgEmptyChildren;
+//             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 no corresponding elements.
+        */
+       public JavaModelStatus(CoreException coreException) {
+               super(ERROR, PHPeclipsePlugin.PLUGIN_ID, CORE_EXCEPTION, "JavaModelStatus", coreException); //$NON-NLS-1$
+               fElements= JavaElementInfo.fgEmptyChildren;
+       }
+       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() {
+//             if (getException() == 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",fElements[0].getElementName()); //$NON-NLS-1$
+//                             case EVALUATION_ERROR:
+//                                     return Util.bind("status.evaluationError", getString()); //$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", fElements[0].getElementName()); //$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(fElements[0].getElementName());
+//                                     }
+//                                     return buff.toString();
+//                             case INVALID_NAME:
+//                                     return Util.bind("status.invalidName", getString()); //$NON-NLS-1$
+//                             case INVALID_PACKAGE:
+//                                     return Util.bind("status.invalidPackage", getString()); //$NON-NLS-1$
+//                             case INVALID_PATH:
+//                                     return Util.bind("status.invalidPath", getPath() == null ? "null" : getPath().toString()); //$NON-NLS-1$ //$NON-NLS-2$
+//                             case INVALID_PROJECT:
+//                                     return Util.bind("status.invalidProject", getString()); //$NON-NLS-1$
+//                             case INVALID_RESOURCE:
+//                                     return Util.bind("status.invalidResource", getString()); //$NON-NLS-1$
+//                             case INVALID_RESOURCE_TYPE:
+//                                     return Util.bind("status.invalidResourceType", getString()); //$NON-NLS-1$
+//                             case INVALID_SIBLING:
+//                                     return Util.bind("status.invalidSibling", fElements[0].getElementName()); //$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$
+//                                             }
+//                                     }
+//                                     return Util.bind("status.nameCollision"); //$NON-NLS-1$
+//                             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", getString(), fElements[0].getElementName()); //$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$
+//                     }
+//                     return getString();
+//             } else {
+//                     return getException().getMessage();
+//             }
+//     }
+       /**
+        * @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()
+        */
+       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 <code>IJavaModelStatus</code> 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/TypeConverter.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/TypeConverter.java
new file mode 100644 (file)
index 0000000..dc7ef2a
--- /dev/null
@@ -0,0 +1,245 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.core;
+
+import net.sourceforge.phpdt.core.IField;
+import net.sourceforge.phpdt.core.IMethod;
+import net.sourceforge.phpdt.core.IType;
+import net.sourceforge.phpdt.core.JavaModelException;
+import net.sourceforge.phpdt.core.Signature;
+import net.sourceforge.phpdt.internal.compiler.CompilationResult;
+import net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.Argument;
+import net.sourceforge.phpdt.internal.compiler.ast.ArrayQualifiedTypeReference;
+import net.sourceforge.phpdt.internal.compiler.ast.ArrayTypeReference;
+import net.sourceforge.phpdt.internal.compiler.ast.CompilationUnitDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.ConstructorDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.ImportReference;
+import net.sourceforge.phpdt.internal.compiler.ast.MemberTypeDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.MethodDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.QualifiedTypeReference;
+import net.sourceforge.phpdt.internal.compiler.ast.SingleTypeReference;
+import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.TypeReference;
+import net.sourceforge.phpdt.internal.compiler.lookup.CompilerModifiers;
+import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
+import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
+
+/**
+ * Converter from a type to an AST type declaration.
+ */
+public class TypeConverter {
+       
+       /**
+        * Convert a type into an AST type declaration and put it in the given compilation unit.
+        */
+//     public static TypeDeclaration buildTypeDeclaration(IType type, CompilationUnitDeclaration compilationUnit, CompilationResult compilationResult, ProblemReporter problemReporter)  throws JavaModelException {
+//             char[] packageName = type.getPackageFragment().getElementName().toCharArray();
+//             
+//             if (packageName != null && packageName.length > 0) { 
+//                     compilationUnit.currentPackage = new ImportReference(CharOperation.splitOn('.', packageName), new long[]{0}, false);
+//             }
+//     
+//             /* convert type */
+//             TypeDeclaration typeDeclaration = convert(type, null, null, compilationResult);
+//             
+//             IType alreadyComputedMember = type;
+//             IType parent = type.getDeclaringType();
+//             TypeDeclaration previousDeclaration = typeDeclaration;
+//             while(parent != null) {
+//                     TypeDeclaration declaration = convert(parent, alreadyComputedMember, (MemberTypeDeclaration)previousDeclaration, compilationResult);
+//                     
+//                     alreadyComputedMember = parent;
+//                     previousDeclaration = declaration;
+//                     parent = parent.getDeclaringType();
+//             }
+//             
+//             compilationUnit.types = new TypeDeclaration[]{previousDeclaration};
+//
+//             return typeDeclaration;
+//     }
+       
+       private static FieldDeclaration convert(IField field, IType type) throws JavaModelException {
+
+               FieldDeclaration fieldDeclaration = new FieldDeclaration();
+
+               fieldDeclaration.name = field.getElementName().toCharArray();
+               fieldDeclaration.type = createTypeReference(Signature.toString(field.getTypeSignature()).toCharArray(), type);
+               fieldDeclaration.modifiers = field.getFlags();
+
+               return fieldDeclaration;
+       }
+       
+       private static AbstractMethodDeclaration convert(IMethod method, IType type, CompilationResult compilationResult) throws JavaModelException {
+
+               AbstractMethodDeclaration methodDeclaration;
+
+               if (method.isConstructor()) {
+                       ConstructorDeclaration decl = new ConstructorDeclaration(compilationResult);
+                       decl.isDefaultConstructor = false;
+                       methodDeclaration = decl;
+               } else {
+                       MethodDeclaration decl = new MethodDeclaration(compilationResult);
+                       /* convert return type */
+                       decl.returnType = createTypeReference(Signature.toString(method.getReturnType()).toCharArray(), type);
+                       methodDeclaration = decl;
+               }
+               methodDeclaration.selector = method.getElementName().toCharArray();
+               methodDeclaration.modifiers = method.getFlags();
+
+               /* convert arguments */
+               String[] argumentTypeNames = method.getParameterTypes();
+               String[] argumentNames = method.getParameterNames();
+               int argumentCount = argumentTypeNames == null ? 0 : argumentTypeNames.length;
+               methodDeclaration.arguments = new Argument[argumentCount];
+               for (int i = 0; i < argumentCount; i++) {
+                       methodDeclaration.arguments[i] = new Argument(
+                               argumentNames[i].toCharArray(),
+                               0,
+                               createTypeReference(Signature.toString(argumentTypeNames[i]).toCharArray(), type),
+                               CompilerModifiers.AccDefault);
+                       // do not care whether was final or not
+               }
+
+               /* convert thrown exceptions */
+               String[] exceptionTypeNames = method.getExceptionTypes();
+               int exceptionCount = exceptionTypeNames == null ? 0 : exceptionTypeNames.length;
+               if(exceptionCount > 0) {
+                       methodDeclaration.thrownExceptions = new TypeReference[exceptionCount];
+                       for (int i = 0; i < exceptionCount; i++) {
+                               methodDeclaration.thrownExceptions[i] =
+                                       createTypeReference(Signature.toString(exceptionTypeNames[i]).toCharArray(), type);
+                       }
+               }
+               return methodDeclaration;
+       }
+       
+       private static TypeDeclaration convert(IType type, IType alreadyComputedMember,MemberTypeDeclaration alreadyComputedMemberDeclaration, CompilationResult compilationResult) throws JavaModelException {
+               /* create type declaration - can be member type */
+               TypeDeclaration typeDeclaration;
+               if (type.getDeclaringType() == null) {
+                       typeDeclaration = new TypeDeclaration(compilationResult);
+               } else {
+                       typeDeclaration = new MemberTypeDeclaration(compilationResult);
+               }
+               typeDeclaration.name = type.getElementName().toCharArray();
+               typeDeclaration.modifiers = type.getFlags();
+
+
+               /* set superclass and superinterfaces */
+               if (type.getSuperclassName() != null) {
+                       typeDeclaration.superclass = createTypeReference(type.getSuperclassName().toCharArray(), type);
+               }
+               String[] interfaceNames = type.getSuperInterfaceNames();
+               int interfaceCount = interfaceNames == null ? 0 : interfaceNames.length;
+               typeDeclaration.superInterfaces = new TypeReference[interfaceCount];
+               for (int i = 0; i < interfaceCount; i++) {
+                       typeDeclaration.superInterfaces[i] = createTypeReference(interfaceNames[i].toCharArray(), type);
+               }
+               
+               /* convert member types */
+               IType[] memberTypes = type.getTypes();
+               int memberTypeCount =   memberTypes == null ? 0 : memberTypes.length;
+               typeDeclaration.memberTypes = new MemberTypeDeclaration[memberTypeCount];
+               for (int i = 0; i < memberTypeCount; i++) {
+                       if(alreadyComputedMember != null && alreadyComputedMember.getFullyQualifiedName().equals(memberTypes[i].getFullyQualifiedName())) {
+                               typeDeclaration.memberTypes[i] = alreadyComputedMemberDeclaration;
+                       } else {
+                               typeDeclaration.memberTypes[i] =
+                                       (MemberTypeDeclaration) convert(memberTypes[i], null, null, compilationResult);
+                       }
+               }
+
+               /* convert fields */
+               IField[] fields = type.getFields();
+               int fieldCount = fields == null ? 0 : fields.length;
+               typeDeclaration.fields = new FieldDeclaration[fieldCount];
+               for (int i = 0; i < fieldCount; i++) {
+                       typeDeclaration.fields[i] = convert(fields[i], type);
+               }
+
+               /* convert methods - need to add default constructor if necessary */
+               IMethod[] methods = type.getMethods();
+               int methodCount = methods == null ? 0 : methods.length;
+
+               /* source type has a constructor ?           */
+               /* by default, we assume that one is needed. */
+               int neededCount = 1;
+               for (int i = 0; i < methodCount; i++) {
+                       if (methods[i].isConstructor()) {
+                               neededCount = 0;
+                               // Does not need the extra constructor since one constructor already exists.
+                               break;
+                       }
+               }
+               typeDeclaration.methods = new AbstractMethodDeclaration[methodCount + neededCount];
+               if (neededCount != 0) { // add default constructor in first position
+                       typeDeclaration.methods[0] = typeDeclaration.createsInternalConstructor(false, false);
+               }
+               boolean isInterface = type.isInterface();
+               for (int i = 0; i < methodCount; i++) {
+                       AbstractMethodDeclaration method =convert(methods[i], type, compilationResult);
+                       if (isInterface || method.isAbstract()) { // fix-up flag 
+                               method.modifiers |= CompilerModifiers.AccSemicolonBody;
+                       }
+                       typeDeclaration.methods[neededCount + i] = method;
+               }
+               return typeDeclaration;
+       }
+       
+       private static TypeReference createTypeReference(char[] type, IType contextType) {
+               try {
+                       String[][] resolvedName = contextType.resolveType(new String(type));
+                       char[] superClassName = null;
+                       if(resolvedName != null && resolvedName.length == 1) {
+                               type= CharOperation.concat(resolvedName[0][0].toCharArray(), resolvedName[0][1].toCharArray(), '.');
+                       }
+               } catch (JavaModelException e) {
+                       
+               }
+               
+               /* count identifiers and dimensions */
+               int max = type.length;
+               int dimStart = max;
+               int dim = 0;
+               int identCount = 1;
+               for (int i = 0; i < max; i++) {
+                       switch (type[i]) {
+                               case '[' :
+                                       if (dim == 0)
+                                               dimStart = i;
+                                       dim++;
+                                       break;
+                               case '.' :
+                                       identCount++;
+                                       break;
+                       }
+               }
+               /* rebuild identifiers and dimensions */
+               if (identCount == 1) { // simple type reference
+                       if (dim == 0) {
+                               return new SingleTypeReference(type, 0);
+                       } else {
+                               char[] identifier = new char[dimStart];
+                               System.arraycopy(type, 0, identifier, 0, dimStart);
+                               return new ArrayTypeReference(identifier, dim, 0);
+                       }
+               } else { // qualified type reference
+                       char[][] identifiers =  CharOperation.splitOn('.', type, 0, dimStart - 1);
+                       if (dim == 0) {
+                               return new QualifiedTypeReference(identifiers, new long[]{0});
+                       } else {
+                               return new ArrayQualifiedTypeReference(identifiers, dim, new long[]{0});
+                       }
+               }
+       }
+}