New compiler level v_785_R33x
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/BindingKey.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/BindingKey.java
index 2196a29..c3234b5 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/BindingKey.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/BindingKey.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005 IBM Corporation and others.
+ * Copyright (c) 2005, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -67,8 +67,13 @@
* For example:
* <pre>
* <code>
- * createParameterizedTypeBindingKey("Ljava/util/Map<TK;TV;>;", new String[] {"Ljava/lang/String;", "Ljava/lang/Object;"}) -> "Ljava/util/Map<Ljava/lang/String;Ljava/lang/Object;>;"
- * createParameterizedTypeBindingKey("Ljava/util/List<TE;>;", new String[] {}) -> "Ljava/util/List<>;"
+ * createParameterizedTypeBindingKey(
+ * "Ljava/util/Map<TK;TV;>;",
+ * new String[] {"Ljava/lang/String;", "Ljava/lang/Object;"}) ->
+ * "Ljava/util/Map<Ljava/lang/String;Ljava/lang/Object;>;"
+ * createParameterizedTypeBindingKey(
+ * "Ljava/util/List<TE;>;", new String[] {}) ->
+ * "Ljava/util/List<>;"
* </code>
* </pre>
* </p>
@@ -121,8 +126,10 @@
* For example:
* <pre>
* <code>
- * createTypeVariableBindingKey("T", "Ljava/util/List<TE;>;") -> "Ljava/util/List<TE;>;:TT;"
- * createTypeVariableBindingKey("SomeTypeVariable", "Lp/X;.foo()V") -> "Lp/X;.foo()V:TSomeTypeVariable;"
+ * createTypeVariableBindingKey("T", "Ljava/util/List<TE;>;") ->
+ * "Ljava/util/List<TE;>;:TT;"
+ * createTypeVariableBindingKey("SomeTypeVariable", "Lp/X;.foo()V") ->
+ * "Lp/X;.foo()V:TSomeTypeVariable;"
* </code>
* </pre>
* </p>
@@ -150,9 +157,11 @@
* For example:
* <pre>
* <code>
- * createWilcardTypeBindingKey(null, Signature.C_STAR) -> "*"
- * createWilcardTypeBindingKey("Ljava/util/List<TE;>;", Signature.C_SUPER) -> "-Ljava/util/List<TE;>;"
- * createWilcardTypeBindingKey("Ljava/util/ArrayList;", Signature.C_EXTENDS) -> "+Ljava/util/ArrayList;"
+ * createWilcardTypeBindingKey(null, Signature.C_STAR) -> "*"
+ * createWilcardTypeBindingKey("Ljava/util/List<TE;>;",
+ * Signature.C_SUPER) -> "-Ljava/util/List<TE;>;"
+ * createWilcardTypeBindingKey("Ljava/util/ArrayList;", Signature.C_EXTENDS) ->
+ * "+Ljava/util/ArrayList;"
* </code>
* </pre>
* </p>
@@ -173,7 +182,21 @@
}
return null;
}
-
+
+ /**
+ * Returns the thrown exception signatures of the element represented by this binding key.
+ * If this binding key does not represent a method or does not throw any exception,
+ * returns an empty array.
+ *
+ * @return the thrown exceptions signatures
+ * @since 3.3
+ */
+ public String[] getThrownExceptions() {
+ KeyToSignature keyToSignature = new KeyToSignature(this.key, KeyToSignature.THROWN_EXCEPTIONS);
+ keyToSignature.parse();
+ return keyToSignature.getThrownExceptions();
+ }
+
/**
* Returns the type argument signatures of the element represented by this binding key.
* If this binding key doesn't represent a parameterized type or a parameterized method,
@@ -221,15 +244,15 @@
}
/**
- * Internal method.
- * <p>
- * This method transforms this binding key into a signature.
- * This method is not intended to be called by clients.
- * </p>
+ * Transforms this binding key into a resolved signature.
+ * If this binding key represents a field, the returned signature is
+ * the declaring type's signature.
*
- * @return the signature for this binding key
+ * @return the resolved signature for this binding key
+ * @see Signature
+ * @since 3.2
*/
- public String internalToSignature() {
+ public String toSignature() {
KeyToSignature keyToSignature = new KeyToSignature(this.key, KeyToSignature.SIGNATURE);
keyToSignature.parse();
return keyToSignature.signature.toString();
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/BufferChangedEvent.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/BufferChangedEvent.java
index b03507c..2b09ad9 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/BufferChangedEvent.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/BufferChangedEvent.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ClasspathContainerInitializer.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ClasspathContainerInitializer.java
index 578a8a2..a1c437b 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ClasspathContainerInitializer.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ClasspathContainerInitializer.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -17,8 +17,8 @@
*******************************************************************************/
package org.eclipse.jdt.core;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.*;
+import org.eclipse.jdt.internal.core.JavaModelStatus;
/**
* Abstract base implementation of all classpath container initializer.
@@ -27,22 +27,44 @@
* <p>
* Clients should subclass this class to implement a specific classpath
* container initializer. The subclass must have a public 0-argument
- * constructor and a concrete implementation of <code>initialize</code>.
+ * constructor and a concrete implementation of {@link #initialize(IPath, IJavaProject)}.
* <p>
* Multiple classpath containers can be registered, each of them declares
* the container ID they can handle, so as to narrow the set of containers they
- * can resolve, in other words, a container initializer is guaranteed to only be
+ * can resolve, in other words, a container initializer is guaranteed to only be
* activated to resolve containers which match the ID they registered onto.
* <p>
* In case multiple container initializers collide on the same container ID, the first
* registered one will be invoked.
- *
+ *
* @see IClasspathEntry
* @see IClasspathContainer
* @since 2.0
*/
public abstract class ClasspathContainerInitializer {
-
+
+ /**
+ * Status code indicating that an attribute is not supported.
+ *
+ * @see #getAccessRulesStatus(IPath, IJavaProject)
+ * @see #getAttributeStatus(IPath, IJavaProject, String)
+ * @see #getSourceAttachmentStatus(IPath, IJavaProject)
+ *
+ * @since 3.3
+ */
+ public static final int ATTRIBUTE_NOT_SUPPORTED = 1;
+
+ /**
+ * Status code indicating that an attribute is not modifiable.
+ *
+ * @see #getAccessRulesStatus(IPath, IJavaProject)
+ * @see #getAttributeStatus(IPath, IJavaProject, String)
+ * @see #getSourceAttachmentStatus(IPath, IJavaProject)
+ *
+ * @since 3.3
+ */
+ public static final int ATTRIBUTE_READ_ONLY = 2;
+
/**
* Creates a new classpath container initializer.
*/
@@ -59,7 +81,7 @@
* the second segment can be used as an additional hint when performing the resolution.
* <p>
* The initializer is invoked if a container path needs to be resolved for a given project, and no
- * value for it was recorded so far. The implementation of the initializer would typically set the
+ * value for it was recorded so far. The implementation of the initializer would typically set the
* corresponding container using <code>JavaCore#setClasspathContainer</code>.
* <p>
* A container initialization can be indirectly performed while attempting to resolve a project
@@ -69,10 +91,10 @@
* infinite regression of initializations.
* <p>
* A container initialization may also occur indirectly when setting a project classpath, as the operation
- * needs to resolve the classpath for validation purpose. While the operation is in progress, a referenced
- * container initializer may be invoked. If the initializer further tries to access the referring project classpath,
- * it will not see the new assigned classpath until the operation has completed. Note that once the Java
- * change notification occurs (at the end of the operation), the model has been updated, and the project
+ * needs to resolve the classpath for validation purpose. While the operation is in progress, a referenced
+ * container initializer may be invoked. If the initializer further tries to access the referring project classpath,
+ * it will not see the new assigned classpath until the operation has completed. Note that once the Java
+ * change notification occurs (at the end of the operation), the model has been updated, and the project
* classpath can be queried normally.
* <p>
* This method is called by the Java model to give the party that defined
@@ -96,23 +118,23 @@
* </ul>
* The effects of using other Java model APIs are unspecified.
* </p>
- *
- * @param containerPath a two-segment path (ID/hint) identifying the container that needs
+ *
+ * @param containerPath a two-segment path (ID/hint) identifying the container that needs
* to be resolved
* @param project the Java project in which context the container is to be resolved.
* This allows generic containers to be bound with project specific values.
* @throws CoreException if an exception occurs during the initialization
- *
+ *
* @see JavaCore#getClasspathContainer(IPath, IJavaProject)
* @see JavaCore#setClasspathContainer(IPath, IJavaProject[], IClasspathContainer[], org.eclipse.core.runtime.IProgressMonitor)
* @see IClasspathContainer
*/
public abstract void initialize(IPath containerPath, IJavaProject project) throws CoreException;
-
+
/**
- * Returns <code>true</code> if this container initializer can be requested to perform updates
+ * Returns <code>true</code> if this container initializer can be requested to perform updates
* on its own container values. If so, then an update request will be performed using
- * <code>ClasspathContainerInitializer#requestClasspathContainerUpdate</code>/
+ * {@link #requestClasspathContainerUpdate(IPath, IJavaProject, IClasspathContainer)}.
* <p>
* @param containerPath the path of the container which requires to be updated
* @param project the project for which the container is to be updated
@@ -120,24 +142,24 @@
* @since 2.1
*/
public boolean canUpdateClasspathContainer(IPath containerPath, IJavaProject project) {
-
+
// By default, classpath container initializers do not accept updating containers
- return false;
+ return false;
}
/**
- * Request a registered container definition to be updated according to a container suggestion. The container suggestion
- * only acts as a place-holder to pass along the information to update the matching container definition(s) held by the
- * container initializer. In particular, it is not expected to store the container suggestion as is, but rather adjust
+ * Request a registered container definition to be updated according to a container suggestion. The container suggestion
+ * only acts as a place-holder to pass along the information to update the matching container definition(s) held by the
+ * container initializer. In particular, it is not expected to store the container suggestion as is, but rather adjust
* the actual container definition based on suggested changes.
* <p>
* IMPORTANT: In reaction to receiving an update request, a container initializer will update the corresponding
- * container definition (after reconciling changes) at its earliest convenience, using
- * <code>JavaCore#setClasspathContainer(IPath, IJavaProject[], IClasspathContainer[], IProgressMonitor)</code>.
+ * container definition (after reconciling changes) at its earliest convenience, using
+ * {@link JavaCore#setClasspathContainer(IPath, IJavaProject[], IClasspathContainer[], IProgressMonitor)}.
* Until it does so, the update will not be reflected in the Java Model.
* <p>
* In order to anticipate whether the container initializer allows to update its containers, the predicate
- * <code>JavaCore#canUpdateClasspathContainer</code> should be used.
+ * {@link #canUpdateClasspathContainer(IPath, IJavaProject)} should be used.
* <p>
* @param containerPath the path of the container which requires to be updated
* @param project the project for which the container is to be updated
@@ -147,6 +169,7 @@
* @see ClasspathContainerInitializer#canUpdateClasspathContainer(IPath, IJavaProject)
* @since 2.1
*/
+
public void requestClasspathContainerUpdate(IPath containerPath, IJavaProject project, IClasspathContainer containerSuggestion) throws CoreException {
// By default, classpath container initializers do not accept updating containers
@@ -155,26 +178,64 @@
/**
* Returns a readable description for a container path. A readable description for a container path can be
* used for improving the display of references to container, without actually needing to resolve them.
- * A good implementation should answer a description consistent with the description of the associated
- * target container (see <code>IClasspathContainer.getDescription()</code>).
- *
+ * A good implementation should answer a description consistent with the description of the associated
+ * target container (see {@link IClasspathContainer#getDescription()}).
+ *
* @param containerPath the path of the container which requires a readable description
* @param project the project from which the container is referenced
* @return a string description of the container
* @since 2.1
- */
+ */
public String getDescription(IPath containerPath, IJavaProject project) {
-
+
// By default, a container path is the only available description
return containerPath.makeRelative().toString();
}
+ /**
+ * Returns a classpath container that is used after this initializer failed to bind a classpath container
+ * to a {@link IClasspathContainer} for the given project. A non-<code>null</code>
+ * failure container indicates that there will be no more request to initialize the given container
+ * for the given project.
+ * <p>
+ * By default a non-<code>null</code> failure container with no classpath entries is returned.
+ * Clients wishing to get a chance to run the initializer again should override this method
+ * and return <code>null</code>.
+ * </p>
+ *
+ * @param containerPath the path of the container which failed to initialize
+ * @param project the project from which the container is referenced
+ * @return the default failure container, or <code>null</code> if wishing to run the initializer again
+ * @since 3.3
+ */
+ public IClasspathContainer getFailureContainer(final IPath containerPath, IJavaProject project) {
+ final String description = getDescription(containerPath, project);
+ return
+ new IClasspathContainer() {
+ public IClasspathEntry[] getClasspathEntries() {
+ return new IClasspathEntry[0];
+ }
+ public String getDescription() {
+ return description;
+ }
+ public int getKind() {
+ return 0;
+ }
+ public IPath getPath() {
+ return containerPath;
+ }
+ public String toString() {
+ return getDescription();
+ }
+ };
+ }
+
/**
* Returns an object which identifies a container for comparison purpose. This allows
- * to eliminate redundant containers when accumulating classpath entries (e.g.
+ * to eliminate redundant containers when accumulating classpath entries (e.g.
* runtime classpath computation). When requesting a container comparison ID, one
* should ensure using its corresponding container initializer. Indeed, a random container
- * initializer cannot be held responsible for determining comparison IDs for arbitrary
+ * initializer cannot be held responsible for determining comparison IDs for arbitrary
* containers.
* <p>
* @param containerPath the path of the container which is being checked
@@ -192,5 +253,115 @@
return containerPath.segment(0);
}
}
+
+ /**
+ * Returns the access rules attribute status according to this initializer.
+ * <p>
+ * The returned {@link IStatus status} can have one of the following severities:
+ * <ul>
+ * <li>{@link IStatus#OK OK}: means that the attribute is supported
+ * <strong>and</strong> is modifiable</li>
+ * <li>{@link IStatus#ERROR ERROR}: means that either the attribute
+ * is not supported or is not modifiable.<br>
+ * In this case, the {@link IStatus#getCode() code}will have
+ * respectively the {@link #ATTRIBUTE_NOT_SUPPORTED} value
+ * or the {@link #ATTRIBUTE_READ_ONLY} value.</li>
+ * </ul>
+ * </p><p>
+ * The status message can contain more information.
+ * </p><p>
+ * If the subclass does not override this method, then the default behavior is
+ * to return {@link IStatus#OK OK} if and only if the classpath container can
+ * be updated (see {@link #canUpdateClasspathContainer(IPath, IJavaProject)}).
+ * </p>
+ *
+ * @param containerPath the path of the container which requires to be
+ * updated
+ * @param project the project for which the container is to be updated
+ * @return returns the access rules attribute status
+ *
+ * @since 3.3
+ */
+ public IStatus getAccessRulesStatus(IPath containerPath, IJavaProject project) {
+
+ if (canUpdateClasspathContainer(containerPath, project)) {
+ return Status.OK_STATUS;
+ }
+ return new JavaModelStatus(ATTRIBUTE_READ_ONLY);
+ }
+
+ /**
+ * Returns the extra attribute status according to this initializer.
+ * <p>
+ * The returned {@link IStatus status} can have one of the following severities:
+ * <ul>
+ * <li>{@link IStatus#OK OK}: means that the attribute is supported
+ * <strong>and</strong> is modifiable</li>
+ * <li>{@link IStatus#ERROR ERROR}: means that either the attribute
+ * is not supported or is not modifiable.<br>
+ * In this case, the {@link IStatus#getCode() code}will have
+ * respectively the {@link #ATTRIBUTE_NOT_SUPPORTED} value
+ * or the {@link #ATTRIBUTE_READ_ONLY} value.</li>
+ * </ul>
+ * </p><p>
+ * The status message can contain more information.
+ * </p><p>
+ * If the subclass does not override this method, then the default behavior is
+ * to return {@link IStatus#OK OK} if and only if the classpath container can
+ * be updated (see {@link #canUpdateClasspathContainer(IPath, IJavaProject)}).
+ * </p>
+ *
+ * @param containerPath the path of the container which requires to be
+ * updated
+ * @param project the project for which the container is to be updated
+ * @param attributeKey the key of the extra attribute
+ * @return returns the extra attribute status
+ * @see IClasspathAttribute
+ *
+ * @since 3.3
+ */
+ public IStatus getAttributeStatus(IPath containerPath, IJavaProject project, String attributeKey) {
+
+ if (canUpdateClasspathContainer(containerPath, project)) {
+ return Status.OK_STATUS;
+ }
+ return new JavaModelStatus(ATTRIBUTE_READ_ONLY);
+ }
+
+ /**
+ * Returns the source attachment attribute status according to this initializer.
+ * <p>
+ * The returned {@link IStatus status} can have one of the following severities:
+ * <ul>
+ * <li>{@link IStatus#OK OK}: means that the attribute is supported
+ * <strong>and</strong> is modifiable</li>
+ * <li>{@link IStatus#ERROR ERROR}: means that either the attribute
+ * is not supported or is not modifiable.<br>
+ * In this case, the {@link IStatus#getCode() code}will have
+ * respectively the {@link #ATTRIBUTE_NOT_SUPPORTED} value
+ * or the {@link #ATTRIBUTE_READ_ONLY} value.</li>
+ * </ul>
+ * </p><p>
+ * The status message can contain more information.
+ * </p><p>
+ * If the subclass does not override this method, then the default behavior is
+ * to return {@link IStatus#OK OK} if and only if the classpath container can
+ * be updated (see {@link #canUpdateClasspathContainer(IPath, IJavaProject)}).
+ * </p>
+ *
+ * @param containerPath the path of the container which requires to be
+ * updated
+ * @param project the project for which the container is to be updated
+ * @return returns the source attachment attribute status
+ *
+ * @since 3.3
+ */
+ public IStatus getSourceAttachmentStatus(IPath containerPath, IJavaProject project) {
+
+ if (canUpdateClasspathContainer(containerPath, project)) {
+ return Status.OK_STATUS;
+ }
+ return new JavaModelStatus(ATTRIBUTE_READ_ONLY);
+ }
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ClasspathVariableInitializer.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ClasspathVariableInitializer.java
index 49d21b4..f277284 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ClasspathVariableInitializer.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ClasspathVariableInitializer.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionContext.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionContext.java
index b853f87..e07e3cb 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionContext.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionContext.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005 IBM Corporation and others.
+ * Copyright (c) 2005, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -11,16 +11,79 @@
package org.eclipse.jdt.core;
import org.eclipse.jdt.internal.codeassist.InternalCompletionContext;
+import org.eclipse.jdt.internal.codeassist.complete.CompletionOnJavadoc;
/**
* Completion context.
*
* Represent the context in which the completion occurs.
+ * <p>
+ * This class is not intended to be instantiated or subclassed by clients.
+ * </p>
*
* @see CompletionRequestor#acceptContext(CompletionContext)
* @since 3.1
*/
public final class CompletionContext extends InternalCompletionContext {
+
+ /**
+ * The completion token is unknown.
+ * @since 3.2
+ */
+ public static final int TOKEN_KIND_UNKNOWN = 0;
+
+ /**
+ * The completion token is a name.
+ * @since 3.2
+ */
+ public static final int TOKEN_KIND_NAME = 1;
+ /**
+ * The completion token is a string literal.
+ * The string literal ends quote can be not present the source.
+ * <code>"foo"</code> or <code>"foo</code>.
+ * @since 3.2
+ */
+
+ public static final int TOKEN_KIND_STRING_LITERAL = 2;
+ /**
+ * Tell user whether completion takes place in a javadoc comment or not.
+ *
+ * @return boolean true if completion takes place in a javadoc comment, false otherwise.
+ * @since 3.2
+ */
+ public boolean isInJavadoc() {
+ return this.javadoc != 0;
+ }
+
+ /**
+ * Tell user whether completion takes place in text area of a javadoc comment or not.
+ *
+ * @return boolean true if completion takes place in a text area of a javadoc comment, false otherwise.
+ * @since 3.2
+ */
+ public boolean isInJavadocText() {
+ return (this.javadoc & CompletionOnJavadoc.TEXT) != 0;
+ }
+
+ /**
+ * Tell user whether completion takes place in a formal reference of a javadoc tag or not.
+ * Tags with formal reference are:
+ * <ul>
+ * <li>@see</li>
+ * <li>@throws</li>
+ * <li>@exception</li>
+ * <li>{@link Object}</li>
+ * <li>{@linkplain Object}</li>
+ * <li>{@value} when compiler compliance is set at leats to 1.5</li>
+ * </ul>
+ *
+ * @return boolean true if completion takes place in formal reference of a javadoc tag, false otherwise.
+ * @since 3.2
+ */
+ public boolean isInJavadocFormalReference() {
+ return (this.javadoc & CompletionOnJavadoc.FORMAL_REFERENCE) != 0;
+ }
+
/**
* Return signatures of expected types of a potential completion proposal at the completion position.
*
@@ -47,4 +110,137 @@
public char[][] getExpectedTypesKeys() {
return this.expectedTypesKeys;
}
+
+ /**
+ * Returns the completed token.
+ * This token is either the identifier or Java language keyword
+ * or the string literal under, immediately preceding,
+ * the original request offset. If the original request offset
+ * is not within or immediately after an identifier or keyword or
+ * a string literal then the returned value is <code>null</code>.
+ *
+ * @return completed token or <code>null</code>
+ * @since 3.2
+ */
+ public char[] getToken() {
+ return this.token;
+ }
+
+ /**
+ * Returns the kind of completion token being proposed.
+ * <p>
+ * The set of different kinds of completion token is
+ * expected to change over time. It is strongly recommended
+ * that clients do <b>not</b> assume that the kind is one of the
+ * ones they know about, and code defensively for the
+ * possibility of unexpected future growth.
+ * </p>
+ *
+ * @return the kind; one of the kind constants declared on
+ * this class whose name starts with <code>TOKEN_KIND</code>,
+ * or possibly a kind unknown to the caller
+ * @since 3.2
+ */
+ public int getTokenKind() {
+ return this.tokenKind;
+ }
+
+ /**
+ * Returns the character index of the start of the
+ * subrange in the source file buffer containing the
+ * relevant token being completed. This
+ * token is either the identifier or Java language keyword
+ * under, or immediately preceding, the original request
+ * offset. If the original request offset is not within
+ * or immediately after an identifier or keyword, then the
+ * position returned is original request offset and the
+ * token range is empty.
+ *
+ * @return character index of token start position (inclusive)
+ * @since 3.2
+ */
+ public int getTokenStart() {
+ return this.tokenStart;
+ }
+
+ /**
+ * Returns the character index of the end (exclusive) of the subrange
+ * in the source file buffer containing the
+ * relevant token. When there is no relevant token, the
+ * range is empty
+ * (<code>getTokenEnd() == getTokenStart() - 1</code>).
+ *
+ * @return character index of token end position (exclusive)
+ * @since 3.2
+ */
+ // TODO (david) https://bugs.eclipse.org/bugs/show_bug.cgi?id=132558
+ public int getTokenEnd() {
+ return this.tokenEnd;
+ }
+
+ /**
+ * Returns the offset position in the source file buffer
+ * after which code assist is requested.
+ *
+ * @return offset position in the source file buffer
+ * @since 3.2
+ */
+ public int getOffset() {
+ return this.offset;
+ }
+
+ public String toString() {
+ StringBuffer buffer = new StringBuffer();
+
+ buffer.append("completion offset="); //$NON-NLS-1$
+ buffer.append(this.offset);
+ buffer.append('\n');
+
+ buffer.append("completion range=["); //$NON-NLS-1$
+ buffer.append(this.tokenStart);
+ buffer.append(", "); //$NON-NLS-1$
+ buffer.append(this.tokenEnd);
+ buffer.append("]\n"); //$NON-NLS-1$
+
+ buffer.append("completion token="); //$NON-NLS-1$
+ String string = "null"; //$NON-NLS-1$
+ if(token == null) {
+ buffer.append(string);
+ } else {
+ buffer.append('\"');
+ buffer.append(this.token);
+ buffer.append('\"');
+ }
+ buffer.append('\n');
+
+ buffer.append("expectedTypesSignatures="); //$NON-NLS-1$
+ if(this.expectedTypesSignatures == null) {
+ buffer.append(string);
+ } else {
+ buffer.append('{');
+ for (int i = 0; i < this.expectedTypesSignatures.length; i++) {
+ if(i > 0) buffer.append(',');
+ buffer.append(this.expectedTypesSignatures[i]);
+
+ }
+ buffer.append('}');
+ }
+ buffer.append('\n');
+
+ buffer.append("expectedTypesKeys="); //$NON-NLS-1$
+ if(expectedTypesSignatures == null) {
+ buffer.append(string);
+ } else {
+ buffer.append('{');
+ for (int i = 0; i < this.expectedTypesKeys.length; i++) {
+ if(i > 0) buffer.append(',');
+ buffer.append(this.expectedTypesKeys[i]);
+
+ }
+ buffer.append('}');
+ }
+ buffer.append('\n');
+
+ return buffer.toString();
+ }
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionFlags.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionFlags.java
new file mode 100755
index 0000000..bda7c36
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionFlags.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core;
+
+/**
+ * Utility class for decoding additional flags in completion proposal.
+ * <p>
+ * This class provides static methods only; it is not intended to be
+ * instantiated or subclassed by clients.
+ * </p>
+ *
+ * @see CompletionProposal#getAdditionalFlags()
+ *
+ * @since 3.3
+ */
+public final class CompletionFlags {
+ /**
+ * Constant representing the absence of any flag
+ */
+ public static final int Default = 0x0000;
+
+ /**
+ * Constant representing a static import
+ */
+ public static final int StaticImport = 0x0001;
+
+ /**
+ * Not instantiable.
+ */
+ private CompletionFlags() {
+ // Not instantiable
+ }
+
+ /**
+ * Returns whether the given integer includes the {@link #StaticImport} flag.
+ *
+ * @param flags the flags
+ * @return <code>true</code> if the {@link #StaticImport} flag is included
+ */
+ public static boolean isStaticImport(int flags) {
+ return (flags & StaticImport) != 0;
+ }
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionProposal.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionProposal.java
index 74a3813..cf8d8bf 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionProposal.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionProposal.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * Copyright (c) 2004, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -43,8 +43,8 @@
* competing proposals.
* </p>
* <p>
- * The completion engine creates instances of this class; it is not
- * intended to be used by other clients.
+ * The completion engine creates instances of this class; it is not intended
+ * to be instantiated or subclassed by clients.
* </p>
*
* @see ICodeAssist#codeComplete(int, CompletionRequestor)
@@ -411,6 +411,319 @@
* @since 3.1
*/
public static final int ANNOTATION_ATTRIBUTE_REF = 13;
+
+ /**
+ * Completion is a link reference to a field in a javadoc text.
+ * This kind of completion might occur in a context like
+ * <code>" * blabla System.o^ blabla"</code> and complete it to
+ * <code>" * blabla {@link System#out } blabla"</code>.
+ * <p>
+ * The following additional context information is available
+ * for this kind of completion proposal at little extra cost:
+ * <ul>
+ * <li>{@link #getDeclarationSignature()} -
+ * the type signature of the type that declares the field that is referenced
+ * </li>
+ * <li>{@link #getFlags()} -
+ * the modifiers flags (including ACC_ENUM) of the field that is referenced
+ * </li>
+ * <li>{@link #getName()} -
+ * the simple name of the field that is referenced
+ * </li>
+ * <li>{@link #getSignature()} -
+ * the type signature of the field's type (as opposed to the
+ * signature of the type in which the referenced field
+ * is declared)
+ * </li>
+ * </ul>
+ * </p>
+ *
+ * @see #getKind()
+ * @since 3.2
+ */
+ public static final int JAVADOC_FIELD_REF = 14;
+
+ /**
+ * Completion is a link reference to a method in a javadoc text.
+ * This kind of completion might occur in a context like
+ * <code>" * blabla Runtime#get^ blabla"</code> and complete it to
+ * <code>" * blabla {@link Runtime#getRuntime() }"</code>.
+ * <p>
+ * The following additional context information is available
+ * for this kind of completion proposal at little extra cost:
+ * <ul>
+ * <li>{@link #getDeclarationSignature()} -
+ * the type signature of the type that declares the method that is referenced
+ * </li>
+ * <li>{@link #getFlags()} -
+ * the modifiers flags of the method that is referenced
+ * </li>
+ * <li>{@link #getName()} -
+ * the simple name of the method that is referenced
+ * </li>
+ * <li>{@link #getSignature()} -
+ * the method signature of the method that is referenced
+ * </li>
+ * </ul>
+ * </p>
+ *
+ * @see #getKind()
+ * @since 3.2
+ */
+ public static final int JAVADOC_METHOD_REF = 15;
+
+ /**
+ * Completion is a link reference to a type in a javadoc text.
+ * Any kind of type is allowed, including primitive types, reference types,
+ * array types, parameterized types, and type variables.
+ * This kind of completion might occur in a context like
+ * <code>" * blabla Str^ blabla"</code> and complete it to
+ * <code>" * blabla {@link String } blabla"</code>.
+ * <p>
+ * The following additional context information is available
+ * for this kind of completion proposal at little extra cost:
+ * <ul>
+ * <li>{@link #getDeclarationSignature()} -
+ * the dot-based package name of the package that contains
+ * the type that is referenced
+ * </li>
+ * <li>{@link #getSignature()} -
+ * the type signature of the type that is referenced
+ * </li>
+ * <li>{@link #getFlags()} -
+ * the modifiers flags (including Flags.AccInterface, AccEnum,
+ * and AccAnnotation) of the type that is referenced
+ * </li>
+ * </ul>
+ * </p>
+ *
+ * @see #getKind()
+ * @since 3.2
+ */
+ public static final int JAVADOC_TYPE_REF = 16;
+
+ /**
+ * Completion is a value reference to a static field in a javadoc text.
+ * This kind of completion might occur in a context like
+ * <code>" * blabla System.o^ blabla"</code> and complete it to
+ * <code>" * blabla {@value System#out } blabla"</code>.
+ * <p>
+ * The following additional context information is available
+ * for this kind of completion proposal at little extra cost:
+ * <ul>
+ * <li>{@link #getDeclarationSignature()} -
+ * the type signature of the type that declares the field that is referenced
+ * </li>
+ * <li>{@link #getFlags()} -
+ * the modifiers flags (including ACC_ENUM) of the field that is referenced
+ * </li>
+ * <li>{@link #getName()} -
+ * the simple name of the field that is referenced
+ * </li>
+ * <li>{@link #getSignature()} -
+ * the type signature of the field's type (as opposed to the
+ * signature of the type in which the referenced field
+ * is declared)
+ * </li>
+ * </ul>
+ * </p>
+ *
+ * @see #getKind()
+ * @since 3.2
+ */
+ public static final int JAVADOC_VALUE_REF = 17;
+
+ /**
+ * Completion is a method argument or a class/method type parameter
+ * in javadoc param tag.
+ * This kind of completion might occur in a context like
+ * <code>" * @param arg^ blabla"</code> and complete it to
+ * <code>" * @param argument blabla"</code>.
+ * or
+ * <code>" * @param <T^ blabla"</code> and complete it to
+ * <code>" * @param <TT> blabla"</code>.
+ * <p>
+ * The following additional context information is available
+ * for this kind of completion proposal at little extra cost:
+ * <ul>
+ * <li>{@link #getDeclarationSignature()} -
+ * the type signature of the type that declares the field that is referenced
+ * </li>
+ * <li>{@link #getFlags()} -
+ * the modifiers flags (including ACC_ENUM) of the field that is referenced
+ * </li>
+ * <li>{@link #getName()} -
+ * the simple name of the field that is referenced
+ * </li>
+ * <li>{@link #getSignature()} -
+ * the type signature of the field's type (as opposed to the
+ * signature of the type in which the referenced field
+ * is declared)
+ * </li>
+ * </ul>
+ * </p>
+ *
+ * @see #getKind()
+ * @since 3.2
+ */
+ public static final int JAVADOC_PARAM_REF = 18;
+
+ /**
+ * Completion is a javadoc block tag.
+ * This kind of completion might occur in a context like
+ * <code>" * @s^ blabla"</code> and complete it to
+ * <code>" * @see blabla"</code>.
+ * <p>
+ * The following additional context information is available
+ * for this kind of completion proposal at little extra cost:
+ * <ul>
+ * <li>{@link #getDeclarationSignature()} -
+ * the type signature of the type that declares the field that is referenced
+ * </li>
+ * <li>{@link #getFlags()} -
+ * the modifiers flags (including ACC_ENUM) of the field that is referenced
+ * </li>
+ * <li>{@link #getName()} -
+ * the simple name of the field that is referenced
+ * </li>
+ * <li>{@link #getSignature()} -
+ * the type signature of the field's type (as opposed to the
+ * signature of the type in which the referenced field
+ * is declared)
+ * </li>
+ * </ul>
+ * </p>
+ *
+ * @see #getKind()
+ * @since 3.2
+ */
+ public static final int JAVADOC_BLOCK_TAG = 19;
+
+ /**
+ * Completion is a javadoc inline tag.
+ * This kind of completion might occur in a context like
+ * <code>" * Insert @l^ Object"</code> and complete it to
+ * <code>" * Insert {@link Object }"</code>.
+ * <p>
+ * The following additional context information is available
+ * for this kind of completion proposal at little extra cost:
+ * <ul>
+ * <li>{@link #getDeclarationSignature()} -
+ * the type signature of the type that declares the field that is referenced
+ * </li>
+ * <li>{@link #getFlags()} -
+ * the modifiers flags (including ACC_ENUM) of the field that is referenced
+ * </li>
+ * <li>{@link #getName()} -
+ * the simple name of the field that is referenced
+ * </li>
+ * <li>{@link #getSignature()} -
+ * the type signature of the field's type (as opposed to the
+ * signature of the type in which the referenced field
+ * is declared)
+ * </li>
+ * </ul>
+ * </p>
+ *
+ * @see #getKind()
+ * @since 3.2
+ */
+ public static final int JAVADOC_INLINE_TAG = 20;
+
+ /**
+ * Completion is an import of reference to a static field.
+ * <p>
+ * The following additional context information is available
+ * for this kind of completion proposal at little extra cost:
+ * <ul>
+ * <li>{@link #getDeclarationSignature()} -
+ * the type signature of the type that declares the field that is imported
+ * </li>
+ * <li>{@link #getFlags()} -
+ * the modifiers flags (including ACC_ENUM) of the field that is imported
+ * </li>
+ * <li>{@link #getName()} -
+ * the simple name of the field that is imported
+ * </li>
+ * <li>{@link #getSignature()} -
+ * the type signature of the field's type (as opposed to the
+ * signature of the type in which the referenced field
+ * is declared)
+ * </li>
+ * <li>{@link #getAdditionalFlags()} -
+ * the completion flags (including ComletionFlags.StaticImport)
+ * of the proposed import
+ * </li>
+ * </ul>
+ * </p>
+ *
+ * @see #getKind()
+ *
+ * @since 3.3
+ */
+ public static final int FIELD_IMPORT = 21;
+
+ /**
+ * Completion is an import of reference to a static method.
+ * <p>
+ * The following additional context information is available
+ * for this kind of completion proposal at little extra cost:
+ * <ul>
+ * <li>{@link #getDeclarationSignature()} -
+ * the type signature of the type that declares the method that is imported
+ * </li>
+ * <li>{@link #getFlags()} -
+ * the modifiers flags of the method that is imported
+ * </li>
+ * <li>{@link #getName()} -
+ * the simple name of the method that is imported
+ * </li>
+ * <li>{@link #getSignature()} -
+ * the method signature of the method that is imported
+ * </li>
+ * <li>{@link #getAdditionalFlags()} -
+ * the completion flags (including ComletionFlags.StaticImport)
+ * of the proposed import
+ * </li>
+ * </ul>
+ * </p>
+ *
+ * @see #getKind()
+ *
+ * @since 3.3
+ */
+ public static final int METHOD_IMPORT = 22;
+
+ /**
+ * Completion is an import of reference to a type.
+ * Only reference to reference types are allowed.
+ * <p>
+ * The following additional context information is available
+ * for this kind of completion proposal at little extra cost:
+ * <ul>
+ * <li>{@link #getDeclarationSignature()} -
+ * the dot-based package name of the package that contains
+ * the type that is imported
+ * </li>
+ * <li>{@link #getSignature()} -
+ * the type signature of the type that is imported
+ * </li>
+ * <li>{@link #getFlags()} -
+ * the modifiers flags (including Flags.AccInterface, AccEnum,
+ * and AccAnnotation) of the type that is imported
+ * </li>
+ * <li>{@link #getAdditionalFlags()} -
+ * the completion flags (including ComletionFlags.StaticImport)
+ * of the proposed import
+ * </li>
+ * </ul>
+ * </p>
+ *
+ * @see #getKind()
+ *
+ * @since 3.3
+ */
+ public static final int TYPE_IMPORT = 23;
/**
* First valid completion kind.
@@ -424,7 +737,7 @@
*
* @since 3.1
*/
- protected static final int LAST_KIND = ANNOTATION_ATTRIBUTE_REF;
+ protected static final int LAST_KIND = TYPE_IMPORT;
/**
* Kind of completion request.
@@ -513,6 +826,13 @@
private char[] key = null;
/**
+ * Array of required completion proposals, or <code>null</code> if none.
+ * The proposal can not be applied if the required proposals aren't applied.
+ * Defaults to <code>null</code>.
+ */
+ private CompletionProposal[] requiredProposals;
+
+ /**
* Modifier flags relevant in the context, or
* <code>Flags.AccDefault</code> if none.
* Defaults to <code>Flags.AccDefault</code>.
@@ -520,6 +840,13 @@
private int flags = Flags.AccDefault;
/**
+ * Completion flags relevant in the context, or
+ * <code>CompletionFlags.Default</code> if none.
+ * Defaults to <code>CompletionFlags.Default</code>.
+ */
+ private int additionalFlags = CompletionFlags.Default;
+
+ /**
* Parameter names (for method completions), or
* <code>null</code> if none. Lazily computed.
* Defaults to <code>null</code>.
@@ -566,13 +893,69 @@
throw new IllegalArgumentException();
}
if (this.completion == null || completionLocation < 0) {
- throw new IllegalArgumentException();
+ // Work around for bug 132558 (https://bugs.eclipse.org/bugs/show_bug.cgi?id=132558).
+ // completionLocation can be -1 if the completion occur at the start of a file or
+ // the start of a code snippet but this API isn't design to support negative position.
+ if(this.completion == null || completionLocation != -1) {
+ throw new IllegalArgumentException();
+ }
+ completionLocation = 0;
}
this.completionKind = kind;
this.completionLocation = completionLocation;
}
/**
+ * Returns the completion flags relevant in the context, or
+ * <code>CompletionFlags.Default</code> if none.
+ * <p>
+ * This field is available for the following kinds of
+ * completion proposals:
+ * <ul>
+ * <li><code>FIELD_IMPORT</code> - completion flags
+ * of the attribute that is referenced. Completion flags for
+ * this proposal kind can only include <code>CompletionFlags.StaticImport</code></li>
+ * <li><code>METHOD_IMPORT</code> - completion flags
+ * of the attribute that is referenced. Completion flags for
+ * this proposal kind can only include <code>CompletionFlags.StaticImport</code></li>
+ * <li><code>TYPE_IMPORT</code> - completion flags
+ * of the attribute that is referenced. Completion flags for
+ * this proposal kind can only include <code>CompletionFlags.StaticImport</code></li>
+ * </ul>
+ * For other kinds of completion proposals, this method returns
+ * <code>CompletionFlags.Default</code>.
+ * </p>
+ *
+ * @return the completion flags, or
+ * <code>CompletionFlags.Default</code> if none
+ * @see CompletionFlags
+ *
+ * @since 3.3
+ */
+ public int getAdditionalFlags() {
+ return this.additionalFlags;
+ }
+
+ /**
+ * Sets the completion flags relevant in the context.
+ * <p>
+ * If not set, defaults to none.
+ * </p>
+ * <p>
+ * The completion engine creates instances of this class and sets
+ * its properties; this method is not intended to be used by other clients.
+ * </p>
+ *
+ * @param additionalFlags the completion flags, or
+ * <code>CompletionFlags.Default</code> if none
+ *
+ * @since 3.3
+ */
+ public void setAdditionalFlags(int additionalFlags) {
+ this.additionalFlags = additionalFlags;
+ }
+
+ /**
* Returns the kind of completion being proposed.
* <p>
* The set of different kinds of completion proposals is
@@ -593,12 +976,13 @@
/**
* Returns the character index in the source file buffer
* where source completion was requested (the
- * <code>offset</code>parameter to
- * <code>ICodeAssist.codeComplete</code>.
+ * <code>offset</code> parameter to
+ * <code>ICodeAssist.codeComplete</code> minus one).
*
* @return character index in source file buffer
* @see ICodeAssist#codeComplete(int,CompletionRequestor)
*/
+ // TODO (david) https://bugs.eclipse.org/bugs/show_bug.cgi?id=132558
public int getCompletionLocation() {
return this.completionLocation;
}
@@ -825,16 +1209,22 @@
* of the annotation that declares the attribute that is referenced</li>
* <li><code>ANONYMOUS_CLASS_DECLARATION</code> - type signature
* of the type that is being subclassed or implemented</li>
- * <li><code>FIELD_REF</code> - type signature
+ * <li><code>FIELD_IMPORT</code> - type signature
+ * of the type that declares the field that is imported</li>
+ * <li><code>FIELD_REF</code> - type signature
* of the type that declares the field that is referenced</li>
- * <li><code>METHOD_REF</code> - type signature
+ * <li><code>METHOD_IMPORT</code> - type signature
+ * of the type that declares the method that is imported</li>
+ * <li><code>METHOD_REF</code> - type signature
* of the type that declares the method that is referenced</li>
* <li><code>METHOD_DECLARATION</code> - type signature
* of the type that declares the method that is being
* implemented or overridden</li>
* <li><code>PACKAGE_REF</code> - dot-based package
* name of the package that is referenced</li>
- * <li><code>TYPE_REF</code> - dot-based package
+ * <li><code>TYPE_IMPORT</code> - dot-based package
+ * name of the package containing the type that is imported</li>
+ * <li><code>TYPE_REF</code> - dot-based package
* name of the package containing the type that is referenced</li>
* <li><code>POTENTIAL_METHOD_DECLARATION</code> - type signature
* of the type that declares the method that is being created</li>
@@ -924,11 +1314,13 @@
* completion proposals:
* <ul>
* <li><code>ANNOTATION_ATTRIBUT_REF</code> - the name of the attribute</li>
- * <li><code>FIELD_REF</code> - the name of the field</li>
+ * <li><code>FIELD_IMPORT</code> - the name of the field</li>
+ * <li><code>FIELD_REF</code> - the name of the field</li>
* <li><code>KEYWORD</code> - the keyword</li>
* <li><code>LABEL_REF</code> - the name of the label</li>
* <li><code>LOCAL_VARIABLE_REF</code> - the name of the local variable</li>
- * <li><code>METHOD_REF</code> - the name of the method (the type simple name for constructor)</li>
+ * <li><code>METHOD_IMPORT</code> - the name of the method</li>
+ * <li><code>METHOD_REF</code> - the name of the method (the type simple name for constructor)</li>
* <li><code>METHOD_DECLARATION</code> - the name of the method (the type simple name for constructor)</li>
* <li><code>VARIABLE_DECLARATION</code> - the name of the variable</li>
* <li><code>POTENTIAL_METHOD_DECLARATION</code> - the name of the method</li>
@@ -976,14 +1368,20 @@
* of the referenced attribute's type</li>
* <li><code>ANONYMOUS_CLASS_DECLARATION</code> - method signature
* of the constructor that is being invoked</li>
- * <li><code>FIELD_REF</code> - the type signature
+ * <li><code>FIELD_IMPORT</code> - the type signature
+ * of the referenced field's type</li>
+ * <li><code>FIELD_REF</code> - the type signature
* of the referenced field's type</li>
* <li><code>LOCAL_VARIABLE_REF</code> - the type signature
* of the referenced local variable's type</li>
- * <li><code>METHOD_REF</code> - method signature
+ * <li><code>METHOD_IMPORT</code> - method signature
+ * of the method that is imported</li>
+ * <li><code>METHOD_REF</code> - method signature
* of the method that is referenced</li>
* <li><code>METHOD_DECLARATION</code> - method signature
* of the method that is being implemented or overridden</li>
+ * <li><code>TYPE_IMPORT</code> - type signature
+ * of the type that is imported</li>
* <li><code>TYPE_REF</code> - type signature
* of the type that is referenced</li>
* <li><code>VARIABLE_DECLARATION</code> - the type signature
@@ -1074,10 +1472,10 @@
// * of the type that is being subclassed or implemented</li>
// * <li><code>FIELD_REF</code> - the dot-based type name
// * of the type that declares the field that is referenced
-// * or an anonymous type instanciation ("new X(){}") if it is an anonymous type</li>
+// * or an anonymous type instantiation ("new X(){}") if it is an anonymous type</li>
// * <li><code>METHOD_REF</code> - the dot-based type name
// * of the type that declares the method that is referenced
-// * or an anonymous type instanciation ("new X(){}") if it is an anonymous type</li>
+// * or an anonymous type instantiation ("new X(){}") if it is an anonymous type</li>
// * <li><code>METHOD_DECLARATION</code> - the dot-based type name
// * of the type that declares the method that is being
// * implemented or overridden</li>
@@ -1205,7 +1603,7 @@
// }
//
// /**
-// * Returns the parameter type names without teh package fragment of
+// * Returns the parameter type names without the package fragment of
// * the method relevant in the context, or <code>null</code> if none.
// * <p>
// * This field is available for the following kinds of
@@ -1280,23 +1678,33 @@
* of the attribute that is referenced;
* <li><code>ANONYMOUS_CLASS_DECLARATION</code> - modifier flags
* of the constructor that is referenced</li>
- * <li><code>FIELD_REF</code> - modifier flags
+ * <li><code>FIELD_IMPORT</code> - modifier flags
+ * of the field that is imported.</li>
+ * <li><code>FIELD_REF</code> - modifier flags
* of the field that is referenced;
* <code>Flags.AccEnum</code> can be used to recognize
* references to enum constants
* </li>
* <li><code>KEYWORD</code> - modifier flag
- * corrresponding to the modifier keyword</li>
+ * corresponding to the modifier keyword</li>
* <li><code>LOCAL_VARIABLE_REF</code> - modifier flags
* of the local variable that is referenced</li>
+ * <li><code>METHOD_IMPORT</code> - modifier flags
+ * of the method that is imported;
+ * </li>
* <li><code>METHOD_REF</code> - modifier flags
* of the method that is referenced;
* <code>Flags.AccAnnotation</code> can be used to recognize
* references to annotation type members
* </li>
- * <li><code>METHOD_DECLARATION</code> - modifier flags
+ * <li><code>METHOD_DECLARATION</code> - modifier flags
* for the method that is being implemented or overridden</li>
- * <li><code>TYPE_REF</code> - modifier flags
+ * <li><code>TYPE_IMPORT</code> - modifier flags
+ * of the type that is imported; <code>Flags.AccInterface</code>
+ * can be used to recognize references to interfaces,
+ * <code>Flags.AccEnum</code> enum types,
+ * and <code>Flags.AccAnnotation</code> annotation types</li>
+ * <li><code>TYPE_REF</code> - modifier flags
* of the type that is referenced; <code>Flags.AccInterface</code>
* can be used to recognize references to interfaces,
* <code>Flags.AccEnum</code> enum types,
@@ -1337,6 +1745,69 @@
}
/**
+ * Returns the required completion proposals.
+ * The proposal can be apply only if these required completion proposals are also applied.
+ * If the required proposal aren't applied the completion could create completion problems.
+ *
+ * <p>
+ * This field is available for the following kinds of
+ * completion proposals:
+ * <ul>
+ * <li><code>FIELD_REF</code> - The allowed required proposals for this kind are:
+ * <ul>
+ * <li><code>TYPE_REF</code></li>
+ * <li><code>TYPE_IMPORT</code></li>
+ * <li><code>FIELD_IMPORT</code></li>
+ * </ul>
+ * </li>
+ * <li><code>METHOD_REF</code> - The allowed required proposals for this kind are:
+ * <ul>
+ * <li><code>TYPE_REF</code></li>
+ * <li><code>TYPE_IMPORT</code></li>
+ * <li><code>METHOD_IMPORT</code></li>
+ * </ul>
+ * </li>
+ * </ul>
+ * </p>
+ * <p>
+ * Other kinds of required proposals will be returned in the future, therefore clients of this
+ * API must allow with {@link CompletionRequestor#setAllowsRequiredProposals(int, int, boolean)}
+ * only kinds which are in this list to avoid unexpected results in the future.
+ * </p>
+ * <p>
+ * A required completion proposal cannot have required completion proposals.
+ * </p>
+ *
+ * @return the required completion proposals, or <code>null</code> if none.
+ *
+ * @see CompletionRequestor#setAllowsRequiredProposals(int, int,boolean)
+ *
+ * @since 3.3
+ */
+ public CompletionProposal[] getRequiredProposals() {
+ return this.requiredProposals;
+ }
+
+
+ /**
+ * Sets the list of required completion proposals, or <code>null</code> if none.
+ * <p>
+ * If not set, defaults to none.
+ * </p>
+ * <p>
+ * The completion engine creates instances of this class and sets
+ * its properties; this method is not intended to be used by other clients.
+ * </p>
+ *
+ * @param proposals the list of required completion proposals, or
+ * <code>null</code> if none
+ * @since 3.3
+ */
+ public void setRequiredProposals(CompletionProposal[] proposals) {
+ this.requiredProposals = proposals;
+ }
+
+ /**
* Finds the method parameter names.
* This information is relevant to method reference (and
* method declaration proposals). Returns <code>null</code>
@@ -1346,7 +1817,7 @@
* </p>
* <p>
* <b>Note that this is an expensive thing to compute, which may require
- * parsing Java source files, etc. Use sparingly.
+ * parsing Java source files, etc. Use sparingly.</b>
* </p>
*
* @param monitor the progress monitor, or <code>null</code> if none
@@ -1475,4 +1946,110 @@
public boolean isConstructor() {
return this.isConstructor;
}
+
+ public String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append('[');
+ switch(this.completionKind) {
+ case CompletionProposal.ANONYMOUS_CLASS_DECLARATION :
+ buffer.append("ANONYMOUS_CLASS_DECLARATION"); //$NON-NLS-1$
+ break;
+ case CompletionProposal.FIELD_REF :
+ buffer.append("FIELD_REF"); //$NON-NLS-1$
+ break;
+ case CompletionProposal.KEYWORD :
+ buffer.append("KEYWORD"); //$NON-NLS-1$
+ break;
+ case CompletionProposal.LABEL_REF :
+ buffer.append("LABEL_REF"); //$NON-NLS-1$
+ break;
+ case CompletionProposal.LOCAL_VARIABLE_REF :
+ buffer.append("LOCAL_VARIABLE_REF"); //$NON-NLS-1$
+ break;
+ case CompletionProposal.METHOD_DECLARATION :
+ buffer.append("METHOD_DECLARATION"); //$NON-NLS-1$
+ if(this.isConstructor) {
+ buffer.append("<CONSTRUCTOR>"); //$NON-NLS-1$
+ }
+ break;
+ case CompletionProposal.METHOD_REF :
+ buffer.append("METHOD_REF"); //$NON-NLS-1$
+ if(this.isConstructor) {
+ buffer.append("<CONSTRUCTOR>"); //$NON-NLS-1$
+ }
+ break;
+ case CompletionProposal.PACKAGE_REF :
+ buffer.append("PACKAGE_REF"); //$NON-NLS-1$
+ break;
+ case CompletionProposal.TYPE_REF :
+ buffer.append("TYPE_REF"); //$NON-NLS-1$
+ break;
+ case CompletionProposal.VARIABLE_DECLARATION :
+ buffer.append("VARIABLE_DECLARATION"); //$NON-NLS-1$
+ break;
+ case CompletionProposal.POTENTIAL_METHOD_DECLARATION :
+ buffer.append("POTENTIAL_METHOD_DECLARATION"); //$NON-NLS-1$
+ break;
+ case CompletionProposal.METHOD_NAME_REFERENCE :
+ buffer.append("METHOD_IMPORT"); //$NON-NLS-1$
+ break;
+ case CompletionProposal.ANNOTATION_ATTRIBUTE_REF :
+ buffer.append("ANNOTATION_ATTRIBUTE_REF"); //$NON-NLS-1$
+ break;
+ case CompletionProposal.JAVADOC_BLOCK_TAG :
+ buffer.append("JAVADOC_BLOCK_TAG"); //$NON-NLS-1$
+ break;
+ case CompletionProposal.JAVADOC_INLINE_TAG :
+ buffer.append("JAVADOC_INLINE_TAG"); //$NON-NLS-1$
+ break;
+ case CompletionProposal.JAVADOC_FIELD_REF:
+ buffer.append("JAVADOC_FIELD_REF"); //$NON-NLS-1$
+ break;
+ case CompletionProposal.JAVADOC_METHOD_REF :
+ buffer.append("JAVADOC_METHOD_REF"); //$NON-NLS-1$
+ break;
+ case CompletionProposal.JAVADOC_TYPE_REF :
+ buffer.append("JAVADOC_TYPE_REF"); //$NON-NLS-1$
+ break;
+ case CompletionProposal.JAVADOC_PARAM_REF :
+ buffer.append("JAVADOC_PARAM_REF"); //$NON-NLS-1$
+ break;
+ case CompletionProposal.JAVADOC_VALUE_REF :
+ buffer.append("JAVADOC_VALUE_REF"); //$NON-NLS-1$
+ break;
+ case CompletionProposal.FIELD_IMPORT :
+ buffer.append("FIELD_IMPORT"); //$NON-NLS-1$
+ break;
+ case CompletionProposal.METHOD_IMPORT :
+ buffer.append("METHOD_IMPORT"); //$NON-NLS-1$
+ break;
+ case CompletionProposal.TYPE_IMPORT :
+ buffer.append("TYPE_IMPORT"); //$NON-NLS-1$
+ break;
+ default :
+ buffer.append("PROPOSAL"); //$NON-NLS-1$
+ break;
+
+ }
+ buffer.append("]{completion:"); //$NON-NLS-1$
+ if (this.completion != null) buffer.append(this.completion);
+ buffer.append(", declSign:"); //$NON-NLS-1$
+ if (this.declarationSignature != null) buffer.append(this.declarationSignature);
+ buffer.append(", sign:"); //$NON-NLS-1$
+ if (this.signature != null) buffer.append(this.signature);
+ buffer.append(", declKey:"); //$NON-NLS-1$
+ if (this.declarationKey != null) buffer.append(this.declarationKey);
+ buffer.append(", key:"); //$NON-NLS-1$
+ if (this.key != null) buffer.append(key);
+ buffer.append(", name:"); //$NON-NLS-1$
+ if (this.name != null) buffer.append(this.name);
+ buffer.append(", ["); //$NON-NLS-1$
+ buffer.append(this.replaceStart);
+ buffer.append(',');
+ buffer.append(this.replaceEnd);
+ buffer.append("], relevance="); //$NON-NLS-1$
+ buffer.append(this.relevance);
+ buffer.append('}');
+ return buffer.toString();
+ }
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionRequestor.java
index f2654b6..fe1fb1c 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionRequestor.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * Copyright (c) 2004, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -20,7 +20,7 @@
* </p>
* <p>
* The code assist engine normally invokes methods on completion
- * requestors in the following sequence:
+ * requestor in the following sequence:
* <pre>
* requestor.beginReporting();
* requestor.acceptContext(context);
@@ -59,6 +59,15 @@
* 1 << completionProposalKind
*/
private int ignoreSet = 0;
+
+ private String[] favoriteReferences;
+
+ /**
+ * The set of CompletionProposal kinds that this requestor
+ * allows for required proposals; <code>0</code> means the set is empty.
+ * 1 << completionProposalKind
+ */
+ private int requiredProposalAllowSet[] = null;
/**
* Creates a new completion requestor.
@@ -80,10 +89,10 @@
* @see #setIgnored(int, boolean)
* @see CompletionProposal#getKind()
*/
- public final boolean isIgnored(int completionProposalKind) {
+ public boolean isIgnored(int completionProposalKind) {
if (completionProposalKind < CompletionProposal.FIRST_KIND
|| completionProposalKind > CompletionProposal.LAST_KIND) {
- throw new IllegalArgumentException();
+ throw new IllegalArgumentException("Unknown kind of completion proposal: "+completionProposalKind); //$NON-NLS-1$
}
return 0 != (this.ignoreSet & (1 << completionProposalKind));
}
@@ -99,10 +108,10 @@
* @see #isIgnored(int)
* @see CompletionProposal#getKind()
*/
- public final void setIgnored(int completionProposalKind, boolean ignore) {
+ public void setIgnored(int completionProposalKind, boolean ignore) {
if (completionProposalKind < CompletionProposal.FIRST_KIND
|| completionProposalKind > CompletionProposal.LAST_KIND) {
- throw new IllegalArgumentException();
+ throw new IllegalArgumentException("Unknown kind of completion proposal: "+completionProposalKind); //$NON-NLS-1$
}
if (ignore) {
this.ignoreSet |= (1 << completionProposalKind);
@@ -112,6 +121,118 @@
}
/**
+ * Returns whether a proposal of a given kind with a required proposal
+ * of the given kind is allowed.
+ *
+ * @param proposalKind one of the kind constants declared
+ * @param requiredProposalKind one of the kind constants declared
+ * on <code>CompletionProposal</code>
+ * @return <code>true</code> if a proposal of a given kind with a required proposal
+ * of the given kind is allowed by this requestor, and <code>false</code>
+ * if it isn't of interest.
+ * <p>
+ * By default, all kinds of required proposals aren't allowed.
+ * </p>
+ * @see #setAllowsRequiredProposals(int, int, boolean)
+ * @see CompletionProposal#getKind()
+ * @see CompletionProposal#getRequiredProposals()
+ *
+ * @since 3.3
+ */
+ public boolean isAllowingRequiredProposals(int proposalKind, int requiredProposalKind) {
+ if (proposalKind < CompletionProposal.FIRST_KIND
+ || proposalKind > CompletionProposal.LAST_KIND) {
+ throw new IllegalArgumentException("Unknown kind of completion proposal: "+requiredProposalKind); //$NON-NLS-1$
+ }
+
+ if (requiredProposalKind < CompletionProposal.FIRST_KIND
+ || requiredProposalKind > CompletionProposal.LAST_KIND) {
+ throw new IllegalArgumentException("Unknown required kind of completion proposal: "+requiredProposalKind); //$NON-NLS-1$
+ }
+ if (this.requiredProposalAllowSet == null) return false;
+
+ return 0 != (this.requiredProposalAllowSet[proposalKind] & (1 << requiredProposalKind));
+ }
+
+ /**
+ * Sets whether a proposal of a given kind with a required proposal
+ * of the given kind is allowed.
+ *
+ * Currently only a subset of kinds support required proposals. To see what combinations
+ * are supported you must look at {@link CompletionProposal#getRequiredProposals()}
+ * documentation.
+ *
+ * @param proposalKind one of the kind constants declared
+ * @param requiredProposalKind one of the kind constants declared
+ * on <code>CompletionProposal</code>
+ * @param allow <code>true</code> if a proposal of a given kind with a required proposal
+ * of the given kind is allowed by this requestor, and <code>false</code>
+ * if it isn't of interest
+ * @see #isAllowingRequiredProposals(int, int)
+ * @see CompletionProposal#getKind()
+ * @see CompletionProposal#getRequiredProposals()
+ *
+ * @since 3.3
+ */
+ public void setAllowsRequiredProposals(int proposalKind, int requiredProposalKind, boolean allow) {
+ if (proposalKind < CompletionProposal.FIRST_KIND
+ || proposalKind > CompletionProposal.LAST_KIND) {
+ throw new IllegalArgumentException("Unknown kind of completion proposal: "+requiredProposalKind); //$NON-NLS-1$
+ }
+ if (requiredProposalKind < CompletionProposal.FIRST_KIND
+ || requiredProposalKind > CompletionProposal.LAST_KIND) {
+ throw new IllegalArgumentException("Unknown required kind of completion proposal: "+requiredProposalKind); //$NON-NLS-1$
+ }
+
+ if (this.requiredProposalAllowSet == null) {
+ this.requiredProposalAllowSet = new int[CompletionProposal.LAST_KIND + 1];
+ }
+
+ if (allow) {
+ this.requiredProposalAllowSet[proposalKind] |= (1 << requiredProposalKind);
+ } else {
+ this.requiredProposalAllowSet[proposalKind] &= ~(1 << requiredProposalKind);
+ }
+ }
+
+ /**
+ * Returns the favorite references which are used to compute some completion proposals.
+ * <p>
+ * A favorite reference is a qualified reference as it can be seen in an import statement.<br>
+ * e.g. <code>{"java.util.Arrays"}</code><br>
+ * It can be an on demand reference.<br>
+ * e.g. <code>{"java.util.Arrays.*"}</code>
+ * It can be a reference to a static method or field (as in a static import)<br>
+ * e.g. <code>{"java.util.Arrays.equals"}</code>
+ * </p>
+ * <p>
+ * Currently only on demand type references (<code>"java.util.Arrays.*"</code>),
+ * references to a static method or a static field are used to compute completion proposals.
+ * Other kind of reference could be used in the future.
+ * </p>
+ * @return favorite imports
+ *
+ * @since 3.3
+ */
+ public String[] getFavoriteReferences() {
+ return this.favoriteReferences;
+ }
+
+ /**
+ * Set the favorite references which will be used to compute some completion proposals.
+ * A favorite reference is a qualified reference as it can be seen in an import statement.<br>
+ *
+ * @param favoriteImports
+ *
+ * @see #getFavoriteReferences()
+ *
+ * @since 3.3
+ */
+ public void setFavoriteReferences(String[] favoriteImports) {
+ this.favoriteReferences = favoriteImports;
+ }
+
+ /**
* Pro forma notification sent before reporting a batch of
* completion proposals.
* <p>
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionRequestorAdapter.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionRequestorAdapter.java
index 1cc38aa..bb872dc 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionRequestorAdapter.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionRequestorAdapter.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CorrectionEngine.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CorrectionEngine.java
index d873606..2b1f71f 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CorrectionEngine.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CorrectionEngine.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,6 +10,7 @@
*******************************************************************************/
package org.eclipse.jdt.core;
+import java.util.Hashtable;
import java.util.Map;
import org.eclipse.core.resources.*;
@@ -273,11 +274,19 @@
break;
}
}
-
- this.compilationUnit.codeComplete(
- completionPosition,
- this.completionRequestor
- );
+ Hashtable oldOptions = JavaCore.getOptions();
+ try {
+ Hashtable options = new Hashtable(oldOptions);
+ options.put(JavaCore.CODEASSIST_CAMEL_CASE_MATCH, JavaCore.DISABLED);
+ JavaCore.setOptions(options);
+
+ this.compilationUnit.codeComplete(
+ completionPosition,
+ this.completionRequestor
+ );
+ } finally {
+ JavaCore.setOptions(oldOptions);
+ }
} catch (JavaModelException e) {
return;
} catch (InvalidInputException e) {
@@ -386,6 +395,26 @@
}
}
};
+
+
+ /**
+ * Return an array of strings which contains one entry per warning token
+ * accepted by the <code>@SuppressWarnings</code> annotation. This array is
+ * neither null nor empty, it contains at least the String <code>all</code>.
+ * It should not be modified by the caller (please take a copy if modifications
+ * are needed).<br>
+ * <b>Note:</b> The tokens returned are not necessarily standardized across Java
+ * compilers. If you were to use one of these tokens in a <code>@SuppressWarnings</code>
+ * annotation in the Java source code, the effects (if any) may vary from
+ * compiler to compiler.
+ *
+ * @return an array of strings which contains one entry per warning token
+ * accepted by the <code>@SuppressWarnings</code> annotation.
+ * @since 3.2
+ */
+ public static String[] getAllWarningTokens() {
+ return CompilerOptions.warningTokens;
+ }
/**
* Helper method for decoding problem marker attributes. Returns an array of String arguments
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ElementChangedEvent.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ElementChangedEvent.java
index 00a51c4..2a3ed08 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ElementChangedEvent.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ElementChangedEvent.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/Flags.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/Flags.java
index 1097d50..687af9e 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/Flags.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/Flags.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -12,7 +12,7 @@
*******************************************************************************/
package org.eclipse.jdt.core;
-import org.eclipse.jdt.internal.compiler.env.IConstants;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
/**
* Utility class for decoding modifier flags in Java elements.
@@ -35,82 +35,82 @@
* Constant representing the absence of any flag
* @since 3.0
*/
- public static final int AccDefault = 0;
+ public static final int AccDefault = ClassFileConstants.AccDefault;
/**
* Public access flag. See The Java Virtual Machine Specification for more details.
* @since 2.0
*/
- public static final int AccPublic = IConstants.AccPublic;
+ public static final int AccPublic = ClassFileConstants.AccPublic;
/**
* Private access flag. See The Java Virtual Machine Specification for more details.
* @since 2.0
*/
- public static final int AccPrivate = IConstants.AccPrivate;
+ public static final int AccPrivate = ClassFileConstants.AccPrivate;
/**
* Protected access flag. See The Java Virtual Machine Specification for more details.
* @since 2.0
*/
- public static final int AccProtected = IConstants.AccProtected;
+ public static final int AccProtected = ClassFileConstants.AccProtected;
/**
* Static access flag. See The Java Virtual Machine Specification for more details.
* @since 2.0
*/
- public static final int AccStatic = IConstants.AccStatic;
+ public static final int AccStatic = ClassFileConstants.AccStatic;
/**
* Final access flag. See The Java Virtual Machine Specification for more details.
* @since 2.0
*/
- public static final int AccFinal = IConstants.AccFinal;
+ public static final int AccFinal = ClassFileConstants.AccFinal;
/**
* Synchronized access flag. See The Java Virtual Machine Specification for more details.
* @since 2.0
*/
- public static final int AccSynchronized = IConstants.AccSynchronized;
+ public static final int AccSynchronized = ClassFileConstants.AccSynchronized;
/**
* Volatile property flag. See The Java Virtual Machine Specification for more details.
* @since 2.0
*/
- public static final int AccVolatile = IConstants.AccVolatile;
+ public static final int AccVolatile = ClassFileConstants.AccVolatile;
/**
* Transient property flag. See The Java Virtual Machine Specification for more details.
* @since 2.0
*/
- public static final int AccTransient = IConstants.AccTransient;
+ public static final int AccTransient = ClassFileConstants.AccTransient;
/**
* Native property flag. See The Java Virtual Machine Specification for more details.
* @since 2.0
*/
- public static final int AccNative = IConstants.AccNative;
+ public static final int AccNative = ClassFileConstants.AccNative;
/**
* Interface property flag. See The Java Virtual Machine Specification for more details.
* @since 2.0
*/
- public static final int AccInterface = IConstants.AccInterface;
+ public static final int AccInterface = ClassFileConstants.AccInterface;
/**
* Abstract property flag. See The Java Virtual Machine Specification for more details.
* @since 2.0
*/
- public static final int AccAbstract = IConstants.AccAbstract;
+ public static final int AccAbstract = ClassFileConstants.AccAbstract;
/**
* Strictfp property flag. See The Java Virtual Machine Specification for more details.
* @since 2.0
*/
- public static final int AccStrictfp = IConstants.AccStrictfp;
+ public static final int AccStrictfp = ClassFileConstants.AccStrictfp;
/**
* Super property flag. See The Java Virtual Machine Specification for more details.
* @since 2.0
*/
- public static final int AccSuper = IConstants.AccSuper;
+ public static final int AccSuper = ClassFileConstants.AccSuper;
/**
* Synthetic property flag. See The Java Virtual Machine Specification for more details.
* @since 2.0
*/
- public static final int AccSynthetic = IConstants.AccSynthetic;
+ public static final int AccSynthetic = ClassFileConstants.AccSynthetic;
/**
* Deprecated property flag. See The Java Virtual Machine Specification for more details.
* @since 2.0
*/
- public static final int AccDeprecated = IConstants.AccDeprecated;
+ public static final int AccDeprecated = ClassFileConstants.AccDeprecated;
/**
* Bridge method property flag (added in J2SE 1.5). Used to flag a compiler-generated
@@ -118,7 +118,7 @@
* See The Java Virtual Machine Specification for more details.
* @since 3.0
*/
- public static final int AccBridge = IConstants.AccBridge;
+ public static final int AccBridge = ClassFileConstants.AccBridge;
/**
* Varargs method property flag (added in J2SE 1.5).
@@ -126,21 +126,21 @@
* See The Java Virtual Machine Specification for more details.
* @since 3.0
*/
- public static final int AccVarargs = IConstants.AccVarargs;
+ public static final int AccVarargs = ClassFileConstants.AccVarargs;
/**
* Enum property flag (added in J2SE 1.5).
* See The Java Virtual Machine Specification for more details.
* @since 3.0
*/
- public static final int AccEnum = 0x4000;
+ public static final int AccEnum = ClassFileConstants.AccEnum;
/**
* Annotation property flag (added in J2SE 1.5).
* See The Java Virtual Machine Specification for more details.
* @since 3.0
*/
- public static final int AccAnnotation = 0x2000;
+ public static final int AccAnnotation = ClassFileConstants.AccAnnotation;
/**
* Not instantiable.
@@ -196,6 +196,17 @@
return (flags & AccNative) != 0;
}
/**
+ * Returns whether the given integer does not include one of the
+ * <code>public</code>, <code>private</code>, or <code>protected</code> flags.
+ *
+ * @param flags the flags
+ * @return <code>true</code> if no visibility flag is set
+ * @since 3.2
+ */
+ public static boolean isPackageDefault(int flags) {
+ return (flags & (AccPublic | AccPrivate | AccProtected)) == 0;
+ }
+ /**
* Returns whether the given integer includes the <code>private</code> modifier.
*
* @param flags the flags
@@ -232,6 +243,16 @@
return (flags & AccStatic) != 0;
}
/**
+ * Returns whether the given integer includes the <code>super</code> modifier.
+ *
+ * @param flags the flags
+ * @return <code>true</code> if the <code>super</code> modifier is included
+ * @since 3.2
+ */
+ public static boolean isSuper(int flags) {
+ return (flags & AccSuper) != 0;
+ }
+ /**
* Returns whether the given integer includes the <code>strictfp</code> modifier.
*
* @param flags the flags
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IAccessRule.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IAccessRule.java
index 9079343..ee952bb 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IAccessRule.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IAccessRule.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -70,6 +70,20 @@
int K_DISCOURAGED = 2;
/**
+ * <p>Flag indicating that whether a type matching this rule should be ignored iff a type with
+ * the same qualified name can be found on a later classpath entry with a better
+ * accessibility.</p>
+ * <p>E.g. if a type p.X matches a rule K_NON_ACCESSIBLE | IGNORE_IF_BETTER
+ * on a library entry 'lib1' and another type p.X also matches a rule
+ * K_DISCOURAGED on library entry 'lib2' ('lib2' being after 'lib1' on the
+ * classpath), then p.X from 'lib2' will be used and reported as
+ * discouraged.</p>
+ *
+ * @since 3.2
+ */
+ int IGNORE_IF_BETTER = 0x100;
+
+ /**
* Returns the file pattern for this access rule.
*
* @return the file pattern for this access rule
@@ -83,5 +97,22 @@
* @return the kind of this access rule
*/
int getKind();
+
+ /**
+ * <p>Returns whether a type matching this rule should be ignored iff a type with
+ * the same qualified name can be found on a later classpath entry with a better
+ * accessibility.</p>
+ * <p>E.g. if a type p.X matches a rule K_NON_ACCESSIBLE | IGNORE_IF_BETTER
+ * on a library entry 'lib1' and another type p.X also matches a rule
+ * K_DISCOURAGED on library entry 'lib2' ('lib2' being after 'lib1' on the
+ * classpath), then p.X from 'lib2' will be used and reported as
+ * discouraged.</p>
+ *
+ * @return whether a type matching this rule should be ignored iff a type
+ * with the same qualified name can be found on a later classpath
+ * entry with a better accessibility
+ * @since 3.2
+ */
+ boolean ignoreIfBetter();
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IBuffer.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IBuffer.java
index 79b59af..c50d704 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IBuffer.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IBuffer.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IBufferChangedListener.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IBufferChangedListener.java
index b790380..2db385b 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IBufferChangedListener.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IBufferChangedListener.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IBufferFactory.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IBufferFactory.java
index 171c64e..cb93d1a 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IBufferFactory.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IBufferFactory.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -16,7 +16,7 @@
* This interface may be implemented by clients.
* </p>
* @since 2.0
- * @deprecated Use <code>WorkingCopyOwner</code> instead
+ * @deprecated Use {@link WorkingCopyOwner} instead
*/
public interface IBufferFactory {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClassFile.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClassFile.java
index 6d06467..b9bd115 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClassFile.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClassFile.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -13,10 +13,10 @@
import org.eclipse.core.runtime.IProgressMonitor;
/**
- * Represents an entire binary type (single <code>.class</code> file).
+ * Represents an entire binary type (single <code>.class</code> file).
* A class file has a single child of type <code>IType</code>.
* Class file elements need to be opened before they can be navigated.
- * If a class file cannot be parsed, its structure remains unknown. Use
+ * If a class file cannot be parsed, its structure remains unknown. Use
* <code>IJavaElement.isStructureKnown</code> to determine whether this is the
* case.
* <p>
@@ -31,57 +31,75 @@
*
* @see IPackageFragmentRoot#attachSource(org.eclipse.core.runtime.IPath, org.eclipse.core.runtime.IPath, IProgressMonitor)
*/
-
-public interface IClassFile extends IJavaElement, IParent, IOpenable, ISourceReference, ICodeAssist {
+
+public interface IClassFile extends ITypeRoot {
+
/**
- * Returns the smallest element within this class file that
- * includes the given source position (a method, field, etc.), or
- * <code>null</code> if there is no element other than the class file
- * itself at the given position, or if the given position is not
- * within the source range of this class file.
+ * Changes this class file handle into a working copy. A new {@link IBuffer} is
+ * created using the given owner. Uses the primary owner if <code>null</code> is
+ * specified.
+ * <p>
+ * When switching to working copy mode, problems are reported to the given
+ * {@link IProblemRequestor}. Note that once in working copy mode, the given
+ * {@link IProblemRequestor} is ignored. Only the original {@link IProblemRequestor}
+ * is used to report subsequent problems.
+ * </p>
+ * <p>
+ * Once in working copy mode, changes to this working copy or its children are done in memory.
+ * Only the new buffer is affected.
+ * </p>
+ * <p>
+ * Using {@link ICompilationUnit#commitWorkingCopy(boolean, IProgressMonitor)} on the working copy
+ * will throw a <code>JavaModelException</code> as a class file is implicetly read-only.
+ * </p>
+ * <p>
+ * If this class file was already in working copy mode, an internal counter is incremented and no
+ * other action is taken on this working copy. To bring this working copy back into the original mode
+ * (where it reflects the underlying resource), {@link ICompilationUnit#discardWorkingCopy} must be call as many
+ * times as {@link #becomeWorkingCopy(IProblemRequestor, WorkingCopyOwner, IProgressMonitor)}.
+ * </p>
+ * <p>
+ * The primary compilation unit of a class file's working copy does not exist if the class file is not
+ * in working copy mode (<code>classFileWorkingCopy.getPrimary().exists() == false</code>).
+ * </p>
+ * <p>
+ * The resource of a class file's working copy is <code>null</code> if the class file is in an external jar file.
+ * </p>
*
- * @param position a source position inside the class file
- * @return the innermost Java element enclosing a given source position or <code>null</code>
- * if none (excluding the class file).
+ * @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.
+ * @param owner the given {@link WorkingCopyOwner}, or <code>null</code> for the primary owner
+ * @param monitor a progress monitor used to report progress while opening this compilation unit
+ * or <code>null</code> if no progress should be reported
+ * @return a working copy for this class file
+ * @throws JavaModelException if this compilation unit could not become a working copy.
+ * @see ICompilationUnit#discardWorkingCopy()
+ * @since 3.2
+ * @deprecated Use {@link ITypeRoot#getWorkingCopy(WorkingCopyOwner, IProgressMonitor)} instead.
+ * Note that if this deprecated method is used, problems will be reported to the given problem requestor
+ * as well as the problem requestor returned by the working copy owner (if not null).
+ */
+ICompilationUnit becomeWorkingCopy(IProblemRequestor problemRequestor, WorkingCopyOwner owner, IProgressMonitor monitor) throws JavaModelException;
+/**
+ * Returns the bytes contained in this class file.
+ *
+ * @return the bytes contained in this class file
*
* @exception JavaModelException if this element does not exist or if an
* exception occurs while accessing its corresponding resource
+ * @since 3.3
*/
-IJavaElement getElementAt(int position) throws JavaModelException;
+byte[] getBytes() throws JavaModelException;
/**
* Returns the type contained in this class file.
+ * This is a handle-only method. The type may or may not exist.
*
* @return the type contained in this class file
- *
- * @exception JavaModelException if this element does not exist or if an
- * exception occurs while accessing its corresponding resource
*/
-IType getType() throws JavaModelException;
+IType getType();
/**
- * Returns a working copy on the source associated with this class file using the given
- * owner to create the buffer, or <code>null</code> if there is no source associated
- * with the class file.
- * <p>
- * The buffer will be automatically initialized with the source of the class file
- * upon creation.
- * <p>
- * The only valid operations on this working copy are <code>getBuffer()</code> or <code>getPrimary()</code>.
- *
- * @param owner the owner that creates a buffer that is used to get the content of the working copy
- * or <code>null</code> if the primary owner should be used
- * @param monitor a progress monitor used to report progress while opening this compilation unit
- * or <code>null</code> if no progress should be reported
- * @return a a working copy on the source associated with this class file
- * @exception JavaModelException if the source of this class file can
- * not be determined. Reasons include:
- * <ul>
- * <li> This class file does not exist (ELEMENT_DOES_NOT_EXIST)</li>
- * </ul>
- * @since 3.0
- */
-ICompilationUnit getWorkingCopy(WorkingCopyOwner owner, IProgressMonitor monitor) throws JavaModelException;
-/**
- * Returns a working copy on the source associated with this class file using the given
+ * Returns a working copy on the source associated with this class file using the given
* factory to create the buffer, or <code>null</code> if there is no source associated
* with the class file.
* <p>
@@ -91,7 +109,7 @@
* The only valid operations on this working copy are <code>getBuffer()</code> or <code>getOriginalElement</code>.
*
* @param monitor a progress monitor used to report progress while opening this compilation unit
- * or <code>null</code> if no progress should be reported
+ * 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
* @return a a working copy on the source associated with this class file
@@ -101,9 +119,10 @@
* <li> This class file does not exist (ELEMENT_DOES_NOT_EXIST)</li>
* </ul>
* @since 2.0
- * @deprecated Use getWorkingCopy(WorkingCopyOwner, IProgressMonitor) instead
+ * @deprecated Use {@link ITypeRoot#getWorkingCopy(WorkingCopyOwner, IProgressMonitor)} instead
*/
-IJavaElement getWorkingCopy(IProgressMonitor monitor, IBufferFactory factory) throws JavaModelException;/**
+IJavaElement getWorkingCopy(IProgressMonitor monitor, IBufferFactory factory) throws JavaModelException;
+/**
* Returns whether this type represents a class. This is not guaranteed to be
* instantaneous, as it may require parsing the underlying file.
*
@@ -115,7 +134,7 @@
boolean isClass() throws JavaModelException;
/**
* Returns whether this type represents an interface. This is not guaranteed to
- * be instantaneous, as it may require parsing the underlying file.
+ * be instantaneous, as it may require parsing the underlying file.
*
* @return <code>true</code> if the class file represents an interface.
*
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathAttribute.java
index 74625ab..0e976e1 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathAttribute.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005 IBM Corporation and others.
+ * Copyright (c) 2005, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -13,6 +13,9 @@
/**
* A classpath attribute defines a name/value pair that can be persisted with a classpath entry. Such an attribute
* can be created using the factory method {@link JavaCore#newClasspathAttribute(String, String) newClasspathAttribute(String name, String value)}.
+ * <p>
+ * This interface is not intended to be implemented by clients.
+ * </p>
*
* @see JavaCore#newContainerEntry(
* org.eclipse.core.runtime.IPath containerPath,
@@ -57,6 +60,18 @@
String JAVADOC_LOCATION_ATTRIBUTE_NAME = "javadoc_location"; //$NON-NLS-1$
/**
+ * Constant for the name of the optional attribute. The possible values
+ * for this attribute are <code>"true"</code> or <code>"false"</code>.
+ * When not present, <code>"false"</code> is assumed.
+ * If the value of this attribute is <code>"true"</code>, the classpath entry
+ * is optional. If the underlying resource or jar file doesn't exist, no error
+ * is reported and the classpath entry is ignored.
+ *
+ * @since 3.2
+ */
+ String OPTIONAL = "optional"; //$NON-NLS-1$
+
+ /**
* Returns the name of this classpath attribute.
*
* @return the name of this classpath attribute.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathContainer.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathContainer.java
index 28b5b44..d4e0072 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathContainer.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathContainer.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathEntry.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathEntry.java
index 7e9ff1a..6948c09 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathEntry.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathEntry.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -15,21 +15,23 @@
/**
* An entry on a Java project classpath identifying one or more package fragment
* roots. A classpath entry has a content kind (either source,
- * <code>K_SOURCE</code>, or binary, <code>K_BINARY</code>), which is inherited
+ * {@link IPackageFragmentRoot#K_SOURCE}, or binary, {@link IPackageFragmentRoot#K_BINARY}), which is inherited
* by each package fragment root and package fragment associated with the entry.
* <p>
* A classpath entry can refer to any of the following:<ul>
*
* <li>Source code in the current project. In this case, the entry identifies a
* root folder in the current project containing package fragments and
- * <code>.java</code> source files. The root folder itself represents a default
- * package, subfolders represent package fragments, and <code>.java</code> files
+ * source files with one of the {@link JavaCore#getJavaLikeExtensions()
+ * Java-like extensions}. The root folder itself represents a default
+ * package, subfolders represent package fragments, and files with a
+ * Java-like extension (e.g. <code>.java</code> files)
* represent compilation units. All compilation units will be compiled when
* the project is built. The classpath entry must specify the
* absolute path to the root folder. Entries of this kind are
- * associated with the <code>CPE_SOURCE</code> constant.
+ * associated with the {@link #CPE_SOURCE} constant.
* Source classpath entries can carry inclusion and exclusion patterns for
- * selecting which <code>.java</code> source files appear as compilation
+ * selecting which source files appear as compilation
* units and get compiled when the project is built.
* </li>
*
@@ -38,7 +40,7 @@
* package fragments and <code>.class</code> files. The classpath entry
* must specify the absolute path to the JAR (or root folder), and in case it refers
* to an external JAR, then there is no associated resource in the workbench. Entries
- * of this kind are associated with the <code>CPE_LIBRARY</code> constant.</li>
+ * of this kind are associated with the {@link #CPE_LIBRARY} constant.</li>
*
* <li>A required project. In this case the entry identifies another project in
* the workspace. The required project is used as a binary library when compiling
@@ -49,50 +51,50 @@
* is performed against a required project's source code, and compilation is
* performed against a required project's last built state. The
* classpath entry must specify the absolute path to the
- * project. Entries of this kind are associated with the <code>CPE_PROJECT</code>
+ * project. Entries of this kind are associated with the {@link #CPE_PROJECT}
* constant.
* Note: referencing a required project with a classpath entry refers to the source
* code or associated <code>.class</code> files located in its output location.
* It will also automatically include any other libraries or projects that the required project's classpath
* refers to, iff the corresponding classpath entries are tagged as being exported
- * (<code>IClasspathEntry#isExported</code>).
+ * ({@link IClasspathEntry#isExported}).
* Unless exporting some classpath entries, classpaths are not chained by default -
* each project must specify its own classpath in its entirety.</li>
*
* <li> A path beginning in a classpath variable defined globally to the workspace.
- * Entries of this kind are associated with the <code>CPE_VARIABLE</code> constant.
- * Classpath variables are created using <code>JavaCore#setClasspathVariable</code>,
+ * Entries of this kind are associated with the {@link #CPE_VARIABLE} constant.
+ * Classpath variables are created using {@link JavaCore#setClasspathVariable(String, IPath, org.eclipse.core.runtime.IProgressMonitor)},
* and gets resolved, to either a project or library entry, using
- * <code>JavaCore#getResolvedClasspathVariable</code>.
- * It is also possible to register an automatic initializer (<code>ClasspathVariableInitializer</code>),
+ * {@link JavaCore#getResolvedClasspathEntry(IClasspathEntry)}.
+ * It is also possible to register an automatic initializer ({@link ClasspathVariableInitializer}),
* which will be invoked through the extension point "org.eclipse.jdt.core.classpathVariableInitializer".
* After resolution, a classpath variable entry may either correspond to a project or a library entry. </li>
*
* <li> A named classpath container identified by its container path.
* A classpath container provides a way to indirectly reference a set of classpath entries through
- * a classpath entry of kind <code>CPE_CONTAINER</code>. Typically, a classpath container can
+ * a classpath entry of kind {@link #CPE_CONTAINER}. Typically, a classpath container can
* be used to describe a complex library composed of multiple JARs, projects or classpath variables,
* considering also that containers can be mapped differently on each project. Several projects can
* reference the same generic container path, but have each of them actually bound to a different
* container object.
* The container path is a formed by a first ID segment followed with extra segments,
* which can be used as additional hints for resolving this container reference. If no container was ever
- * recorded for this container path onto this project (using <code>setClasspathContainer</code>,
- * then a <code>ClasspathContainerInitializer</code> will be activated if any was registered for this
+ * recorded for this container path onto this project (using {@link JavaCore#setClasspathContainer},
+ * then a {@link ClasspathContainerInitializer} will be activated if any was registered for this
* container ID onto the extension point "org.eclipse.jdt.core.classpathContainerInitializer".
- * A classpath container entry can be resolved explicitly using <code>JavaCore#getClasspathContainer</code>
+ * A classpath container entry can be resolved explicitly using {@link JavaCore#getClasspathContainer}
* and the resulting container entries can contain any non-container entry. In particular, it may contain variable
* entries, which in turn needs to be resolved before being directly used.
* <br> Also note that the container resolution APIs include an IJavaProject argument, so as to allow the same
* container path to be interpreted in different ways for different projects. </li>
* </ul>
* </p>
- * The result of <code>IJavaProject#getResolvedClasspath</code> will have all entries of type
- * <code>CPE_VARIABLE</code> and <code>CPE_CONTAINER</code> resolved to a set of
- * <code>CPE_SOURCE</code>, <code>CPE_LIBRARY</code> or <code>CPE_PROJECT</code>
+ * The result of {@link IJavaProject#getResolvedClasspath} will have all entries of type
+ * {@link #CPE_VARIABLE} and {@link #CPE_CONTAINER} resolved to a set of
+ * {@link #CPE_SOURCE}, {@link #CPE_LIBRARY} or {@link #CPE_PROJECT}
* classpath entries.
* <p>
- * Any classpath entry other than a source folder (kind <code>CPE_SOURCE</code>) can
+ * Any classpath entry other than a source folder (kind {@link #CPE_SOURCE}) can
* be marked as being exported. Exported entries are automatically contributed to
* dependent projects, along with the project's default output folder, which is
* implicitly exported, and any auxiliary output folders specified on source
@@ -100,7 +102,7 @@
* followed by the any exported entries.
* <p>
* This interface is not intended to be implemented by clients.
- * Classpath entries can be created via methods on <code>JavaCore</code>.
+ * Classpath entries can be created via methods on {@link JavaCore}.
* </p>
*
* @see JavaCore#newLibraryEntry(org.eclipse.core.runtime.IPath, org.eclipse.core.runtime.IPath, org.eclipse.core.runtime.IPath)
@@ -168,11 +170,11 @@
* Returns the kind of files found in the package fragments identified by this
* classpath entry.
*
- * @return <code>IPackageFragmentRoot.K_SOURCE</code> for files containing
- * source code, and <code>IPackageFragmentRoot.K_BINARY</code> for binary
+ * @return {@link IPackageFragmentRoot#K_SOURCE} for files containing
+ * source code, and {@link IPackageFragmentRoot#K_BINARY} for binary
* class files.
- * There is no specified value for an entry denoting a variable (<code>CPE_VARIABLE</code>)
- * or a classpath container (<code>CPE_CONTAINER</code>).
+ * There is no specified value for an entry denoting a variable ({@link #CPE_VARIABLE})
+ * or a classpath container ({@link #CPE_CONTAINER}).
*/
int getContentKind();
@@ -181,16 +183,16 @@
*
* @return one of:
* <ul>
- * <li><code>CPE_SOURCE</code> - this entry describes a source root in
+ * <li>{@link #CPE_SOURCE} - this entry describes a source root in
its project
- * <li><code>CPE_LIBRARY</code> - this entry describes a folder or JAR
+ * <li>{@link #CPE_LIBRARY} - this entry describes a folder or JAR
containing binaries
- * <li><code>CPE_PROJECT</code> - this entry describes another project
+ * <li>{@link #CPE_PROJECT} - this entry describes another project
*
- * <li><code>CPE_VARIABLE</code> - this entry describes a project or library
+ * <li>{@link #CPE_VARIABLE} - this entry describes a project or library
* indirectly via a classpath variable in the first segment of the path
* *
- * <li><code>CPE_CONTAINER</code> - this entry describes set of entries
+ * <li>{@link #CPE_CONTAINER} - this entry describes set of entries
* referenced indirectly via a classpath container
* </ul>
*/
@@ -237,13 +239,13 @@
* Combinations of *'s and ?'s are allowed.
* </p>
* <p>
- * The special pattern '**' matches zero or more segments. In a source enry,
+ * The special pattern '**' matches zero or more segments. In a source entry,
* a path like <code>tests/</code> that ends in a trailing separator is interpreted
* as <code>tests/**</code>, and would match everything under
* the folder named <code>tests</code>.
* </p>
* <p>
- * Example patterns in source entries:
+ * Example patterns in source entries (assuming that "java" is the only {@link JavaCore#getJavaLikeExtensions() Java-like extension}):
* <ul>
* <li>
* <code>tests/**</code> (or simply <code>tests/</code>)
@@ -342,11 +344,11 @@
/**
* Returns the full path to the specific location where the builder writes
* <code>.class</code> files generated for this source entry
- * (entry kind <code>CPE_SOURCE</code>).
+ * (entry kind {@link #CPE_SOURCE}).
* <p>
* Source entries can optionally be associated with a specific output location.
* If none is provided, the source entry will be implicitly associated with its project
- * default output location (see <code>IJavaProject#getOutputLocation</code>).
+ * default output location (see {@link IJavaProject#getOutputLocation}).
* </p><p>
* NOTE: A specific output location cannot coincidate with another source/library entry.
* </p>
@@ -362,24 +364,24 @@
* Returns the path of this classpath entry.
*
* The meaning of the path of a classpath entry depends on its entry kind:<ul>
- * <li>Source code in the current project (<code>CPE_SOURCE</code>) -
+ * <li>Source code in the current project ({@link #CPE_SOURCE}) -
* The path associated with this entry is the absolute path to the root folder. </li>
- * <li>A binary library in the current project (<code>CPE_LIBRARY</code>) - the path
+ * <li>A binary library in the current project ({@link #CPE_LIBRARY}) - the path
* associated with this entry is the absolute path to the JAR (or root folder), and
* in case it refers to an external JAR, then there is no associated resource in
* the workbench.
- * <li>A required project (<code>CPE_PROJECT</code>) - the path of the entry denotes the
+ * <li>A required project ({@link #CPE_PROJECT}) - the path of the entry denotes the
* path to the corresponding project resource.</li>
- * <li>A variable entry (<code>CPE_VARIABLE</code>) - the first segment of the path
+ * <li>A variable entry ({@link #CPE_VARIABLE}) - the first segment of the path
* is the name of a classpath variable. If this classpath variable
- * is bound to the path <it>P</it>, the path of the corresponding classpath entry
- * is computed by appending to <it>P</it> the segments of the returned
+ * is bound to the path <i>P</i>, the path of the corresponding classpath entry
+ * is computed by appending to <i>P</i> the segments of the returned
* path without the variable.</li>
- * <li> A container entry (<code>CPE_CONTAINER</code>) - the path of the entry
+ * <li> A container entry ({@link #CPE_CONTAINER}) - the path of the entry
* is the name of the classpath container, which can be bound indirectly to a set of classpath
* entries after resolution. The containerPath is a formed by a first ID segment followed with
* extra segments that can be used as additional hints for resolving this container
- * reference (also see <code>IClasspathContainer</code>).
+ * reference (also see {@link IClasspathContainer}).
* </li>
* </ul>
*
@@ -408,7 +410,7 @@
* Returns the path within the source archive or folder where package fragments
* are located. An empty path indicates that packages are located at
* the root of the source archive or folder. Returns a non-<code>null</code> value
- * if and only if <code>getSourceAttachmentPath</code> returns
+ * if and only if {@link #getSourceAttachmentPath} returns
* a non-<code>null</code> value.
*
* @return the path within the source archive or folder, or <code>null</code> if
@@ -419,7 +421,7 @@
/**
* Returns whether this entry is exported to dependent projects.
* Always returns <code>false</code> for source entries (kind
- * <code>CPE_SOURCE</code>), which cannot be exported.
+ * {@link #CPE_SOURCE}), which cannot be exported.
*
* @return <code>true</code> if exported, and <code>false</code> otherwise
* @since 2.0
@@ -429,7 +431,7 @@
/**
* This is a helper method, which returns the resolved classpath entry denoted
* by an entry (if it is a variable entry). It is obtained by resolving the variable
- * reference in the first segment. Returns <node>null</code> if unable to resolve using
+ * reference in the first segment. Returns <code>null</code> if unable to resolve using
* the following algorithm:
* <ul>
* <li> if variable segment cannot be resolved, returns <code>null</code></li>
@@ -445,7 +447,7 @@
* <p>
* Note that this deprecated API doesn't handle CPE_CONTAINER entries.
*
- * @deprecated - use JavaCore.getResolvedClasspathEntry(...)
+ * @deprecated Use {@link JavaCore#getResolvedClasspathEntry(IClasspathEntry)} instead
*/
IClasspathEntry getResolvedEntry();
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICodeAssist.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICodeAssist.java
index 254e3a0..11410dd 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICodeAssist.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICodeAssist.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -144,15 +144,20 @@
throws JavaModelException;
/**
- * Returns the Java elements correspondiing to the given selected text in this compilation unit.
+ * Returns the Java elements corresponding to the given selected text in this compilation unit.
* The <code>offset</code> is the 0-based index of the first selected character.
* The <code>length</code> is the number of selected characters.
+ * <p>
+ * Note that if the <code>length</code> is 0 and the <code>offset</code> is inside an identifier
+ * or the index just after an identifier then this identifier is considered as the selection.
+ * </p>
*
* @param offset the given offset position
* @param length the number of selected characters
- * @return the Java elements correspondiing to the given selected text
+ * @return the Java elements corresponding to the given selected text
*
* @exception JavaModelException if code resolve could not be performed. Reasons include:
+ * <ul>
* <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)
@@ -161,13 +166,17 @@
*/
IJavaElement[] codeSelect(int offset, int length) throws JavaModelException;
/**
- * Returns the Java elements correspondiing to the given selected text in this compilation unit.
+ * Returns the Java elements corresponding to the given selected text in this compilation unit.
* The <code>offset</code> is the 0-based index of the first selected character.
* The <code>length</code> is the number of selected characters.
* It considers types in the working copies with the given owner first. In other words,
* the owner's working copies will take precedence over their original compilation units
* in the workspace.
* <p>
+ * Note that if the <code>length</code> is 0 and the <code>offset</code> is inside an identifier
+ * or the index just after an identifier then this identifier is considered as the selection.
+ * </p>
+ * <p>
* Note that if a working copy is empty, it will be as if the original compilation
* unit had been deleted.
* </p>
@@ -175,9 +184,10 @@
* @param offset the given offset position
* @param length the number of selected characters
* @param owner the owner of working copies that take precedence over their original compilation units
- * @return the Java elements correspondiing to the given selected text
+ * @return the Java elements corresponding to the given selected text
*
* @exception JavaModelException if code resolve could not be performed. Reasons include:
+ * <ul>
* <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)
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICodeCompletionRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICodeCompletionRequestor.java
index 86ef806..90bb0e6 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICodeCompletionRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICodeCompletionRequestor.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICodeFormatter.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICodeFormatter.java
index e44e348..a590fc1 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICodeFormatter.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICodeFormatter.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -18,7 +18,7 @@
* @see ToolFactory#createCodeFormatter()
* @see ToolFactory#createDefaultCodeFormatter(java.util.Map options)
* @since 2.0
- * @deprecated - should use org.eclipse.jdt.core.formatter.CodeFormatter instead (note: options have changed)
+ * @deprecated Use {@link org.eclipse.jdt.core.formatter.CodeFormatter} instead (note: options have changed)
*/
public interface ICodeFormatter {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICompilationUnit.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICompilationUnit.java
index e714fac..421bc41 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICompilationUnit.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICompilationUnit.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -12,24 +12,27 @@
package org.eclipse.jdt.core;
import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.IBinding;
/**
- * Represents an entire Java compilation unit (<code>.java</code> source file).
+ * Represents an entire Java compilation unit (source file with one of the
+ * {@link JavaCore#getJavaLikeExtensions() Java-like extensions}).
* Compilation unit elements need to be opened before they can be navigated or manipulated.
* The children are of type {@link IPackageDeclaration},
* {@link IImportContainer}, and {@link IType},
* 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 {@link IJavaElement#isStructureKnown} to determine whether this is
+ * If a source file cannot be parsed, its structure remains unknown.
+ * Use {@link IJavaElement#isStructureKnown} 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 {
+public interface ICompilationUnit extends ITypeRoot, IWorkingCopy, ISourceManipulation {
/**
* Constant indicating that a reconcile operation should not return an AST.
* @since 3.0
@@ -37,11 +40,33 @@
public static final int NO_AST = 0;
/**
+ * Constant indicating that a reconcile operation should recompute the problems
+ * even if the source hasn't changed.
+ * @since 3.3
+ */
+public static final int FORCE_PROBLEM_DETECTION = 0x01;
+
+/**
+ * Constant indicating that a reconcile operation should enable the statements recovery.
+ * @see ASTParser#setStatementsRecovery(boolean)
+ * @since 3.3
+ */
+public static final int ENABLE_STATEMENTS_RECOVERY = 0x02;
+
+/**
+ * Constant indicating that a reconcile operation should enable the bindings recovery
+ * @see ASTParser#setBindingsRecovery(boolean)
+ * @see IBinding#isRecovered()
+ * @since 3.3
+ */
+public static final int ENABLE_BINDINGS_RECOVERY = 0x04;
+
+/**
* Changes this compilation unit handle into a working copy. A new {@link IBuffer} is
- * created using this compilation unit handle's owner. Uses the primary owner is none was
+ * created using this compilation unit handle's owner. Uses the primary owner if none was
* specified when this compilation unit handle was created.
* <p>
- * When switching to working copy mode, problems are reported to given
+ * When switching to working copy mode, problems are reported to given
* {@link IProblemRequestor}. Note that once in working copy mode, the given
* {@link IProblemRequestor} is ignored. Only the original {@link IProblemRequestor}
* is used to report subsequent problems.
@@ -53,22 +78,51 @@
* </p>
* <p>
* If this compilation unit was already in working copy mode, an internal counter is incremented and no
- * other action is taken on this compilation unit. To bring this compilation unit back into the original mode
- * (where it reflects the underlying resource), {@link #discardWorkingCopy} must be call as many
+ * other action is taken on this compilation unit. To bring this compilation unit back into the original mode
+ * (where it reflects the underlying resource), {@link #discardWorkingCopy} must be call as many
* times as {@link #becomeWorkingCopy(IProblemRequestor, IProgressMonitor)}.
* </p>
- *
+ *
* @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.
* @param monitor a progress monitor used to report progress while opening this compilation unit
- * or <code>null</code> if no progress should be reported
+ * or <code>null</code> if no progress should be reported
* @throws JavaModelException if this compilation unit could not become a working copy.
* @see #discardWorkingCopy()
* @since 3.0
+ *
+ * @deprecated Use {@link #becomeWorkingCopy(IProgressMonitor)} instead.
+ * Note that if this deprecated method is used, problems will be reported to the given problem requestor
+ * as well as the problem requestor returned by the working copy owner (if not null).
*/
void becomeWorkingCopy(IProblemRequestor problemRequestor, IProgressMonitor monitor) throws JavaModelException;
/**
+ * Changes this compilation unit handle into a working copy. A new {@link IBuffer} is
+ * created using this compilation unit handle's owner. Uses the primary owner if none was
+ * specified when this compilation unit handle was created.
+ * <p>
+ * When switching to working copy mode, problems are reported to the {@link IProblemRequestor
+ * problem requestor} of the {@link WorkingCopyOwner working copy owner}.
+ * </p><p>
+ * Once in working copy mode, changes to this compilation unit or its children are done in memory.
+ * Only the new buffer is affected. Using {@link #commitWorkingCopy(boolean, IProgressMonitor)}
+ * will bring the underlying resource in sync with this compilation unit.
+ * </p><p>
+ * If this compilation unit was already in working copy mode, an internal counter is incremented and no
+ * other action is taken on this compilation unit. To bring this compilation unit back into the original mode
+ * (where it reflects the underlying resource), {@link #discardWorkingCopy} must be call as many
+ * times as {@link #becomeWorkingCopy(IProblemRequestor, IProgressMonitor)}.
+ * </p>
+ *
+ * @param monitor a progress monitor used to report progress while opening this compilation unit
+ * or <code>null</code> if no progress should be reported
+ * @throws JavaModelException if this compilation unit could not become a working copy.
+ * @see #discardWorkingCopy()
+ * @since 3.3
+ */
+void becomeWorkingCopy(IProgressMonitor monitor) throws JavaModelException;
+/**
* Commits the contents of this working copy to its underlying resource.
*
* <p>It is possible that the contents of the original resource have changed
@@ -99,7 +153,7 @@
void commitWorkingCopy(boolean force, IProgressMonitor monitor) throws JavaModelException;
/**
* Creates and returns an non-static import declaration in this compilation unit
- * with the given name. This method is equivalent to
+ * with the given name. This method is equivalent to
* <code>createImport(name, Flags.AccDefault, sibling, monitor)</code>.
*
* @param name the name of the import declaration to add as defined by JLS2 7.5. (For example: <code>"java.io.File"</code> or
@@ -182,7 +236,7 @@
* <li> The name is not a valid package name (INVALID_NAME)
* </ul>
*/
- IPackageDeclaration createPackageDeclaration(String name, IProgressMonitor monitor) throws JavaModelException;
+ 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
@@ -222,17 +276,18 @@
* This has no effect if this compilation unit was not in working copy mode.
* </p>
* <p>
- * If {@link #becomeWorkingCopy} was called several times on this
- * compilation unit, {@link #discardWorkingCopy} must be called as
- * many times before it switches back to the original mode.
+ * If {@link #becomeWorkingCopy(IProgressMonitor)} method was called several
+ * times on this compilation unit, {@link #discardWorkingCopy()} must be called
+ * as many times before it switches back to the original mode. Same as
+ * for method {@link #getWorkingCopy(IProgressMonitor)}.
* </p>
- *
+ *
* @throws JavaModelException if this working copy could not return in its original mode.
* @see #becomeWorkingCopy(IProblemRequestor, IProgressMonitor)
* @since 3.0
*/
void discardWorkingCopy() throws JavaModelException;
-/**
+/**
* Finds the elements in this compilation unit that correspond to
* the given element.
* An element A corresponds to an element B if:
@@ -246,27 +301,19 @@
* </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 3.0
+ * @since 3.0
*/
IJavaElement[] findElements(IJavaElement element);
/**
- * Finds the primary type of this compilation unit (that is, 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 3.0
- */
-IType findPrimaryType();
-/**
- * Finds the working copy for this compilation unit, given a {@link WorkingCopyOwner}.
+ * Finds the working copy for this compilation unit, given a {@link WorkingCopyOwner}.
* If no working copy has been created for this compilation unit associated with this
* working copy owner, returns <code>null</code>.
* <p>
- * Users of this method must not destroy the resulting working copy.
- *
+ * Users of this method must not destroy the resulting working copy.
+ *
* @param owner the given {@link WorkingCopyOwner}
* @return the found working copy for this compilation unit, <code>null</code> if none
* @see WorkingCopyOwner
@@ -275,7 +322,7 @@
ICompilationUnit findWorkingCopy(WorkingCopyOwner owner);
/**
* Returns all types declared in this compilation unit in the order
- * in which they appear in the source.
+ * 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).
*
@@ -285,26 +332,12 @@
*/
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).
- * @throws 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>
+ * @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.
*/
@@ -312,9 +345,9 @@
/**
* 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
+ * may not exist. The import container can used to access the
* imports.
- * @return a handle onto the corresponding import container. The
+ * @return a handle onto the corresponding import container. The
* import contain may or may not exist.
*/
IImportContainer getImportContainer();
@@ -336,7 +369,7 @@
* <p>
* Note that the returned primary compilation unit can be in working copy mode.
* </p>
- *
+ *
* @return the primary compilation unit this working copy was created from,
* or this compilation unit if it is primary
* @since 3.0
@@ -345,7 +378,7 @@
/**
* Returns the working copy owner of this working copy.
* Returns null if it is not a working copy or if it has no owner.
- *
+ *
* @return WorkingCopyOwner the owner of this working copy or <code>null</code>
* @since 3.0
*/
@@ -377,7 +410,7 @@
*
* @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)
+ * @see JavaConventions#validateCompilationUnitName(String name, String sourceLevel, String complianceLevel)
*/
IType getType(String name);
/**
@@ -390,27 +423,27 @@
*/
IType[] getTypes() throws JavaModelException;
/**
- * Returns a new working copy of this compilation unit if it is a primary compilation unit,
+ * Returns a new working copy of this compilation unit if it is a primary compilation unit,
* or this compilation unit if it is already a non-primary working copy.
* <p>
- * Note: if intending to share a working copy amongst several clients, then
- * {@link #getWorkingCopy(WorkingCopyOwner, IProblemRequestor, IProgressMonitor)}
+ * Note: if intending to share a working copy amongst several clients, then
+ * {@link #getWorkingCopy(WorkingCopyOwner, IProblemRequestor, IProgressMonitor)}
* should be used instead.
* </p><p>
- * When the working copy instance is created, an ADDED IJavaElementDelta is
+ * When the working copy instance is created, an ADDED IJavaElementDelta is
* reported on this working copy.
* </p><p>
- * Once done with the working copy, users of this method must discard it using
+ * Once done with the working copy, users of this method must discard it using
* {@link #discardWorkingCopy()}.
* </p><p>
* Since 2.1, a working copy can be created on a not-yet existing compilation
* unit. In particular, such a working copy can then be committed in order to create
* the corresponding compilation unit.
* </p>
-* @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 monitor a progress monitor used to report progress while opening this compilation unit
+ * or <code>null</code> if no progress should be reported
* @throws JavaModelException if the contents of this element can
- * not be determined.
+ * not be determined.
* @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
* @since 3.0
@@ -420,11 +453,11 @@
* Returns a shared working copy on this compilation unit using the given working copy owner to create
* the buffer, or this compilation unit if it is already a non-primary 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 working copy owner (that is, as defined by {@link Object#equals}).
+ * original compilation unit AND was using the same working copy owner (that is, as defined by {@link Object#equals}).
* <p>
* The life time of a shared working copy is as follows:
* <ul>
- * <li>The first call to {@link #getWorkingCopy(WorkingCopyOwner, IProblemRequestor, IProgressMonitor)}
+ * <li>The first call to {@link #getWorkingCopy(WorkingCopyOwner, IProblemRequestor, IProgressMonitor)}
* creates a new working copy for this element</li>
* <li>Subsequent calls increment an internal counter.</li>
* <li>A call to {@link #discardWorkingCopy()} decrements the internal counter.</li>
@@ -432,7 +465,7 @@
* </ul>
* So users of this method must discard exactly once the working copy.
* <p>
- * Note that the working copy owner will be used for the life time of this working copy, that is if the
+ * Note that the working copy owner will be used for the life time of this working copy, that is if the
* working copy is closed then reopened, this owner will be used.
* The buffer will be automatically initialized with the original's compilation unit content
* upon creation.
@@ -444,32 +477,35 @@
* unit. In particular, such a working copy can then be committed in order to create
* the corresponding compilation unit.
* </p>
- * @param owner the working copy owner that creates a buffer that is used to get the content
+ * @param owner the working copy owner that creates a buffer that is used to get the content
* of the working copy
* @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.
* @param monitor a progress monitor used to report progress while opening this compilation unit
- * or <code>null</code> if no progress should be reported
+ * or <code>null</code> if no progress should be reported
* @throws JavaModelException if the contents of this element can
- * not be determined.
+ * not be determined.
* @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 3.0
+ * @deprecated Use {@link ITypeRoot#getWorkingCopy(WorkingCopyOwner, IProgressMonitor)} instead.
+ * Note that if this deprecated method is used, problems will be reported on the passed problem requester
+ * as well as on the problem requestor returned by the working copy owner (if not null).
*/
ICompilationUnit getWorkingCopy(WorkingCopyOwner owner, IProblemRequestor problemRequestor, IProgressMonitor monitor) throws JavaModelException;
/**
* Returns whether the resource of this working copy has changed since the
* inception of this working copy.
* Returns <code>false</code> if this compilation unit is not in working copy mode.
- *
+ *
* @return whether the resource has changed
* @since 3.0
*/
public boolean hasResourceChanged();
/**
* Returns whether this element is a working copy.
- *
+ *
* @return true if this element is a working copy, false otherwise
* @since 3.0
*/
@@ -478,12 +514,12 @@
/**
* Reconciles the contents of this working copy, sends out a Java delta
* notification indicating the nature of the change of the working copy since
- * the last time it was either reconciled or made consistent
+ * the last time it was either reconciled or made consistent
* ({@link IOpenable#makeConsistent(IProgressMonitor)}), and returns a
* compilation unit AST if requested.
* <p>
- * It performs the reconciliation by locally caching the contents of
- * the working copy, updating the contents, then creating a delta
+ * 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>
@@ -513,15 +549,20 @@
* API is not supported, or if the working copy was already consistent.
* </p>
*
+ * <p>
+ * This method doesn't perform statements recovery. To recover statements with syntax
+ * errors, {@link #reconcile(int, boolean, boolean, WorkingCopyOwner, IProgressMonitor)} must be use.
+ * </p>
+ *
* @param astLevel either {@link #NO_AST} if no AST is wanted,
* or the {@linkplain AST#newAST(int) AST API level} of the AST if one is wanted
- * @param forceProblemDetection boolean indicating whether problem should be
+ * @param forceProblemDetection boolean indicating whether problem should be
* recomputed even if the source hasn't changed
- * @param owner the owner of working copies that take precedence over the
+ * @param owner the owner of working copies that take precedence over the
* original compilation units, or <code>null</code> if the primary working
* copy owner should be used
* @param monitor a progress monitor
- * @return the compilation unit AST or <code>null</code> if not requested,
+ * @return the compilation unit AST or <code>null</code> if not requested,
* or if the requested level of AST API is not supported,
* or if the working copy was consistent
* @throws JavaModelException if the contents of the original element
@@ -534,6 +575,146 @@
CompilationUnit reconcile(int astLevel, boolean forceProblemDetection, WorkingCopyOwner owner, IProgressMonitor monitor) throws JavaModelException;
/**
+ * Reconciles the contents of this working copy, sends out a Java delta
+ * notification indicating the nature of the change of the working copy since
+ * the last time it was either reconciled or made consistent
+ * ({@link IOpenable#makeConsistent(IProgressMonitor)}), and returns a
+ * compilation unit AST if requested.
+ * <p>
+ * 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>
+ * <p>
+ * This functionality allows to specify a working copy owner which is used
+ * during problem detection. All references contained in the working copy are
+ * resolved against other units; for which corresponding owned working copies
+ * are going to take precedence over their original compilation units. If
+ * <code>null</code> is passed in, then the primary working copy owner is used.
+ * </p>
+ * <p>
+ * Compilation problems found in the new contents are notified through the
+ * {@link IProblemRequestor} interface which was passed at
+ * creation, and no longer as transient markers.
+ * </p>
+ * <p>
+ * Note: Since 3.0, added/removed/changed inner types generate change deltas.
+ * </p>
+ * <p>
+ * If requested, a DOM AST representing the compilation unit is returned.
+ * Its bindings are computed only if the problem requestor is active, or if the
+ * problem detection is forced. This method returns <code>null</code> if the
+ * creation of the DOM AST was not requested, or if the requested level of AST
+ * API is not supported, or if the working copy was already consistent.
+ * </p>
+ *
+ * <p>
+ * If statements recovery is enabled then this method tries to rebuild statements
+ * with syntax error. Otherwise statements with syntax error won't be present in
+ * the returning DOM AST.
+ * </p>
+ *
+ * @param astLevel either {@link #NO_AST} if no AST is wanted,
+ * or the {@linkplain AST#newAST(int) AST API level} of the AST if one is wanted
+ * @param forceProblemDetection boolean indicating whether problem should be
+ * recomputed even if the source hasn't changed
+ * @param enableStatementsRecovery if <code>true</code> statements recovery is enabled.
+ * @param owner the owner of working copies that take precedence over the
+ * original compilation units, or <code>null</code> if the primary working
+ * copy owner should be used
+ * @param monitor a progress monitor
+ * @return the compilation unit AST or <code>null</code> if not requested,
+ * or if the requested level of AST API is not supported,
+ * or if the working copy was consistent
+ * @throws 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 3.2
+ */
+CompilationUnit reconcile(int astLevel, boolean forceProblemDetection, boolean enableStatementsRecovery, WorkingCopyOwner owner, IProgressMonitor monitor) throws JavaModelException;
+
+/**
+ * Reconciles the contents of this working copy, sends out a Java delta
+ * notification indicating the nature of the change of the working copy since
+ * the last time it was either reconciled or made consistent
+ * ({@link IOpenable#makeConsistent(IProgressMonitor)}), and returns a
+ * compilation unit AST if requested.
+ *
+ * <p>
+ * If the problem detection is forced by passing the {@link #FORCE_PROBLEM_DETECTION} bit in the given reconcile flag,
+ * problem detection is run even if the working copy is already consistent.
+ * </p>
+ *
+ * <p>
+ * 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>
+ *
+ * <p>
+ * This functionality allows to specify a working copy owner which is used
+ * during problem detection. All references contained in the working copy are
+ * resolved against other units; for which corresponding owned working copies
+ * are going to take precedence over their original compilation units. If
+ * <code>null</code> is passed in, then the primary working copy owner is used.
+ * </p>
+ * <p>
+ * Compilation problems found in the new contents are notified through the
+ * {@link IProblemRequestor} interface which was passed at
+ * creation, and no longer as transient markers.
+ * </p>
+ * <p>
+ * Note: Since 3.0, added/removed/changed inner types generate change deltas.
+ * </p>
+ * <p>
+ * If requested, a DOM AST representing the compilation unit is returned.
+ * Its bindings are computed only if the problem requestor is active, or if the
+ * problem detection is forced. This method returns <code>null</code> if the
+ * creation of the DOM AST was not requested, or if the requested level of AST
+ * API is not supported, or if the working copy was already consistent.
+ * </p>
+ *
+ * <p>
+ * If statements recovery is enabled by passing the {@link #ENABLE_STATEMENTS_RECOVERY} bit in the given reconcile flag
+ * then this method tries to rebuild statements with syntax error. Otherwise statements with syntax error won't be
+ * present in the returning DOM AST.</p>
+ * <p>
+ * If bindings recovery is enabled by passing the {@link #ENABLE_BINDINGS_RECOVERY} bit in the given reconcile flag
+ * then this method tries to resolve bindings even if the type resolution contains errors.</p>
+ * <p>
+ * The given reconcile flags is a bit-mask of the different constants ({@link #ENABLE_BINDINGS_RECOVERY},
+ * {@link #ENABLE_STATEMENTS_RECOVERY}, {@link #FORCE_PROBLEM_DETECTION}). Unspecified values are left for future use.
+ * </p>
+ *
+ * @param astLevel either {@link #NO_AST} if no AST is wanted,
+ * or the {@linkplain AST#newAST(int) AST API level} of the AST if one is wanted
+ * @param reconcileFlags the given reconcile flags
+ * @param owner the owner of working copies that take precedence over the
+ * original compilation units, or <code>null</code> if the primary working
+ * copy owner should be used
+ * @param monitor a progress monitor
+ * @return the compilation unit AST or <code>null</code> if not requested,
+ * or if the requested level of AST API is not supported,
+ * or if the working copy was consistent
+ * @throws 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>
+ * @see #FORCE_PROBLEM_DETECTION
+ * @see #ENABLE_BINDINGS_RECOVERY
+ * @see #ENABLE_STATEMENTS_RECOVERY
+ * @since 3.3
+ */
+CompilationUnit reconcile(int astLevel, int reconcileFlags, WorkingCopyOwner owner, 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.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICompletionRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICompletionRequestor.java
index 859e9ca..ef45028 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICompletionRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICompletionRequestor.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICorrectionRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICorrectionRequestor.java
index 0711231..caf903d 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICorrectionRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICorrectionRequestor.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IElementChangedListener.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IElementChangedListener.java
index 64fadc8..72c068e 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IElementChangedListener.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IElementChangedListener.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IImportContainer.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IImportContainer.java
index 691ab5b..f780bd7 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IImportContainer.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IImportContainer.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IImportDeclaration.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IImportDeclaration.java
index 1b081f6..dd4121c 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IImportDeclaration.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IImportDeclaration.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IInitializer.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IInitializer.java
index 2bf888a..6cd7627 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IInitializer.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IInitializer.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJarEntryResource.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJarEntryResource.java
new file mode 100755
index 0000000..7a6e89c
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJarEntryResource.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core;
+
+import org.eclipse.core.resources.IStorage;
+import org.eclipse.core.runtime.IPath;
+
+/**
+ * A jar entry corresponding to a non-Java resource in an archive {@link IPackageFragment} or {@link IPackageFragmentRoot}.
+ * <p>
+ * One can navigate the non-Java resource tree using the {@link #getChildren()} and {@link #getParent()} methods.
+ * Jar entry resources are either files ({@link #isFile()} returns true) or directories ({@link #isFile()} returns false).
+ * Files don't have any children and the returned array is always empty.
+ * </p><p>
+ * Jar entry resources that refer to the same element are guaranteed to be equal, but not necessarily identical.
+ * <p>
+ *
+ * @since 3.3
+ */
+public interface IJarEntryResource extends IStorage {
+
+ /**
+ * Returns the list of children of this jar entry resource.
+ * Returns an empty array if this jar entry is a file, or if this jar entry is a directory and it has no children.
+ *
+ * @return the children of this jar entry resource
+ */
+ IJarEntryResource[] getChildren();
+
+ /**
+ * Returns the full, absolute path of this jar entry resource relative to the archive this jar
+ * entry belongs to.
+ * <p>
+ * A jar entry resource's full path indicates the route from the root of the archive
+ * to the jar entry resource. Within an archive, there is exactly one such path
+ * for any given jar entry resource. The returned path never has a trailing separator.
+ * </p>
+ *
+ * @return the absolute path of this jar entry resource
+ */
+ IPath getFullPath();
+
+ /**
+ * Returns the parent of this jar entry resource. This is either an {@link IJarEntryResource}, an {@link IPackageFragment}
+ * or an {@link IPackageFragmentRoot}.
+ *
+ * @return the parent of this jar entry resource
+ */
+ Object getParent();
+
+ /**
+ * Returns the package fragment root this jar entry file belongs to.
+ *
+ * @return the package fragment root this jar entry file belongs to.
+ */
+ IPackageFragmentRoot getPackageFragmentRoot();
+
+ /**
+ * Returns <code>true</code> if this jar entry represents a file.
+ * Returns <code>false</code> if it is a directory.
+ *
+ * @return whether this jar entry is a file
+ */
+ boolean isFile();
+
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaElement.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaElement.java
index ba23088..bdf18db 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaElement.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaElement.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -13,6 +13,7 @@
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
/**
@@ -21,7 +22,7 @@
* 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 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
@@ -35,92 +36,92 @@
/**
* Constant representing a Java model (workspace level object).
- * A Java element with this type can be safely cast to <code>IJavaModel</code>.
+ * A Java element with this type can be safely cast to {@link IJavaModel}.
*/
int JAVA_MODEL = 1;
/**
* Constant representing a Java project.
- * A Java element with this type can be safely cast to <code>IJavaProject</code>.
+ * A Java element with this type can be safely cast to {@link IJavaProject}.
*/
int JAVA_PROJECT = 2;
/**
* Constant representing a package fragment root.
- * A Java element with this type can be safely cast to <code>IPackageFragmentRoot</code>.
+ * A Java element with this type can be safely cast to {@link IPackageFragmentRoot}.
*/
int PACKAGE_FRAGMENT_ROOT = 3;
/**
* Constant representing a package fragment.
- * A Java element with this type can be safely cast to <code>IPackageFragment</code>.
+ * A Java element with this type can be safely cast to {@link IPackageFragment}.
*/
int PACKAGE_FRAGMENT = 4;
/**
* Constant representing a Java compilation unit.
- * A Java element with this type can be safely cast to <code>ICompilationUnit</code>.
+ * A Java element with this type can be safely cast to {@link ICompilationUnit}.
*/
int COMPILATION_UNIT = 5;
/**
* Constant representing a class file.
- * A Java element with this type can be safely cast to <code>IClassFile</code>.
+ * A Java element with this type can be safely cast to {@link IClassFile}.
*/
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>.
+ * A Java element with this type can be safely cast to {@link IType}.
*/
int TYPE = 7;
/**
* Constant representing a field.
- * A Java element with this type can be safely cast to <code>IField</code>.
+ * A Java element with this type can be safely cast to {@link IField}.
*/
int FIELD = 8;
/**
* Constant representing a method or constructor.
- * A Java element with this type can be safely cast to <code>IMethod</code>.
+ * A Java element with this type can be safely cast to {@link IMethod}.
*/
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>.
+ * A Java element with this type can be safely cast to {@link IInitializer}.
*/
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>.
+ * A Java element with this type can be safely cast to {@link IPackageDeclaration}.
*/
int PACKAGE_DECLARATION = 11;
/**
* Constant representing all import declarations within a compilation unit.
- * A Java element with this type can be safely cast to <code>IImportContainer</code>.
+ * A Java element with this type can be safely cast to {@link IImportContainer}.
*/
int IMPORT_CONTAINER = 12;
/**
* Constant representing an import declaration within a compilation unit.
- * A Java element with this type can be safely cast to <code>IImportDeclaration</code>.
+ * A Java element with this type can be safely cast to {@link IImportDeclaration}.
*/
int IMPORT_DECLARATION = 13;
-
+
/**
* Constant representing a local variable declaration.
- * A Java element with this type can be safely cast to <code>ILocalVariable</code>.
+ * A Java element with this type can be safely cast to {@link ILocalVariable}.
* @since 3.0
*/
int LOCAL_VARIABLE = 14;
-
+
/**
* Constant representing a type parameter declaration.
- * A Java element with this type can be safely cast to <code>ITypeParameter</code>.
+ * A Java element with this type can be safely cast to {@link ITypeParameter}.
* @since 3.1
*/
int TYPE_PARAMETER = 15;
@@ -146,12 +147,12 @@
* <code>false</code> if this element does not exist
*/
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
@@ -159,13 +160,37 @@
IJavaElement getAncestor(int ancestorType);
/**
+ * <p>Returns the Javadoc as an html source if this element has an attached javadoc,
+ * null otherwise.</p>
+ * <p>This should be used only for binary elements. Source elements will always return null.</p>
+ * <p>The encoding used to read the javadoc is the one defined by the content type of the
+ * file. If none is defined, then the project's encoding of this java element is used. If the project's
+ * encoding cannot be retrieved, then the platform encoding is used.</p>
+ * <p>In case of the javadoc doesn't exist for this element, null is returned.</p>
+ *
+ * <p>The html is extracted from the attached javadoc and provided as is. No
+ * transformation or validation is done.</p>
+ *
+ * @param monitor the given progress monitor
+ * @exception JavaModelException if:<ul>
+ * <li>this element does not exist</li>
+ * <li>retrieving the attached javadoc fails (timed-out, invalid URL, ...)</li>
+ * <li>the format of the javadoc doesn't match expected standards (different anchors,...)</li>
+ * </ul>
+ * @return the extracted javadoc from the attached javadoc, null if none
+ * @see IClasspathAttribute#JAVADOC_LOCATION_ATTRIBUTE_NAME
+ * @since 3.2
+ */
+ String getAttachedJavadoc(IProgressMonitor monitor) throws JavaModelException;
+
+ /**
* 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
+ * 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>,
@@ -198,7 +223,7 @@
/**
* 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
+ * workspace sessions, and can be used to recreate this handle via the
* <code>JavaCore.create(String)</code> method.
*
* @return the string handle identifier
@@ -217,7 +242,7 @@
/**
* 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
+ * (for instance, the <code>IJavaModel</code> is not contained in any Java
* project).
* This is a handle-only method.
*
@@ -231,7 +256,7 @@
* 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
@@ -248,26 +273,26 @@
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,
+ * 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 primary element (whose compilation unit is the primary compilation unit)
* this working copy element was created from, or this element if it is a descendant of a
* primary compilation unit or if it is not a descendant of a working copy (e.g. it is a
* binary member).
* The returned element may or may not exist.
- *
+ *
* @return the primary element this working copy element was created from, or this
* element.
* @since 3.0
@@ -275,23 +300,23 @@
IJavaElement getPrimaryElement();
/**
- * 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.
+ * 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.
* This is a handle-only method.
- *
- * @return the innermost resource enclosing this element, <code>null</code> if this
+ *
+ * @return the innermost resource enclosing this element, <code>null</code> if this
* element is included in an external archive
* @since 2.0
*/
IResource getResource();
-
+
/**
* Returns the scheduling rule associated with this Java element.
* This is a handle-only method.
- *
+ *
* @return the scheduling rule associated with this Java element
* @since 3.0
*/
@@ -310,10 +335,10 @@
/**
* Returns whether this Java element is read-only. An element is read-only
- * if its structure cannot be modified by the java model.
+ * 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
+ * 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.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaElementDelta.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaElementDelta.java
index 98fcbf6..d08920e 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaElementDelta.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaElementDelta.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -11,6 +11,7 @@
package org.eclipse.jdt.core;
import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.jdt.core.dom.CompilationUnit;
/**
* A Java element delta describes changes in Java element between two discrete
@@ -18,45 +19,45 @@
* changed, and any children that have changed.
* <p>
* Deltas have a different status depending on the kind of change they represent.
- * The list below summarizes each status (as returned by <code>getKind</code>)
+ * The list below summarizes each status (as returned by {@link #getKind})
* and its meaning (see individual constants for a more detailled description):
* <ul>
- * <li><code>ADDED</code> - The element described by the delta has been added.</li>
- * <li><code>REMOVED</code> - The element described by the delta has been removed.</li>
- * <li><code>CHANGED</code> - The element described by the delta has been changed in some way.
- * Specification of the type of change is provided by <code>getFlags</code> which returns the following values:
+ * <li>{@link #ADDED} - The element described by the delta has been added.</li>
+ * <li>{@link #REMOVED} - The element described by the delta has been removed.</li>
+ * <li>{@link #CHANGED} - The element described by the delta has been changed in some way.
+ * Specification of the type of change is provided by {@link #getFlags} which returns the following values:
* <ul>
- * <li><code>F_ADDED_TO_CLASSPATH</code> - A classpath entry corresponding to the element
+ * <li>{@link #F_ADDED_TO_CLASSPATH} - A classpath entry corresponding to the element
* has been added to the project's classpath. This flag is only valid if the element is an
- * <code>IPackageFragmentRoot</code>.</li>
- * <li><code>F_ARCHIVE_CONTENT_CHANGED</code> - The contents of an archive
- * has changed in some way. This flag is only valid if the element is an <code>IPackageFragmentRoot</code>
+ * {@link IPackageFragmentRoot}.</li>
+ * <li>{@link #F_ARCHIVE_CONTENT_CHANGED} - The contents of an archive
+ * has changed in some way. This flag is only valid if the element is an {@link IPackageFragmentRoot}
* which is an archive.</li>
- * <li><code>F_CHILDREN</code> - A child of the element has changed in some way. This flag
- * is only valid if the element is an <code>IParent</code>.</li>
- * <li><code>F_CLASSPATH_REORDER</code> - A classpath entry corresponding to the element
+ * <li>{@link #F_CHILDREN} - A child of the element has changed in some way. This flag
+ * is only valid if the element is an {@link IParent}.</li>
+ * <li>{@link #F_CLASSPATH_REORDER} - A classpath entry corresponding to the element
* has changed position in the project's classpath. This flag is only valid if the element is an
- * <code>IPackageFragmentRoot</code>.</li>
- * <li><code>F_CLOSED</code> - The underlying <code>IProject</code>
- * has been closed. This flag is only valid if the element is an <code>IJavaProject</code>.</li>
- * <li><code>F_CONTENT</code> - The contents of the element have been altered. This flag
+ * {@link IPackageFragmentRoot}.</li>
+ * <li>{@link #F_CLOSED} - The underlying {@link org.eclipse.core.resources.IProject}
+ * has been closed. This flag is only valid if the element is an {@link IJavaProject}.</li>
+ * <li>{@link #F_CONTENT} - The contents of the element have been altered. This flag
* is only valid for elements which correspond to files.</li>
- *<li><code>F_FINE_GRAINED</code> - The delta is a fine-grained delta, that is, an analysis down
+ *<li>{@link #F_FINE_GRAINED} - The delta is a fine-grained delta, that is, an analysis down
* to the members level was done to determine if there were structural changes to members of the element.</li>
- * <li><code>F_MODIFIERS</code> - The modifiers on the element have changed in some way.
- * This flag is only valid if the element is an <code>IMember</code>.</li>
- * <li><code>F_OPENED</code> - The underlying <code>IProject</code>
- * has been opened. This flag is only valid if the element is an <code>IJavaProject</code>.</li>
- * <li><code>F_REMOVED_FROM_CLASSPATH</code> - A classpath entry corresponding to the element
+ * <li>{@link #F_MODIFIERS} - The modifiers on the element have changed in some way.
+ * This flag is only valid if the element is an {@link IMember}.</li>
+ * <li>{@link #F_OPENED} - The underlying {@link org.eclipse.core.resources.IProject}
+ * has been opened. This flag is only valid if the element is an {@link IJavaProject}.</li>
+ * <li>{@link #F_REMOVED_FROM_CLASSPATH} - A classpath entry corresponding to the element
* has been removed from the project's classpath. This flag is only valid if the element is an
- * <code>IPackageFragmentRoot</code>.</li>
- * <li><code>F_SOURCEATTACHED</code> - The source attachment path or the source attachment root path
+ * {@link IPackageFragmentRoot}.</li>
+ * <li>{@link #F_SOURCEATTACHED} - The source attachment path or the source attachment root path
* of a classpath entry corresponding to the element was added. This flag is only valid if the element is an
- * <code>IPackageFragmentRoot</code>.</li>
- * <li><code>F_SOURCEDETACHED</code> - The source attachment path or the source attachment root path
+ * {@link IPackageFragmentRoot}.</li>
+ * <li>{@link #F_SOURCEDETACHED} - The source attachment path or the source attachment root path
* of a classpath entry corresponding to the element was removed. This flag is only valid if the element is an
- * <code>IPackageFragmentRoot</code>.</li>
- * <li><code>F_SUPER_TYPES</code> - One of the supertypes of an <code>IType</code> has changed</li>.
+ * {@link IPackageFragmentRoot}.</li>
+ * <li>{@link #F_SUPER_TYPES} - One of the supertypes of an {@link IType} has changed</li>.
* </ul>
* </li>
* </ul>
@@ -64,11 +65,11 @@
* <p>
* Move operations are indicated by other change flags, layered on top
* of the change flags described above. If element A is moved to become B,
- * the delta for the change in A will have status <code>REMOVED</code>,
- * with change flag <code>F_MOVED_TO</code>. In this case,
- * <code>getMovedToElement</code> on delta A will return the handle for B.
- * The delta for B will have status <code>ADDED</code>, with change flag
- * <code>F_MOVED_FROM</code>, and <code>getMovedFromElement</code> on delta
+ * the delta for the change in A will have status {@link #REMOVED},
+ * with change flag {@link #F_MOVED_TO}. In this case,
+ * {@link #getMovedToElement} on delta A will return the handle for B.
+ * The delta for B will have status {@link #ADDED}, with change flag
+ * {@link #F_MOVED_FROM}, and {@link #getMovedFromElement} on delta
* B will return the handle for A. (Note, the handle to A in this case represents
* an element that no longer exists).
* </p>
@@ -77,25 +78,25 @@
* do not imply anything about the parent or children of the element.
* </p>
* <p>
- * The <code>F_ADDED_TO_CLASSPATH</code>, <code>F_REMOVED_FROM_CLASSPATH</code> and
- * <code>F_CLASSPATH_REORDER</code> flags are triggered by changes to a project's classpath. They do not mean that
+ * The {@link #F_ADDED_TO_CLASSPATH}, {@link #F_REMOVED_FROM_CLASSPATH} and
+ * {@link #F_CLASSPATH_REORDER} flags are triggered by changes to a project's classpath. They do not mean that
* the underlying resource was added, removed or changed. For example, if a project P already contains a folder src, then
- * adding a classpath entry with the 'P/src' path to the project's classpath will result in an <code>IJavaElementDelta</code>
- * with the <code>F_ADDED_TO_CLASSPATH</code> flag for the <code>IPackageFragmentRoot</code> P/src.
+ * adding a classpath entry with the 'P/src' path to the project's classpath will result in an {@link IJavaElementDelta}
+ * with the {@link #F_ADDED_TO_CLASSPATH} flag for the {@link IPackageFragmentRoot} P/src.
* On the contrary, if a resource is physically added, removed or changed and this resource corresponds to a classpath
- * entry of the project, then an <code>IJavaElementDelta</code> with the <code>ADDED</code>,
- * <code>REMOVED</code>, or <code>CHANGED</code> kind will be fired.
+ * entry of the project, then an {@link IJavaElementDelta} with the {@link #ADDED},
+ * {@link #REMOVED}, or {@link #CHANGED} kind will be fired.
* </p>
* <p>
* Note that when a source attachment path or a source attachment root path is changed, then the flags of the delta contain
- * both <code>F_SOURCEATTACHED</code> and <code>F_SOURCEDETTACHED</code>.
+ * both {@link #F_SOURCEATTACHED} and {@link #F_SOURCEDETACHED}.
* </p>
* <p>
- * No assumptions should be made on whether the java element delta tree is rooted at the <code>IJavaModel</code>
+ * No assumptions should be made on whether the java element delta tree is rooted at the {@link IJavaModel}
* level or not.
* </p>
* <p>
- * <code>IJavaElementDelta</code> object are not valid outside the dynamic scope
+ * {@link IJavaElementDelta} object are not valid outside the dynamic scope
* of the notification.
* </p>
* <p>
@@ -128,90 +129,90 @@
* Change flag indicating that the content of the element has changed.
* This flag is only valid for elements which correspond to files.
*/
- public int F_CONTENT = 0x00001;
+ public int F_CONTENT = 0x000001;
/**
* Change flag indicating that the modifiers of the element have changed.
- * This flag is only valid if the element is an <code>IMember</code>.
+ * This flag is only valid if the element is an {@link IMember}.
*/
- public int F_MODIFIERS = 0x00002;
+ public int F_MODIFIERS = 0x000002;
/**
* Change flag indicating that there are changes to the children of the element.
- * This flag is only valid if the element is an <code>IParent</code>.
+ * This flag is only valid if the element is an {@link IParent}.
*/
- public int F_CHILDREN = 0x00008;
+ public int F_CHILDREN = 0x000008;
/**
* Change flag indicating that the element was moved from another location.
- * The location of the old element can be retrieved using <code>getMovedFromElement</code>.
+ * The location of the old element can be retrieved using {@link #getMovedFromElement}.
*/
- public int F_MOVED_FROM = 0x00010;
+ public int F_MOVED_FROM = 0x000010;
/**
* Change flag indicating that the element was moved to another location.
- * The location of the new element can be retrieved using <code>getMovedToElement</code>.
+ * The location of the new element can be retrieved using {@link #getMovedToElement}.
*/
- public int F_MOVED_TO = 0x00020;
+ public int F_MOVED_TO = 0x000020;
/**
* Change flag indicating that a classpath entry corresponding to the element has been added to the project's classpath.
- * This flag is only valid if the element is an <code>IPackageFragmentRoot</code>.
+ * This flag is only valid if the element is an {@link IPackageFragmentRoot}.
*/
- public int F_ADDED_TO_CLASSPATH = 0x00040;
+ public int F_ADDED_TO_CLASSPATH = 0x000040;
/**
* Change flag indicating that a classpath entry corresponding to the element has been removed from the project's
- * classpath. This flag is only valid if the element is an <code>IPackageFragmentRoot</code>.
+ * classpath. This flag is only valid if the element is an {@link IPackageFragmentRoot}.
*/
- public int F_REMOVED_FROM_CLASSPATH = 0x00080;
+ public int F_REMOVED_FROM_CLASSPATH = 0x000080;
/**
* Change flag indicating that a classpath entry corresponding to the element has changed position in the project's
- * classpath. This flag is only valid if the element is an <code>IPackageFragmentRoot</code>.
- * @deprecated Use F_REORDER instead.
+ * classpath. This flag is only valid if the element is an {@link IPackageFragmentRoot}.
+ * @deprecated Use {@link #F_REORDER} instead.
*/
- public int F_CLASSPATH_REORDER = 0x00100;
+ public int F_CLASSPATH_REORDER = 0x000100;
/**
* Change flag indicating that the element has changed position relatively to its siblings.
- * If the element is an <code>IPackageFragmentRoot</code>, a classpath entry corresponding
+ * If the element is an {@link IPackageFragmentRoot}, a classpath entry corresponding
* to the element has changed position in the project's classpath.
*
* @since 2.1
*/
- public int F_REORDER = 0x00100;
+ public int F_REORDER = 0x000100;
/**
- * Change flag indicating that the underlying <code>IProject</code> has been
- * opened. This flag is only valid if the element is an <code>IJavaProject</code>.
+ * Change flag indicating that the underlying {@link org.eclipse.core.resources.IProject} has been
+ * opened. This flag is only valid if the element is an {@link IJavaProject}.
*/
- public int F_OPENED = 0x00200;
+ public int F_OPENED = 0x000200;
/**
- * Change flag indicating that the underlying <code>IProject</code> has been
- * closed. This flag is only valid if the element is an <code>IJavaProject</code>.
+ * Change flag indicating that the underlying {@link org.eclipse.core.resources.IProject} has been
+ * closed. This flag is only valid if the element is an {@link IJavaProject}.
*/
- public int F_CLOSED = 0x00400;
+ public int F_CLOSED = 0x000400;
/**
- * Change flag indicating that one of the supertypes of an <code>IType</code>
+ * Change flag indicating that one of the supertypes of an {@link IType}
* has changed.
*/
- public int F_SUPER_TYPES = 0x00800;
+ public int F_SUPER_TYPES = 0x000800;
/**
* Change flag indicating that the source attachment path or the source attachment root path of a classpath entry
* corresponding to the element was added. This flag is only valid if the element is an
- * <code>IPackageFragmentRoot</code>.
+ * {@link IPackageFragmentRoot}.
*/
- public int F_SOURCEATTACHED = 0x01000;
+ public int F_SOURCEATTACHED = 0x001000;
/**
* Change flag indicating that the source attachment path or the source attachment root path of a classpath entry
* corresponding to the element was removed. This flag is only valid if the element is an
- * <code>IPackageFragmentRoot</code>.
+ * {@link IPackageFragmentRoot}.
*/
- public int F_SOURCEDETACHED = 0x02000;
+ public int F_SOURCEDETACHED = 0x002000;
/**
* Change flag indicating that this is a fine-grained delta, that is, an analysis down
@@ -219,51 +220,68 @@
* members.
* <p>
* Clients can use this flag to find out if a compilation unit
- * that have a <code>F_CONTENT</code> change should assume that there are
- * no finer grained changes (<code>F_FINE_GRAINED</code> is set) or if
- * finer grained changes were not considered (<code>F_FINE_GRAINED</code>
+ * that have a {@link #F_CONTENT} change should assume that there are
+ * no finer grained changes ({@link #F_FINE_GRAINED} is set) or if
+ * finer grained changes were not considered ({@link #F_FINE_GRAINED}
* is not set).
*
* @since 2.0
*/
- public int F_FINE_GRAINED = 0x04000;
+ public int F_FINE_GRAINED = 0x004000;
/**
* Change flag indicating that the element's archive content on the classpath has changed.
- * This flag is only valid if the element is an <code>IPackageFragmentRoot</code>
+ * This flag is only valid if the element is an {@link IPackageFragmentRoot}
* which is an archive.
*
* @see IPackageFragmentRoot#isArchive()
* @since 2.0
*/
- public int F_ARCHIVE_CONTENT_CHANGED = 0x08000;
+ public int F_ARCHIVE_CONTENT_CHANGED = 0x008000;
/**
* Change flag indicating that a compilation unit has become a primary working copy, or that a
* primary working copy has reverted to a compilation unit.
- * This flag is only valid if the element is an <code>ICompilationUnit</code>.
+ * This flag is only valid if the element is an {@link ICompilationUnit}.
*
* @since 3.0
*/
- public int F_PRIMARY_WORKING_COPY = 0x10000;
+ public int F_PRIMARY_WORKING_COPY = 0x010000;
/**
* Change flag indicating that the raw classpath (or the output folder) of a project has changed.
- * This flag is only valid if the element is an <code>IJavaProject</code>.
+ * This flag is only valid if the element is an {@link IJavaProject}.
*
* @since 3.0
*/
- public int F_CLASSPATH_CHANGED = 0x20000;
+ public int F_CLASSPATH_CHANGED = 0x020000;
/**
* Change flag indicating that the resource of a primary compilation unit has changed.
- * This flag is only valid if the element is a primary <code>ICompilationUnit</code>.
+ * This flag is only valid if the element is a primary {@link ICompilationUnit}.
*
* @since 3.0
*/
- public int F_PRIMARY_RESOURCE = 0x40000;
+ public int F_PRIMARY_RESOURCE = 0x040000;
/**
+ * Change flag indicating that a reconcile operation has affected the compilation unit AST created in a
+ * previous reconcile operation. Use {@link #getCompilationUnitAST()} to retrieve the AST (if any is available).
+ * This flag is only valid if the element is an {@link ICompilationUnit} in working copy mode.
+ *
+ * @since 3.2
+ */
+ public int F_AST_AFFECTED = 0x080000;
+
+ /**
+ * Change flag indicating that the categories of the element have changed.
+ * This flag is only valid if the element is an {@link IMember}.
+ *
+ * @since 3.2
+ */
+ public int F_CATEGORIES = 0x100000;
+
+ /**
* Returns deltas for the children that have been added.
* @return deltas for the children that have been added
*/
@@ -274,6 +292,22 @@
* @return deltas for the affected (added, removed, or changed) children
*/
public IJavaElementDelta[] getAffectedChildren();
+
+ /**
+ * Returns the compilation unit AST created by the last reconcile operation on this delta's element.
+ * This returns a non-null value if and only if:
+ * <ul>
+ * <li>the last reconcile operation on this working copy requested an AST</li>
+ * <li>this delta's element is an {@link ICompilationUnit} in working copy mode</li>
+ * <li>the delta comes from a {@link ElementChangedEvent#POST_RECONCILE} event
+ * </ul>
+ *
+ * @return the AST created during the last reconcile operation
+ * @see ICompilationUnit#reconcile(int, boolean, WorkingCopyOwner, org.eclipse.core.runtime.IProgressMonitor)
+ * @see #F_AST_AFFECTED
+ * @since 3.2
+ */
+ public CompilationUnit getCompilationUnitAST();
/**
* Returns deltas for the children which have changed.
@@ -301,8 +335,8 @@
public int getFlags();
/**
- * Returns the kind of this delta - one of <code>ADDED</code>, <code>REMOVED</code>,
- * or <code>CHANGED</code>.
+ * Returns the kind of this delta - one of {@link #ADDED}, {@link #REMOVED},
+ * or {@link #CHANGED}.
*
* @return the kind of this delta
*/
@@ -311,21 +345,21 @@
/**
* Returns an element describing this element before it was moved
* to its current location, or <code>null</code> if the
- * <code>F_MOVED_FROM</code> change flag is not set.
+ * {@link #F_MOVED_FROM} change flag is not set.
*
* @return an element describing this element before it was moved
* to its current location, or <code>null</code> if the
- * <code>F_MOVED_FROM</code> change flag is not set
+ * {@link #F_MOVED_FROM} change flag is not set
*/
public IJavaElement getMovedFromElement();
/**
* Returns an element describing this element in its new location,
- * or <code>null</code> if the <code>F_MOVED_TO</code> change
+ * or <code>null</code> if the {@link #F_MOVED_TO} change
* flag is not set.
*
* @return an element describing this element in its new location,
- * or <code>null</code> if the <code>F_MOVED_TO</code> change
+ * or <code>null</code> if the {@link #F_MOVED_TO} change
* flag is not set
*/
public IJavaElement getMovedToElement();
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModel.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModel.java
index b646b91..f29180a 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModel.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModel.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModelMarker.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModelMarker.java
index a33ba49..f1e1aa5 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModelMarker.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModelMarker.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -20,72 +20,91 @@
public interface IJavaModelMarker {
/**
- * Java model problem marker type (value <code>"org.eclipse.jdt.core.problem"</code>).
- * This can be used to recognize those markers in the workspace that flag problems
- * detected by the Java tooling during compilation.
+ * Java model problem marker type (value
+ * <code>"org.eclipse.jdt.core.problem"</code>). This can be used to
+ * recognize those markers in the workspace that flag problems detected by
+ * the Java tooling during compilation.
*/
- public static final String JAVA_MODEL_PROBLEM_MARKER = JavaCore.PLUGIN_ID + ".problem"; //$NON-NLS-1$
+ String JAVA_MODEL_PROBLEM_MARKER = JavaCore.PLUGIN_ID + ".problem"; //$NON-NLS-1$
/**
- * Java model transient problem marker type (value <code>"org.eclipse.jdt.core.transient_problem"</code>).
- * This can be used to recognize those markers in the workspace that flag transient
- * problems detected by the Java tooling (such as a problem
- * detected by the outliner, or a problem detected during a code completion)
+ * Java model transient problem marker type (value
+ * <code>"org.eclipse.jdt.core.transient_problem"</code>). This can be
+ * used to recognize those markers in the workspace that flag transient
+ * problems detected by the Java tooling (such as a problem detected by the
+ * outliner, or a problem detected during a code completion). Since 1.0,
+ * transient problems are reported as <code>IProblem</code> through
+ * various API. Only the evaluation API is still producing markers for
+ * transient problems.
+ *
+ * @see org.eclipse.jdt.core.compiler.IProblem
+ * @see org.eclipse.jdt.core.eval.ICodeSnippetRequestor#acceptProblem(org.eclipse.core.resources.IMarker,String,
+ * int)
*/
- public static final String TRANSIENT_PROBLEM = JavaCore.PLUGIN_ID + ".transient_problem"; //$NON-NLS-1$
+ String TRANSIENT_PROBLEM = JavaCore.PLUGIN_ID + ".transient_problem"; //$NON-NLS-1$
/**
- * Java model task marker type (value <code>"org.eclipse.jdt.core.task"</code>).
- * This can be used to recognize task markers in the workspace that correspond to tasks
- * specified in Java source comments and detected during compilation (for example, 'TO-DO: ...').
- * Tasks are identified by a task tag, which can be customized through <code>JavaCore</code>
- * option <code>"org.eclipse.jdt.core.compiler.taskTag"</code>.
+ * Java model task marker type (value
+ * <code>"org.eclipse.jdt.core.task"</code>). This can be used to
+ * recognize task markers in the workspace that correspond to tasks
+ * specified in Java source comments and detected during compilation (for
+ * example, 'TO-DO: ...'). Tasks are identified by a task tag, which can be
+ * customized through <code>JavaCore</code> option
+ * <code>"org.eclipse.jdt.core.compiler.taskTag"</code>.
+ *
* @since 2.1
*/
- public static final String TASK_MARKER = JavaCore.PLUGIN_ID + ".task"; //$NON-NLS-1$
-
- /**
- * Id marker attribute (value <code>"arguments"</code>).
- * Arguments are concatenated into one String, prefixed with an argument count (followed with colon
- * separator) and separated with '#' characters. For example:
- * { "foo", "bar" } is encoded as "2:foo#bar",
- * { } is encoded as "0: "
- * @since 2.0
- */
- public static final String ARGUMENTS = "arguments"; //$NON-NLS-1$
-
- /**
- * Id marker attribute (value <code>"id"</code>).
- */
- public static final String ID = "id"; //$NON-NLS-1$
-
- /**
- * Flags marker attribute (value <code>"flags"</code>).
- * Reserved for future use.
- */
- public static final String FLAGS = "flags"; //$NON-NLS-1$
-
- /**
- * Cycle detected marker attribute (value <code>"cycleDetected"</code>).
- * Used only on buildpath problem markers.
- * The value of this attribute is either "true" or "false".
- */
- public static final String CYCLE_DETECTED = "cycleDetected"; //$NON-NLS-1$
+ String TASK_MARKER = JavaCore.PLUGIN_ID + ".task"; //$NON-NLS-1$
/**
- * Build path problem marker type (value <code>"org.eclipse.jdt.core.buildpath_problem"</code>).
- * This can be used to recognize those markers in the workspace that flag problems
- * detected by the Java tooling during classpath setting.
- */
- public static final String BUILDPATH_PROBLEM_MARKER = JavaCore.PLUGIN_ID + ".buildpath_problem"; //$NON-NLS-1$
-
- /**
- * Classpath file format marker attribute (value <code>"classpathFileFormat"</code>).
- * Used only on buildpath problem markers.
- * The value of this attribute is either "true" or "false".
+ * Id marker attribute (value <code>"arguments"</code>). Arguments are
+ * concatenated into one String, prefixed with an argument count (followed
+ * with colon separator) and separated with '#' characters. For example: {
+ * "foo", "bar" } is encoded as "2:foo#bar", { } is encoded as "0: "
*
* @since 2.0
*/
- public static final String CLASSPATH_FILE_FORMAT = "classpathFileFormat"; //$NON-NLS-1$
-
+ String ARGUMENTS = "arguments"; //$NON-NLS-1$
+
+ /**
+ * ID marker attribute (value <code>"id"</code>).
+ */
+ String ID = "id"; //$NON-NLS-1$
+
+ /**
+ * ID category marker attribute (value <code>"categoryId"</code>)
+ * @since 3.2
+ */
+ String CATEGORY_ID = "categoryId"; //$NON-NLS-1$
+
+ /**
+ * Flags marker attribute (value <code>"flags"</code>). Reserved for
+ * future use.
+ */
+ String FLAGS = "flags"; //$NON-NLS-1$
+
+ /**
+ * Cycle detected marker attribute (value <code>"cycleDetected"</code>).
+ * Used only on buildpath problem markers. The value of this attribute is
+ * either "true" or "false".
+ */
+ String CYCLE_DETECTED = "cycleDetected"; //$NON-NLS-1$
+
+ /**
+ * Build path problem marker type (value
+ * <code>"org.eclipse.jdt.core.buildpath_problem"</code>). This can be
+ * used to recognize those markers in the workspace that flag problems
+ * detected by the Java tooling during classpath setting.
+ */
+ String BUILDPATH_PROBLEM_MARKER = JavaCore.PLUGIN_ID
+ + ".buildpath_problem"; //$NON-NLS-1$
+
+ /**
+ * Classpath file format marker attribute (value
+ * <code>"classpathFileFormat"</code>). Used only on buildpath problem
+ * markers. The value of this attribute is either "true" or "false".
+ *
+ * @since 2.0
+ */
+ String CLASSPATH_FILE_FORMAT = "classpathFileFormat"; //$NON-NLS-1$
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModelStatus.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModelStatus.java
index c90b830..84131cd 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModelStatus.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModelStatus.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -67,7 +67,7 @@
*
* @return the string culprit, or <code>null</code> if none
* @see IJavaModelStatusConstants
- * @deprecated Use IStatus#getMessage instead
+ * @deprecated Use {@link IStatus#getMessage()} instead
*/
String getString();
/**
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModelStatusConstants.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModelStatusConstants.java
index 65b294d..ad659f6 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModelStatusConstants.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModelStatusConstants.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -306,5 +306,24 @@
* Status constant indicating that a compiler option is invalid.
* @since 3.1
*/
-// public static final int INVALID_COMPILER_OPTION = 1007;
+// public static final int INVALID_COMPILER_OPTION = 1007;
+ /**
+ * <p>Status constant indicating that the attached javadoc content cannot be retrieved due to multiple reasons:
+ * invalid url, timed-out,...</p>
+ *
+ * @since 3.2
+ */
+ public static final int CANNOT_RETRIEVE_ATTACHED_JAVADOC = 1008;
+ /**
+ * <p>Status constant indicating that the attached javadoc content format is unrecognized.</p>
+ *
+ * @since 3.2
+ */
+ public static final int UNKNOWN_JAVADOC_FORMAT = 1009;
+ /**
+ * <p>Status constant indicating that the variable is deprecated.</p>
+ *
+ * @since 3.3
+ */
+ public static final int DEPRECATED_VARIABLE = 1010;
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaProject.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaProject.java
index c73c501..1299fda 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaProject.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaProject.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -58,6 +58,26 @@
public interface IJavaProject extends IParent, IJavaElement, IOpenable {
/**
+ * Decodes the classpath entry that has been encoded in the given string
+ * in the context of this project.
+ * Returns null if the encoded entry is malformed.
+ *
+ * @param encodedEntry the encoded classpath entry
+ * @return the decoded classpath entry, or <code>null</code> if unable to decode it
+ * @since 3.2
+ */
+ IClasspathEntry decodeClasspathEntry(String encodedEntry);
+
+ /**
+ * Encodes the given classpath entry into a string in the context of this project.
+ *
+ * @param classpathEntry the classpath entry to encode
+ * @return the encoded classpath entry
+ * @since 3.2
+ */
+ String encodeClasspathEntry(IClasspathEntry classpathEntry);
+
+ /**
* 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
@@ -168,8 +188,7 @@
* Note that in order to be found, a type name (or its toplevel enclosing
* type name) must match its corresponding compilation unit name. As a
* consequence, secondary types cannot be found using this functionality.
- * Secondary types can however be explicitely accessed through their enclosing
- * unit or found by the <code>SearchEngine</code>.
+ * To find secondary types use {@link #findType(String, IProgressMonitor)} instead.
*
* @param fullyQualifiedName the given fully qualified name
* @exception JavaModelException if this project does not exist or if an
@@ -181,6 +200,21 @@
*/
IType findType(String fullyQualifiedName) throws JavaModelException;
/**
+ * Same functionality as {@link #findType(String)} but also look for secondary
+ * types if given name does not match a compilation unit name.
+ *
+ * @param fullyQualifiedName the given fully qualified name
+ * @param progressMonitor the progress monitor to report progress to,
+ * or <code>null</code> if no progress monitor is provided
+ * @exception JavaModelException if this project 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 3.2
+ */
+ IType findType(String fullyQualifiedName, IProgressMonitor progressMonitor) 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,
@@ -192,8 +226,8 @@
* Note that in order to be found, a type name (or its toplevel enclosing
* type name) must match its corresponding compilation unit name. As a
* consequence, secondary types cannot be found using this functionality.
- * Secondary types can however be explicitely accessed through their enclosing
- * unit or found by the <code>SearchEngine</code>.
+ * To find secondary types use {@link #findType(String, WorkingCopyOwner, IProgressMonitor)}
+ * instead.
*
* @param fullyQualifiedName the given fully qualified name
* @param owner the owner of the returned type's compilation unit
@@ -206,6 +240,23 @@
*/
IType findType(String fullyQualifiedName, WorkingCopyOwner owner) throws JavaModelException;
/**
+ * Same functionality as {@link #findType(String, WorkingCopyOwner)}
+ * but also look for secondary types if given name does not match
+ * a compilation unit name.
+ *
+ * @param fullyQualifiedName the given fully qualified name
+ * @param owner the owner of the returned type's compilation unit
+ * @param progressMonitor the progress monitor to report progress to,
+ * or <code>null</code> if no progress monitor is provided
+ * @exception JavaModelException if this project 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 3.2
+ */
+ IType findType(String fullyQualifiedName, WorkingCopyOwner owner, IProgressMonitor progressMonitor) 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.
@@ -217,8 +268,8 @@
* Note that in order to be found, a type name (or its toplevel enclosing
* type name) must match its corresponding compilation unit name. As a
* consequence, secondary types cannot be found using this functionality.
- * Secondary types can however be explicitely accessed through their enclosing
- * unit or found by the <code>SearchEngine</code>.
+ * To find secondary types use {@link #findType(String, String, IProgressMonitor)}
+ * instead.
*
* @param packageName the given package name
* @param typeQualifiedName the given type qualified name
@@ -232,6 +283,22 @@
*/
IType findType(String packageName, String typeQualifiedName) throws JavaModelException;
/**
+ * Same functionality as {@link #findType(String, String)} but also look for
+ * secondary types if given name does not match a compilation unit name.
+ *
+ * @param packageName the given package name
+ * @param typeQualifiedName the given type qualified name
+ * @param progressMonitor the progress monitor to report progress to,
+ * or <code>null</code> if no progress monitor is provided
+ * @exception JavaModelException if this project 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 3.2
+ */
+ IType findType(String packageName, String typeQualifiedName, IProgressMonitor progressMonitor) 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.
@@ -245,8 +312,8 @@
* Note that in order to be found, a type name (or its toplevel enclosing
* type name) must match its corresponding compilation unit name. As a
* consequence, secondary types cannot be found using this functionality.
- * Secondary types can however be explicitely accessed through their enclosing
- * unit or found by the <code>SearchEngine</code>.
+ * To find secondary types use {@link #findType(String, String, WorkingCopyOwner, IProgressMonitor)}
+ * instead.
*
* @param packageName the given package name
* @param typeQualifiedName the given type qualified name
@@ -260,6 +327,23 @@
* @since 3.0
*/
IType findType(String packageName, String typeQualifiedName, WorkingCopyOwner owner) throws JavaModelException;
+ /**
+ * Same functionality as {@link #findType(String, String, WorkingCopyOwner)}
+ * but also look for secondary types if given name does not match a compilation unit name.
+ *
+ * @param packageName the given package name
+ * @param typeQualifiedName the given type qualified name
+ * @param owner the owner of the returned type's compilation unit
+ * @param progressMonitor the progress monitor to report progress to,
+ * or <code>null</code> if no progress monitor is provided
+ * @exception JavaModelException if this project 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 3.2
+ */
+ IType findType(String packageName, String typeQualifiedName, WorkingCopyOwner owner, IProgressMonitor progressMonitor) throws JavaModelException;
/**
* Returns all of the existing package fragment roots that exist
@@ -400,7 +484,7 @@
* @param entry the given entry
* @return the existing package fragment roots identified by the given entry
* @see IClasspathContainer
- * @deprecated Use IJavaProject#findPackageFragmentRoots instead
+ * @deprecated Use {@link IJavaProject#findPackageFragmentRoots(IClasspathEntry)} instead
*/
IPackageFragmentRoot[] getPackageFragmentRoots(IClasspathEntry entry);
@@ -785,9 +869,88 @@
throws JavaModelException;
/**
+ * Sets both the classpath of this project and its default 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 ({@link JavaCore#getClasspathVariable(String)}),
+ * or the full classpath can be resolved at once using the helper method {@link #getResolvedClasspath(boolean)}.
+ * <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><p>
+ * If it is specified that this operation cannot modify resources, the .classpath file will not be written to disk
+ * and no error marker will be generated. To synchronize the .classpath with the in-memory classpath,
+ * one can use <code>setRawClasspath(readRawClasspath(), true, monitor)</code>.
+ * </p><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><p>
+ * If a cycle is detected while setting this classpath (and if resources can be modified), an error marker will be added
+ * to the project closing the cycle.
+ * To avoid this problem, use {@link #hasClasspathCycle(IClasspathEntry[])}
+ * before setting the classpath.
+ * <p>
+ * This operation acquires a lock on the workspace's root.
+ *
+ * @param entries a list of classpath entries
+ * @param outputLocation the default output location
+ * @param canModifyResources whether resources should be written to disk if needed
+ * @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 {@link JavaConventions#validateClasspath(IJavaProject, IClasspathEntry[], IPath)}
+ * </ul>
+ * @see IClasspathEntry
+ * @since 3.2
+ */
+ void setRawClasspath(IClasspathEntry[] entries, IPath outputLocation, boolean canModifyResources, 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>.
+ * classpath variable entries. Classpath variable entries can be resolved individually ({@link JavaCore#getClasspathVariable(String)}),
+ * or the full classpath can be resolved at once using the helper method {@link #getResolvedClasspath(boolean)}.
+ * <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><p>
+ * If it is specified that this operation cannot modify resources, the .classpath file will not be written to disk
+ * and no error marker will be generated. To synchronize the .classpath with the in-memory classpath,
+ * one can use <code>setRawClasspath(readRawClasspath(), true, monitor)</code>.
+ * </p><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><p>
+ * If a cycle is detected while setting this classpath (and if resources can be modified), an error marker will be added
+ * to the project closing the cycle.
+ * To avoid this problem, use {@link #hasClasspathCycle(IClasspathEntry[])}
+ * before setting the classpath.
+ * <p>
+ * This operation acquires a lock on the workspace's root.
+ *
+ * @param entries a list of classpath entries
+ * @param canModifyResources whether resources should be written to disk if needed
+ * @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 {@link JavaConventions#validateClasspath(IJavaProject, IClasspathEntry[], IPath)}
+ * </ul>
+ * @see IClasspathEntry
+ * @since 3.2
+ */
+ void setRawClasspath(IClasspathEntry[] entries, boolean canModifyResources, 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 ({@link JavaCore#getClasspathVariable(String)}),
+ * or the full classpath can be resolved at once using the helper method {@link #getResolvedClasspath(boolean)}.
* <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
@@ -799,7 +962,7 @@
* <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>
+ * To avoid this problem, use {@link #hasClasspathCycle(IClasspathEntry[])}
* before setting the classpath.
* <p>
* This operation acquires a lock on the workspace's root.
@@ -810,7 +973,7 @@
* <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>
+ * <li> The classpath failed the validation check as defined by {@link JavaConventions#validateClasspath(IJavaProject, IClasspathEntry[], IPath)}
* </ul>
* @see IClasspathEntry
*/
@@ -822,9 +985,9 @@
* 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
+ * ({@link JavaCore#getClasspathVariable(String)}), or the full classpath can be
* resolved at once using the helper method
- * <code>getResolvedClasspath</code>.
+ * {@link #getResolvedClasspath(boolean)}.
* <p>
* A classpath variable provides an indirection level for better sharing a
* classpath. As an example, it allows a classpath to no longer refer
@@ -840,7 +1003,7 @@
* <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
+ * {@link #hasClasspathCycle(IClasspathEntry[])} before setting
* the classpath.
* </p>
* <p>
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ILocalVariable.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ILocalVariable.java
index 1ce2918..7c0b6e1 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ILocalVariable.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ILocalVariable.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IMember.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IMember.java
index ff5cc71..59cead4 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IMember.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IMember.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -20,6 +20,17 @@
*/
public interface IMember extends IJavaElement, ISourceReference, ISourceManipulation, IParent {
/**
+ * Returns the categories defined by this member's Javadoc. A category is the identifier
+ * following the tag <code>@category</code> in the member's Javadoc.
+ * Returns an empty array if no category is defined in this member's Javadoc.
+ *
+ * @return the categories defined by this member's doc
+ * @exception JavaModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource.
+ * @since 3.2
+ */
+String[] getCategories() throws JavaModelException;
+/**
* 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.
@@ -61,6 +72,25 @@
*/
int getFlags() throws JavaModelException;
/**
+ * Returns the Javadoc range if this element is from source or if this element
+ * is a binary element with an attached source, null otherwise.
+ *
+ * <p>If this element is from source, the javadoc range is
+ * extracted from the corresponding source.</p>
+ * <p>If this element is from a binary, the javadoc is extracted from the
+ * attached source if present.</p>
+ * <p>If this element's openable is not consistent, then null is returned.</p>
+ *
+ * @exception JavaModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource.
+ * @return a source range corresponding to the javadoc source or <code>null</code>
+ * if no source is available, this element has no javadoc comment or
+ * this element's openable is not consistent
+ * @see IOpenable#isConsistent()
+ * @since 3.2
+ */
+ISourceRange getJavadocRange() 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
@@ -75,6 +105,33 @@
*/
ISourceRange getNameRange() throws JavaModelException;
/**
+ * Returns the position relative to the order this member is defined in the source.
+ * Numbering starts at 1 (thus the first occurrence is occurrence 1, not occurrence 0).
+ * <p>
+ * Two members m1 and m2 that are equal (e.g. 2 fields with the same name in
+ * the same type) can be distinguished using their occurrence counts. If member
+ * m1 appears first in the source, it will have an occurrence count of 1. If member
+ * m2 appears right after member m1, it will have an occurrence count of 2.
+ * </p><p>
+ * The occurrence count can be used to distinguish initializers inside a type
+ * or anonymous types inside a method.
+ * </p><p>
+ * This is a handle-only method. The member may or may not be present.
+ * </p>
+ *
+ * @return the position relative to the order this member is defined in the source
+ * @since 3.2
+ */
+int getOccurrenceCount();
+/**
+ * Returns the Java type root in which this member is declared.
+ * This is a handle-only method.
+ *
+ * @return the Java type root in which this member is declared.
+ * @since 3.3
+ */
+ITypeRoot getTypeRoot();
+/**
* Returns the local or anonymous type declared in this source member with the given simple name and/or
* with the specified position relative to the order they are defined in the source.
* The name is empty if it is an anonymous type.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IMethod.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IMethod.java
index 92c3bd4..85e82c2 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IMethod.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IMethod.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -65,7 +65,7 @@
* in the order declared in the source, an empty array if none
* @see Signature
* @since 3.0
- * @deprecated Use #getTypeParameters() instead
+ * @deprecated Use {@link #getTypeParameters()} instead
*/
String[] getTypeParameterSignatures() throws JavaModelException;
/**
@@ -99,8 +99,8 @@
String getKey();
/**
* 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).
+ * For binary types, associated source or attached Javadoc are used to retrieve the names.
+ * If none can be retrieved, then these names are invented as "arg"+i, where i starts at 0.
* 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>
@@ -131,6 +131,23 @@
*/
String[] getParameterTypes();
/**
+ * Returns the names of parameters in this method.
+ * For binary types, these names are invented as "arg"+i, where i starts at 0
+ * (even if source is associated with the binary or if Javdoc is attached to 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>. For the same method in a
+ * binary, this would return <code>{"arg0", "arg1"}</code>.
+ * </p>
+ *
+ * @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
+ * @since 3.2
+ */
+String[] getRawParameterNames() throws JavaModelException;
+/**
* Returns the type signature of the return value of this method.
* For constructors, this returns the signature for void.
* <p>
@@ -196,7 +213,7 @@
* <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>
+ * <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
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IOpenable.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IOpenable.java
index d0f4e5d..2d1cfab 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IOpenable.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IOpenable.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -55,6 +55,19 @@
*/
public void close() throws JavaModelException;
/**
+ * Finds and returns the recommended line separator for this element.
+ * The element's buffer is first searched and the first line separator in this buffer is returned if any.
+ * Otherwise the preference {@link org.eclipse.core.runtime.Platform#PREF_LINE_SEPARATOR}
+ * on this element's project or workspace is returned.
+ * Finally if no such preference is set, the system line separator is returned.
+ *
+ * @return the recommended line separator for this element
+ * @exception JavaModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource.
+ * @since 3.2
+ */
+public String findRecommendedLineSeparator() throws JavaModelException;
+/**
* Returns the buffer opened for this element, or <code>null</code>
* if this element does not have a buffer.
*
@@ -110,7 +123,9 @@
* by updating the element's structure and properties as necessary.
*<p>
* Note: Using this functionality on a working copy will interfere with any
- * subsequent reconciling operation. Indeed, the next {@link ICompilationUnit#reconcile}
+ * subsequent reconciling operation. Indeed, the next
+ * {@link ICompilationUnit#reconcile(int, boolean, WorkingCopyOwner, IProgressMonitor)} or
+ * {@link ICompilationUnit#reconcile(int, boolean, boolean, WorkingCopyOwner, IProgressMonitor)}
* operation will not account for changes which occurred before an
* explicit use of {@link #makeConsistent(IProgressMonitor)}
* <p>
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IPackageDeclaration.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IPackageDeclaration.java
index 597977c..cc7f318 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IPackageDeclaration.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IPackageDeclaration.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IPackageFragment.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IPackageFragment.java
index 0ae4a74..25b7414 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IPackageFragment.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IPackageFragment.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -100,7 +100,7 @@
*
* @param name the given name
* @return the compilation unit with the specified name in this package
- * @see JavaConventions#validateCompilationUnitName(String)
+ * @see JavaConventions#validateCompilationUnitName(String name, String sourceLevel, String complianceLevel)
*/
ICompilationUnit getCompilationUnit(String name);
/**
@@ -145,7 +145,8 @@
String getElementName();
/**
* Returns this package fragment's root kind encoded as an integer.
- * A package fragment can contain <code>.java</code> source files,
+ * A package fragment can contain source files (i.e. files with one of
+ * the {@link JavaCore#getJavaLikeExtensions() Java-like extensions}),
* or <code>.class</code> files. This is a convenience method.
*
* @exception JavaModelException if this element does not exist or if an
@@ -164,6 +165,11 @@
* inclusion/exclusion patterns on the corresponding source classpath entry
* are considered non-Java resources and will appear in the result
* (possibly in a folder).
+ * </p><p>
+ * Since 3.3, if this package fragment is inside an archive, the non-Java resources
+ * are a tree of {@link IJarEntryResource}s. One can navigate this tree using
+ * the {@link IJarEntryResource#getChildren()} and
+ * {@link IJarEntryResource#getParent()} methods.
* </p>
*
* @exception JavaModelException if this element does not exist or if an
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IPackageFragmentRoot.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IPackageFragmentRoot.java
index 527f119..e8d36dc 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IPackageFragmentRoot.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IPackageFragmentRoot.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -245,11 +245,12 @@
void delete(int updateResourceFlags, int updateModelFlags, IProgressMonitor monitor) throws JavaModelException;
/**
* Returns this package fragment root's kind encoded as an integer.
- * A package fragment root can contain <code>.java</code> source files,
+ * A package fragment root can contain source files (i.e. files with one
+ * of the {@link JavaCore#getJavaLikeExtensions() Java-like extensions},
* or <code>.class</code> files, but not both.
* If the underlying folder or archive contains other kinds of files, they are ignored.
* In particular, <code>.class</code> files are ignored under a source package fragment root,
- * and <code>.java</code> files are ignored under a binary package fragment root.
+ * and source files are ignored under a binary package fragment root.
*
* @exception JavaModelException if this element does not exist or if an
* exception occurs while accessing its corresponding resource.
@@ -269,7 +270,13 @@
* entry are considered non-Java resources and will appear in the result
* (possibly in a folder). Thus when a nested source folder is excluded, it will appear
* in the non-Java resources of the outer folder.
+ * </p><p>
+ * Since 3.3, if this package fragment root is an archive, the non-Java resources
+ * are a tree of {@link IJarEntryResource}s. One can navigate this tree using
+ * the {@link IJarEntryResource#getChildren()} and
+ * {@link IJarEntryResource#getParent()} methods.
* </p>
+ *
* @return an array of non-Java resources (<code>IFile</code>s,
* <code>IFolder</code>s, or <code>IStorage</code>s if the
* package fragment root is in archive) contained in this package
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IParent.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IParent.java
index 66b9379..8f85575 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IParent.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IParent.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IProblemRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IProblemRequestor.java
index 2dc0c95..7781fdc 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IProblemRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IProblemRequestor.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -43,7 +43,7 @@
/**
* Predicate allowing the problem requestor to signal whether or not it is currently
- * interested by problem reports. When answering <code>false</false>, problem will
+ * interested by problem reports. When answering <code>false</code>, problem will
* not be discovered any more until the next iteration.
*
* This predicate will be invoked once prior to each problem detection iteration.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IRegion.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IRegion.java
index b621ede..6474177 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IRegion.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IRegion.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ISourceManipulation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ISourceManipulation.java
index d19b1c7..758e818 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ISourceManipulation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ISourceManipulation.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ISourceRange.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ISourceRange.java
index 468c048..a3bc9a1 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ISourceRange.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ISourceRange.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ISourceReference.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ISourceReference.java
index 3e7b79c..f005327 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ISourceReference.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ISourceReference.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -16,7 +16,6 @@
* <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
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IType.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IType.java
index 95d562e..4286f85 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IType.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IType.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -345,6 +345,17 @@
IMethod[] findMethods(IMethod method);
/**
+ * Returns the children of this type that have the given category as a <code>@category</code> tag.
+ * Returns an empty array if no children with this category exist.
+ *
+ * @return the children for the given category.
+ * @exception JavaModelException if this element does not exist or if an
+ * exception occurs while accessing its corresponding resource.
+ * @since 3.2
+ */
+ IJavaElement[] getChildrenForCategory(String category) throws JavaModelException;
+
+ /**
* Returns the simple name of this type, unqualified by package or enclosing type.
* This is a handle-only method.
*
@@ -417,7 +428,7 @@
/**
* Returns this type's fully qualified name followed by its type parameters between angle brakets if it is a generic type.
- * For example, "p.X<T>", "java.util.Map<java.lang.String, p.X>"
+ * For example, "p.X<T>", "java.util.Map<java.lang.String, p.X>"
*
* @exception JavaModelException if this element does not exist or if an
* exception occurs while accessing its corresponding resource.
@@ -481,7 +492,7 @@
/**
* Returns the methods and constructors declared by this type.
- * For binary types, this may include the special <code><clinit></code>; method
+ * For binary types, this may include the special <code><clinit></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
@@ -569,7 +580,7 @@
/**
* Returns the names of interfaces that this type implements or extends,
* in the order in which they are listed in the source.
- * </p>
+ * <p>
* 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
@@ -668,7 +679,7 @@
* <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>
+ * 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
@@ -776,7 +787,7 @@
boolean isMember() throws JavaModelException;
/**
* Returns whether this type represents a resolved type.
- * If a type is resoved, its key contains resolved information.
+ * If a type is resolved, its key contains resolved information.
*
* @return whether this type represents a resolved type.
* @since 3.1
@@ -791,7 +802,7 @@
* <li>IType#newSupertypeHierarchy(IProgressMonitor)</li>
* <li>IType#newTypeHierarchy(IJavaProject, IProgressMonitor)</li>
* <li>IType#newTypeHierarchy(IProgressMonitor)</li>
- * </u>
+ * </ul>
*
* @param input stream where hierarchy will be read
* @param monitor the given progress monitor
@@ -850,7 +861,7 @@
* @exception JavaModelException if this element does not exist or if an
* exception occurs while accessing its corresponding resource.
* @since 2.0
- * @deprecated use #newSupertypeHierarchy(ICompilationUnit[], IProgressMonitor) instead
+ * @deprecated Use {@link #newSupertypeHierarchy(ICompilationUnit[], IProgressMonitor)} instead
*/
ITypeHierarchy newSupertypeHierarchy(IWorkingCopy[] workingCopies, IProgressMonitor monitor)
throws JavaModelException;
@@ -962,7 +973,7 @@
* @exception JavaModelException if this element does not exist or if an
* exception occurs while accessing its corresponding resource.
* @since 2.0
- * @deprecated use #newTypeHierarchy(ICompilationUnit[], IProgressMonitor) instead
+ * @deprecated Use {@link #newTypeHierarchy(ICompilationUnit[], IProgressMonitor)} instead
*/
ITypeHierarchy newTypeHierarchy(IWorkingCopy[] workingCopies, IProgressMonitor monitor) throws JavaModelException;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ITypeHierarchy.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ITypeHierarchy.java
index 64ef993..51c9732 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ITypeHierarchy.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ITypeHierarchy.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -291,7 +291,7 @@
* <li>IType#newSupertypeHierarchy(IProgressMonitor)</li>
* <li>IType#newTypeHierarchy(IJavaProject, IProgressMonitor)</li>
* <li>IType#newTypeHierarchy(IProgressMonitor)</li>
- * </u>
+ * </ul>
*
* @param outputStream output stream where the hierarchy will be stored
* @param monitor the given progress monitor
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ITypeHierarchyChangedListener.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ITypeHierarchyChangedListener.java
index 335a320..5b43f1d 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ITypeHierarchyChangedListener.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ITypeHierarchyChangedListener.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ITypeParameter.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ITypeParameter.java
index 26ccbc5..12b51ef 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ITypeParameter.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ITypeParameter.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004 IBM Corporation and others.
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -22,6 +22,9 @@
* of the type parameters use {@link IType#getTypeParameters()} for a type and use
* {@link IMethod#getTypeParameters()} for a method.
* </p>
+ * <p>
+ * This interface is not intended to be implemented by clients.
+ * </p>
*
* @since 3.1
*/
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ITypeRoot.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ITypeRoot.java
new file mode 100755
index 0000000..1e14fe4
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ITypeRoot.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+
+
+/**
+ * Represents an entire Java type root (either an <code>ICompilationUnit</code>
+ * or an <code>IClassFile</code>).
+ *
+ * <p>
+ * This interface is not intended to be implemented by clients.
+ * </p>
+ *
+ * @see ICompilationUnit Note that methods {@link #findPrimaryType()} and {@link #getElementAt(int)}
+ * were already implemented in this interface respectively since version 3.0 and version 1.0.
+ * @see IClassFile Note that method {@link #getWorkingCopy(WorkingCopyOwner, IProgressMonitor)}
+ * was already implemented in this interface since version 3.0.
+ * @since 3.3
+ */
+public interface ITypeRoot extends IJavaElement, IParent, IOpenable, ISourceReference, ICodeAssist {
+
+/**
+ * Finds the primary type of this Java type root (that is, the type with the same name as the
+ * compilation unit, or the type of a class file), or <code>null</code> if no such a type exists.
+ *
+ * @return the found primary type of this Java type root, or <code>null</code> if no such a type exists
+ */
+IType findPrimaryType();
+
+/**
+ * Returns the smallest element within this Java type root that
+ * includes the given source position (that is, a method, field, etc.), or
+ * <code>null</code> if there is no element other than the Java type root
+ * itself at the given position, or if the given position is not
+ * within the source range of the source of this Java type root.
+ *
+ * @param position a source position inside the Java type root
+ * @return the innermost Java element enclosing a given source position or <code>null</code>
+ * if none (excluding the Java type root).
+ * @throws JavaModelException if the Java type root does not exist or if an
+ * exception occurs while accessing its corresponding resource
+ */
+IJavaElement getElementAt(int position) throws JavaModelException;
+
+/**
+ * Returns a shared working copy on this compilation unit or class file using the given working copy owner to create
+ * the buffer. If this is already a working copy of the given owner, the element itself is returned.
+ * This API can only answer an already existing working copy if it is based on the same
+ * original Java type root AND was using the same working copy owner (that is, as defined by {@link Object#equals}).
+ * <p>
+ * The life time of a shared working copy is as follows:
+ * <ul>
+ * <li>The first call to {@link #getWorkingCopy(WorkingCopyOwner, IProgressMonitor)}
+ * creates a new working copy for this element</li>
+ * <li>Subsequent calls increment an internal counter.</li>
+ * <li>A call to {@link ICompilationUnit#discardWorkingCopy()} decrements the internal counter.</li>
+ * <li>When this counter is 0, the working copy is discarded.
+ * </ul>
+ * So users of this method must discard exactly once the working copy.
+ * <p>
+ * Note that the working copy owner will be used for the life time of the shared working copy, that is if the
+ * working copy is closed then reopened, this owner will be used.
+ * The buffer will be automatically initialized with the original's Java type root content upon creation.
+ * <p>
+ * When the shared working copy instance is created, an ADDED IJavaElementDelta is reported on this
+ * working copy.
+ * </p><p>
+ * A working copy can be created on a not-yet existing compilation unit.
+ * In particular, such a working copy can then be committed in order to create
+ * the corresponding compilation unit.
+ * </p><p>
+ * Note that possible problems of this working copy are reported using this method only
+ * if the given working copy owner returns a problem requestor for this working copy
+ * (see {@link WorkingCopyOwner#getProblemRequestor(ICompilationUnit)}).
+ * </p>
+ *
+ * @param owner the working copy owner that creates a buffer that is used to get the content
+ * of the 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
+ * @throws JavaModelException if the contents of this element can
+ * not be determined.
+ * @return a new working copy of this Java type root using the given owner to create
+ * the buffer, or this Java type root if it is already a working copy
+ */
+ICompilationUnit getWorkingCopy(WorkingCopyOwner owner, IProgressMonitor monitor) throws JavaModelException;
+
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IWorkingCopy.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IWorkingCopy.java
index c034623..c3b80d1 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IWorkingCopy.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IWorkingCopy.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -49,7 +49,7 @@
* <p>
* This interface is not intended to be implemented by clients.
* </p>
- * @deprecated Use <code>ICompilationUnit</code>instead
+ * @deprecated Use {@link ICompilationUnit} instead
*/
public interface IWorkingCopy {
@@ -81,6 +81,7 @@
* <li> This element is not a working copy (INVALID_ELEMENT_TYPES)
* <li> A update conflict (described above) (UPDATE_CONFLICT)
* </ul>
+ * @deprecated Use {@link ICompilationUnit#commitWorkingCopy(boolean, IProgressMonitor)} instead.
*/
void commit(boolean force, IProgressMonitor monitor) throws JavaModelException;
@@ -97,6 +98,7 @@
* When it is destroyed, a REMOVED IJavaElementDelta is reported on this
* working copy.
* </p>
+ * @deprecated Use {@link ICompilationUnit#discardWorkingCopy()} instead.
*/
void destroy();
@@ -111,6 +113,8 @@
* @return the found shared working copy for this element, <code>null</code> if none
* @see IBufferFactory
* @since 2.0
+ *
+ * @deprecated Use {@link ICompilationUnit#findWorkingCopy(WorkingCopyOwner)} instead.
*/
IJavaElement findSharedWorkingCopy(IBufferFactory bufferFactory);
@@ -122,6 +126,8 @@
* @param workingCopyElement the specified working copy element
* @return the original element the specified working copy element was created from,
* or <code>null</code> if this is not a working copy element
+ *
+ * @deprecated Use {@link IJavaElement#getPrimaryElement()} instead.
*/
IJavaElement getOriginal(IJavaElement workingCopyElement);
@@ -131,6 +137,8 @@
*
* @return the original element this working copy was created from,
* or <code>null</code> if this is not a working copy
+ *
+ * @deprecated Use {@link ICompilationUnit#findPrimaryType()} instead.
*/
IJavaElement getOriginalElement();
@@ -152,6 +160,8 @@
* @param element the given element
* @return the found elements in this compilation unit that correspond to the given element
* @since 2.0
+ *
+ * @deprecated Use {@link ICompilationUnit#findElements(IJavaElement)} instead.
*/
IJavaElement[] findElements(IJavaElement element);
@@ -161,6 +171,8 @@
*
* @return the found primary type of this compilation unit, or <code>null</code> if no such a type exists
* @since 2.0
+ *
+ * @deprecated Use {@link ITypeRoot#findPrimaryType()} instead.
*/
IType findPrimaryType();
@@ -202,6 +214,8 @@
* @see IBufferFactory
* @see IProblemRequestor
* @since 2.0
+ *
+ * @deprecated Use {@link ICompilationUnit#getWorkingCopy(WorkingCopyOwner, IProblemRequestor, IProgressMonitor)} instead.
*/
IJavaElement getSharedWorkingCopy(
IProgressMonitor monitor,
@@ -227,6 +241,8 @@
* not be determined.
* @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
+ *
+ * @deprecated Use {@link ICompilationUnit#getWorkingCopy(IProgressMonitor)} instead.
*/
IJavaElement getWorkingCopy() throws JavaModelException;
@@ -260,6 +276,8 @@
* @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
+ *
+ * @deprecated Use {@link ICompilationUnit#getWorkingCopy(WorkingCopyOwner, IProblemRequestor, IProgressMonitor)} instead.
*/
IJavaElement getWorkingCopy(
IProgressMonitor monitor,
@@ -274,6 +292,8 @@
* @param resource this working copy's resource
* @return true if this working copy's original element's content
* has not changed since the inception of this working copy, false otherwise
+ *
+ * @deprecated Use {@link ICompilationUnit#hasResourceChanged()} instead.
*/
boolean isBasedOn(IResource resource);
@@ -281,6 +301,8 @@
* Returns whether this element is a working copy.
*
* @return true if this element is a working copy, false otherwise
+ *
+ * @deprecated Use {@link ICompilationUnit#isWorkingCopy()} instead.
*/
boolean isWorkingCopy();
@@ -307,6 +329,8 @@
* <li> The original Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
* </ul>
* @return <code>null</code>
+ *
+ * @deprecated Use {@link ICompilationUnit#reconcile(int, boolean, WorkingCopyOwner, IProgressMonitor)} instead.
*/
IMarker[] reconcile() throws JavaModelException;
@@ -336,6 +360,8 @@
* <li> The original Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
* </ul>
* @since 2.0
+ *
+ * @deprecated Use {@link ICompilationUnit#reconcile(int, boolean, WorkingCopyOwner, IProgressMonitor)} instead.
*/
void reconcile(boolean forceProblemDetection, IProgressMonitor monitor) throws JavaModelException;
@@ -352,6 +378,7 @@
* <ul>
* <li> The original Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
* </ul>
+ * @deprecated Use {@link ICompilationUnit#restore()} instead.
*/
void restore() throws JavaModelException;
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaConventions.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaConventions.java
index 9ef3ef0..b6d9ebf 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaConventions.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaConventions.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -19,8 +19,11 @@
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.compiler.*;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.eclipse.jdt.internal.compiler.parser.Scanner;
+import org.eclipse.jdt.internal.compiler.parser.ScannerHelper;
import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
import org.eclipse.jdt.internal.core.*;
@@ -35,10 +38,10 @@
*/
public final class JavaConventions {
- private final static char DOT= '.';
+ private static final char DOT= '.';
private static final String PACKAGE_INFO = new String(TypeConstants.PACKAGE_INFO_NAME);
- private final static Scanner SCANNER = new Scanner();
-
+ private static final Scanner SCANNER = new Scanner(false /*comment*/, true /*whitespace*/, false /*nls*/, ClassFileConstants.JDK1_3 /*sourceLevel*/, null/*taskTag*/, null/*taskPriorities*/, true /*taskCaseSensitive*/);
+
private JavaConventions() {
// Not instantiable
}
@@ -72,32 +75,27 @@
/*
* Returns the current identifier extracted by the scanner (without unicode
- * escapes) from the given id.
+ * escapes) from the given id and for the given source and compliance levels.
* Returns <code>null</code> if the id was not valid
*/
- private static synchronized char[] scannedIdentifier(String id) {
+ private static synchronized char[] scannedIdentifier(String id, String sourceLevel, String complianceLevel) {
if (id == null) {
return null;
}
- String trimmed = id.trim();
- if (!trimmed.equals(id)) {
- return null;
- }
+ // Set scanner for given source and compliance levels
+ SCANNER.sourceLevel = sourceLevel == null ? ClassFileConstants.JDK1_3 : CompilerOptions.versionToJdkLevel(sourceLevel);
+ SCANNER.complianceLevel = complianceLevel == null ? ClassFileConstants.JDK1_3 : CompilerOptions.versionToJdkLevel(complianceLevel);
+
try {
SCANNER.setSource(id.toCharArray());
- int token = SCANNER.getNextToken();
- char[] currentIdentifier;
- try {
- currentIdentifier = SCANNER.getCurrentIdentifierSource();
- } catch (ArrayIndexOutOfBoundsException e) {
- return null;
- }
- int nextToken= SCANNER.getNextToken();
- if (token == TerminalTokens.TokenNameIdentifier
- && nextToken == TerminalTokens.TokenNameEOF
- && SCANNER.startPosition == SCANNER.source.length) { // to handle case where we had an ArrayIndexOutOfBoundsException
- // while reading the last token
- return currentIdentifier;
+ int token = SCANNER.scanIdentifier();
+ if (token != TerminalTokens.TokenNameIdentifier) return null;
+ if (SCANNER.currentPosition == SCANNER.eofPosition) { // to handle case where we had an ArrayIndexOutOfBoundsException
+ try {
+ return SCANNER.getCurrentIdentifierSource();
+ } catch (ArrayIndexOutOfBoundsException e) {
+ return null;
+ }
} else {
return null;
}
@@ -109,10 +107,12 @@
/**
* Validate the given compilation unit name.
+ * <p>
* A compilation unit name must obey the following rules:
* <ul>
* <li> it must not be null
- * <li> it must include the <code>".java"</code> suffix
+ * <li> it must be suffixed by a dot ('.') followed by one of the
+ * {@link JavaCore#getJavaLikeExtensions() Java-like extensions}
* <li> its prefix must be a valid identifier
* <li> it must not contain any characters or substrings that are not valid
* on the file system on which workspace root is located.
@@ -122,8 +122,34 @@
* @return a status object with code <code>IStatus.OK</code> if
* the given name is valid as a compilation unit name, otherwise a status
* object indicating what is wrong with the name
+ * @deprecated Use {@link #validateCompilationUnitName(String id, String sourceLevel, String complianceLevel)} instead
*/
public static IStatus validateCompilationUnitName(String name) {
+ return validateCompilationUnitName(name,CompilerOptions.VERSION_1_3,CompilerOptions.VERSION_1_3);
+ }
+
+ /**
+ * Validate the given compilation unit name for the given source and compliance levels.
+ * <p>
+ * A compilation unit name must obey the following rules:
+ * <ul>
+ * <li> it must not be null
+ * <li> it must be suffixed by a dot ('.') followed by one of the
+ * {@link JavaCore#getJavaLikeExtensions() Java-like extensions}
+ * <li> its prefix must be a valid identifier
+ * <li> it must not contain any characters or substrings that are not valid
+ * on the file system on which workspace root is located.
+ * </ul>
+ * </p>
+ * @param name the name of a compilation unit
+ * @param sourceLevel the source level
+ * @param complianceLevel the compliance level
+ * @return a status object with code <code>IStatus.OK</code> if
+ * the given name is valid as a compilation unit name, otherwise a status
+ * object indicating what is wrong with the name
+ * @since 3.3
+ */
+ public static IStatus validateCompilationUnitName(String name, String sourceLevel, String complianceLevel) {
if (name == null) {
return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.convention_unit_nullName, null);
}
@@ -141,7 +167,7 @@
// file in which to store package annotations and
// the package-level spec (replaces package.html)
if (!identifier.equals(PACKAGE_INFO)) {
- IStatus status = validateIdentifier(identifier);
+ IStatus status = validateIdentifier(identifier, sourceLevel, complianceLevel);
if (!status.isOK()) {
return status;
}
@@ -155,6 +181,7 @@
/**
* Validate the given .class file name.
+ * <p>
* A .class file name must obey the following rules:
* <ul>
* <li> it must not be null
@@ -169,8 +196,33 @@
* the given name is valid as a .class file name, otherwise a status
* object indicating what is wrong with the name
* @since 2.0
+ * @deprecated Use {@link #validateClassFileName(String id, String sourceLevel, String complianceLevel)} instead
*/
public static IStatus validateClassFileName(String name) {
+ return validateClassFileName(name, CompilerOptions.VERSION_1_3, CompilerOptions.VERSION_1_3);
+ }
+
+ /**
+ * Validate the given .class file name for the given source and compliance levels.
+ * <p>
+ * A .class file name must obey the following rules:
+ * <ul>
+ * <li> it must not be null
+ * <li> it must include the <code>".class"</code> suffix
+ * <li> its prefix must be a valid identifier
+ * <li> it must not contain any characters or substrings that are not valid
+ * on the file system on which workspace root is located.
+ * </ul>
+ * </p>
+ * @param name the name of a .class file
+ * @param sourceLevel the source level
+ * @param complianceLevel the compliance level
+ * @return a status object with code <code>IStatus.OK</code> if
+ * the given name is valid as a .class file name, otherwise a status
+ * object indicating what is wrong with the name
+ * @since 3.3
+ */
+ public static IStatus validateClassFileName(String name, String sourceLevel, String complianceLevel) {
if (name == null) {
return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.convention_classFile_nullName, null); }
if (!org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(name)) {
@@ -187,7 +239,7 @@
// file in which to store package annotations and
// the package-level spec (replaces package.html)
if (!identifier.equals(PACKAGE_INFO)) {
- IStatus status = validateIdentifier(identifier);
+ IStatus status = validateIdentifier(identifier, sourceLevel, complianceLevel);
if (!status.isOK()) {
return status;
}
@@ -209,9 +261,28 @@
* @return a status object with code <code>IStatus.OK</code> if
* the given name is valid as a field name, otherwise a status
* object indicating what is wrong with the name
+ * @deprecated Use {@link #validateFieldName(String id, String sourceLevel, String complianceLevel)} instead
*/
public static IStatus validateFieldName(String name) {
- return validateIdentifier(name);
+ return validateIdentifier(name, CompilerOptions.VERSION_1_3,CompilerOptions.VERSION_1_3);
+ }
+
+ /**
+ * Validate the given field name for the given source and compliance levels.
+ * <p>
+ * Syntax of a field name corresponds to VariableDeclaratorId (JLS2 8.3).
+ * For example, <code>"x"</code>.
+ *
+ * @param name the name of a field
+ * @param sourceLevel the source level
+ * @param complianceLevel the compliance level
+ * @return a status object with code <code>IStatus.OK</code> if
+ * the given name is valid as a field name, otherwise a status
+ * object indicating what is wrong with the name
+ * @since 3.3
+ */
+ public static IStatus validateFieldName(String name, String sourceLevel, String complianceLevel) {
+ return validateIdentifier(name, sourceLevel, complianceLevel);
}
/**
@@ -225,9 +296,29 @@
* @return a status object with code <code>IStatus.OK</code> if
* the given identifier is a valid Java identifier, otherwise a status
* object indicating what is wrong with the identifier
+ * @deprecated Use {@link #validateIdentifier(String id, String sourceLevel, String complianceLevel)} instead
*/
public static IStatus validateIdentifier(String id) {
- if (scannedIdentifier(id) != null) {
+ return validateIdentifier(id,CompilerOptions.VERSION_1_3,CompilerOptions.VERSION_1_3);
+ }
+
+ /**
+ * Validate the given Java identifier for the given source and compliance levels
+ * The identifier must not have the same spelling as a Java keyword,
+ * boolean literal (<code>"true"</code>, <code>"false"</code>), or null literal (<code>"null"</code>).
+ * See section 3.8 of the <em>Java Language Specification, Second Edition</em> (JLS2).
+ * A valid identifier can act as a simple type name, method name or field name.
+ *
+ * @param id the Java identifier
+ * @param sourceLevel the source level
+ * @param complianceLevel the compliance level
+ * @return a status object with code <code>IStatus.OK</code> if
+ * the given identifier is a valid Java identifier, otherwise a status
+ * object indicating what is wrong with the identifier
+ * @since 3.3
+ */
+ public static IStatus validateIdentifier(String id, String sourceLevel, String complianceLevel) {
+ if (scannedIdentifier(id, sourceLevel, complianceLevel) != null) {
return JavaModelStatus.VERIFIED_OK;
} else {
return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.bind(Messages.convention_illegalIdentifier, id), null);
@@ -245,19 +336,39 @@
* @return a status object with code <code>IStatus.OK</code> if
* the given name is valid as an import declaration, otherwise a status
* object indicating what is wrong with the name
+ * @deprecated Use {@link #validateImportDeclaration(String id, String sourceLevel, String complianceLevel)} instead
*/
public static IStatus validateImportDeclaration(String name) {
+ return validateImportDeclaration(name,CompilerOptions.VERSION_1_3,CompilerOptions.VERSION_1_3);
+ }
+
+ /**
+ * Validate the given import declaration name for the given source and compliance levels.
+ * <p>
+ * The name of an import corresponds to a fully qualified type name
+ * or an on-demand package name as defined by ImportDeclaration (JLS2 7.5).
+ * For example, <code>"java.util.*"</code> or <code>"java.util.Hashtable"</code>.
+ *
+ * @param name the import declaration
+ * @param sourceLevel the source level
+ * @param complianceLevel the compliance level
+ * @return a status object with code <code>IStatus.OK</code> if
+ * the given name is valid as an import declaration, otherwise a status
+ * object indicating what is wrong with the name
+ * @since 3.3
+ */
+ public static IStatus validateImportDeclaration(String name, String sourceLevel, String complianceLevel) {
if (name == null || name.length() == 0) {
return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.convention_import_nullImport, null);
}
if (name.charAt(name.length() - 1) == '*') {
if (name.charAt(name.length() - 2) == '.') {
- return validatePackageName(name.substring(0, name.length() - 2));
+ return validatePackageName(name.substring(0, name.length() - 2), sourceLevel, complianceLevel);
} else {
return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.convention_import_unqualifiedImport, null);
}
}
- return validatePackageName(name);
+ return validatePackageName(name, sourceLevel, complianceLevel);
}
/**
@@ -272,8 +383,29 @@
* indicating why the given name is discouraged,
* otherwise a status object indicating what is wrong with
* the name
+ * @deprecated Use {@link #validateJavaTypeName(String id, String sourceLevel, String complianceLevel)} instead
*/
public static IStatus validateJavaTypeName(String name) {
+ return validateJavaTypeName(name, CompilerOptions.VERSION_1_3,CompilerOptions.VERSION_1_3);
+ }
+
+ /**
+ * Validate the given Java type name, either simple or qualified, for the given source and compliance levels.
+ * For example, <code>"java.lang.Object"</code>, or <code>"Object"</code>.
+ * <p>
+ *
+ * @param name the name of a type
+ * @param sourceLevel the source level
+ * @param complianceLevel the compliance level
+ * @return a status object with code <code>IStatus.OK</code> if
+ * the given name is valid as a Java type name,
+ * a status with code <code>IStatus.WARNING</code>
+ * indicating why the given name is discouraged,
+ * otherwise a status object indicating what is wrong with
+ * the name
+ * @since 3.3
+ */
+ public static IStatus validateJavaTypeName(String name, String sourceLevel, String complianceLevel) {
if (name == null) {
return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.convention_type_nullName, null);
}
@@ -285,16 +417,16 @@
char[] scannedID;
if (index == -1) {
// simple name
- scannedID = scannedIdentifier(name);
+ scannedID = scannedIdentifier(name, sourceLevel, complianceLevel);
} else {
// qualified name
String pkg = name.substring(0, index).trim();
- IStatus status = validatePackageName(pkg);
+ IStatus status = validatePackageName(pkg, sourceLevel, complianceLevel);
if (!status.isOK()) {
return status;
}
String type = name.substring(index + 1).trim();
- scannedID = scannedIdentifier(type);
+ scannedID = scannedIdentifier(type, sourceLevel, complianceLevel);
}
if (scannedID != null) {
@@ -305,7 +437,7 @@
if (CharOperation.contains('$', scannedID)) {
return new Status(IStatus.WARNING, JavaCore.PLUGIN_ID, -1, Messages.convention_type_dollarName, null);
}
- if ((scannedID.length > 0 && Character.isLowerCase(scannedID[0]))) {
+ if ((scannedID.length > 0 && ScannerHelper.isLowerCase(scannedID[0]))) {
return new Status(IStatus.WARNING, JavaCore.PLUGIN_ID, -1, Messages.convention_type_lowercaseName, null);
}
return JavaModelStatus.VERIFIED_OK;
@@ -325,10 +457,29 @@
* @return a status object with code <code>IStatus.OK</code> if
* the given name is valid as a method name, otherwise a status
* object indicating what is wrong with the name
+ * @deprecated Use {@link #validateMethodName(String id, String sourceLevel, String complianceLevel)} instead
*/
public static IStatus validateMethodName(String name) {
-
- return validateIdentifier(name);
+ return validateMethodName(name, CompilerOptions.VERSION_1_3,CompilerOptions.VERSION_1_3);
+ }
+
+ /**
+ * Validate the given method name for the given source and compliance levels.
+ * The special names "<init>" and "<clinit>" are not valid.
+ * <p>
+ * The syntax for a method name is defined by Identifier
+ * of MethodDeclarator (JLS2 8.4). For example "println".
+ *
+ * @param name the name of a method
+ * @param sourceLevel the source level
+ * @param complianceLevel the compliance level
+ * @return a status object with code <code>IStatus.OK</code> if
+ * the given name is valid as a method name, otherwise a status
+ * object indicating what is wrong with the name
+ * @since 3.3
+ */
+ public static IStatus validateMethodName(String name, String sourceLevel, String complianceLevel) {
+ return validateIdentifier(name, sourceLevel,complianceLevel);
}
/**
@@ -346,8 +497,32 @@
* @return a status object with code <code>IStatus.OK</code> if
* the given name is valid as a package name, otherwise a status
* object indicating what is wrong with the name
+ * @deprecated Use {@link #validatePackageName(String id, String sourceLevel, String complianceLevel)} instead
*/
public static IStatus validatePackageName(String name) {
+ return validatePackageName(name, CompilerOptions.VERSION_1_3,CompilerOptions.VERSION_1_3);
+ }
+
+ /**
+ * Validate the given package name for the given source and compliance levels.
+ * <p>
+ * The syntax of a package name corresponds to PackageName as
+ * defined by PackageDeclaration (JLS2 7.4). For example, <code>"java.lang"</code>.
+ * <p>
+ * Note that the given name must be a non-empty package name (that is, attempting to
+ * validate the default package will return an error status.)
+ * Also it must not contain any characters or substrings that are not valid
+ * on the file system on which workspace root is located.
+ *
+ * @param name the name of a package
+ * @param sourceLevel the source level
+ * @param complianceLevel the compliance level
+ * @return a status object with code <code>IStatus.OK</code> if
+ * the given name is valid as a package name, otherwise a status
+ * object indicating what is wrong with the name
+ * @since 3.3
+ */
+ public static IStatus validatePackageName(String name, String sourceLevel, String complianceLevel) {
if (name == null) {
return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.convention_package_nullName, null);
@@ -375,7 +550,7 @@
while (st.hasMoreTokens()) {
String typeName = st.nextToken();
typeName = typeName.trim(); // grammar allows spaces
- char[] scannedID = scannedIdentifier(typeName);
+ char[] scannedID = scannedIdentifier(typeName, sourceLevel, complianceLevel);
if (scannedID == null) {
return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.bind(Messages.convention_illegalIdentifier, typeName), null);
}
@@ -383,7 +558,7 @@
if (!status.isOK()) {
return status;
}
- if (firstToken && scannedID.length > 0 && Character.isUpperCase(scannedID[0])) {
+ if (firstToken && scannedID.length > 0 && ScannerHelper.isUpperCase(scannedID[0])) {
if (warningStatus == null) {
warningStatus = new Status(IStatus.WARNING, JavaCore.PLUGIN_ID, -1, Messages.convention_package_uppercaseName, null);
}
@@ -444,7 +619,10 @@
* @since 2.0
*/
public static IJavaModelStatus validateClasspathEntry(IJavaProject project, IClasspathEntry entry, boolean checkSourceAttachment){
- return ClasspathEntry.validateClasspathEntry(project, entry, checkSourceAttachment, true/*recurse in container*/);
+ IJavaModelStatus status = ClasspathEntry.validateClasspathEntry(project, entry, checkSourceAttachment, true/*recurse in container*/);
+ if (status.getCode() == IJavaModelStatusConstants.INVALID_CLASSPATH && ((ClasspathEntry) entry).isOptional())
+ return JavaModelStatus.VERIFIED_OK;
+ return status;
}
/**
@@ -458,11 +636,30 @@
* the given name is valid as a type variable name, otherwise a status
* object indicating what is wrong with the name
* @since 3.1
+ * @deprecated Use {@link #validateTypeVariableName(String id, String sourceLevel, String complianceLevel)} instead
*/
public static IStatus validateTypeVariableName(String name) {
- return validateIdentifier(name);
+ return validateIdentifier(name, CompilerOptions.VERSION_1_3,CompilerOptions.VERSION_1_3);
}
-
+
+ /**
+ * Validate the given type variable name for the given source and compliance levels.
+ * <p>
+ * Syntax of a type variable name corresponds to a Java identifier (JLS3 4.3).
+ * For example, <code>"E"</code>.
+ *
+ * @param name the name of a type variable
+ * @param sourceLevel the source level
+ * @param complianceLevel the compliance level
+ * @return a status object with code <code>IStatus.OK</code> if
+ * the given name is valid as a type variable name, otherwise a status
+ * object indicating what is wrong with the name
+ * @since 3.3
+ */
+ public static IStatus validateTypeVariableName(String name, String sourceLevel, String complianceLevel) {
+ return validateIdentifier(name, sourceLevel, complianceLevel);
+ }
+
/**
* Validate that all compiler options of the given project match keys and values
* described in {@link JavaCore#getDefaultOptions()} method.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java
index ca7ccd5..27a3108 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -18,6 +18,7 @@
* IBM Corporation - added specific output location to source classpath entries
* IBM Corporation - added the following constants:
* CORE_JAVA_BUILD_CLEAN_OUTPUT_FOLDER
+ * CORE_JAVA_BUILD_RECREATE_MODIFIED_CLASS_FILES_IN_OUTPUT_FOLDER
* CLEAN
* IBM Corporation - added getClasspathContainerInitializer(String)
* IBM Corporation - added the following constants:
@@ -54,21 +55,62 @@
* COMPILER_PB_MISSING_JAVADOC_COMMENTS_OVERRIDING
* COMPILER_PB_DEPRECATION_WHEN_OVERRIDING_DEPRECATED_METHOD
* COMPILER_PB_UNUSED_DECLARED_THROWN_EXCEPTION_WHEN_OVERRIDING
+ * IBM Corporation - added the following constants:
+ * TIMEOUT_FOR_PARAMETER_NAME_FROM_ATTACHED_JAVADOC
+ * IBM Corporation - added the following constants:
+ * COMPILER_PB_FALLTHROUGH_CASE
+ * COMPILER_PB_PARAMETER_ASSIGNMENT
+ * COMPILER_PB_NULL_REFERENCE
+ * IBM Corporation - added the following constants:
+ * CODEASSIST_DEPRECATION_CHECK
+ * IBM Corporation - added the following constants:
+ * COMPILER_PB_POTENTIAL_NULL_REFERENCE
+ * COMPILER_PB_REDUNDANT_NULL_CHECK
+ * IBM Corporation - added the following constants:
+ * COMPILER_PB_UNUSED_PARAMETER_INCLUDE_DOC_COMMENT_REFERENCE
*******************************************************************************/
package org.eclipse.jdt.core;
import java.io.File;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
-import org.eclipse.core.resources.*;
-import org.eclipse.core.runtime.*;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IMarkerDelta;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
-import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.search.IJavaSearchConstants;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.core.search.SearchPattern;
import org.eclipse.jdt.core.search.TypeNameRequestor;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
import org.eclipse.jdt.internal.core.*;
import org.eclipse.jdt.internal.core.builder.JavaBuilder;
@@ -89,14 +131,16 @@
* </p>
* <p>
* The single instance of this class can be accessed from any plug-in declaring
- * the Java model plug-in as a prerequisite via
+ * the Java model plug-in as a prerequisite via
* <code>JavaCore.getJavaCore()</code>. The Java model plug-in will be activated
* automatically if not already active.
* </p>
*/
public final class JavaCore extends Plugin {
- private static Plugin JAVA_CORE_PLUGIN = null;
+ private static final IResource[] NO_GENERATED_RESOURCES = new IResource[0];
+
+ private static Plugin JAVA_CORE_PLUGIN = null;
/**
* The plug-in identifier of the Java core support
* (value <code>"org.eclipse.jdt.core"</code>).
@@ -118,7 +162,7 @@
/**
* The identifier for the Java nature
* (value <code>"org.eclipse.jdt.core.javanature"</code>).
- * The presence of this nature on a project indicates that it is
+ * The presence of this nature on a project indicates that it is
* Java-capable.
*
* @see org.eclipse.core.resources.IProject#hasNature(java.lang.String)
@@ -136,7 +180,7 @@
* @since 3.0
*/
public static final String USER_LIBRARY_CONTAINER_ID= "org.eclipse.jdt.USER_LIBRARY"; //$NON-NLS-1$
-
+
// *************** Possible IDs for configurable options. ********************
/**
@@ -245,6 +289,12 @@
/**
* Possible configurable option ID.
* @see #getDefaultOptions()
+ * @since 3.3
+ */
+ public static final String COMPILER_PB_UNUSED_PARAMETER_INCLUDE_DOC_COMMENT_REFERENCE = PLUGIN_ID + ".compiler.problem.unusedParameterIncludeDocCommentReference"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
* @since 2.0
*/
public static final String COMPILER_PB_UNUSED_IMPORT = PLUGIN_ID + ".compiler.problem.unusedImport"; //$NON-NLS-1$
@@ -334,6 +384,12 @@
/**
* Possible configurable option ID.
* @see #getDefaultOptions()
+ * @since 3.2
+ */
+ public static final String COMPILER_PB_FALLTHROUGH_CASE = PLUGIN_ID + ".compiler.problem.fallthroughCase"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
* @since 3.0
*/
public static final String COMPILER_PB_EMPTY_STATEMENT = PLUGIN_ID + ".compiler.problem.emptyStatement"; //$NON-NLS-1$
@@ -401,6 +457,12 @@
/**
* Possible configurable option ID.
* @see #getDefaultOptions()
+ * @since 3.2
+ */
+ public static final String COMPILER_PB_RAW_TYPE_REFERENCE = PLUGIN_ID + ".compiler.problem.rawTypeReference"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
* @since 3.1
*/
public static final String COMPILER_PB_FINAL_PARAMETER_BOUND = PLUGIN_ID + ".compiler.problem.finalParameterBound"; //$NON-NLS-1$
@@ -448,13 +510,19 @@
public static final String COMPILER_PB_INCOMPLETE_ENUM_SWITCH = PLUGIN_ID + ".compiler.problem.incompleteEnumSwitch"; //$NON-NLS-1$
/**
* Possible configurable option ID.
- * @see #getDefaultOptions()
* @since 3.1
+ * @deprecated use {@link #COMPILER_PB_NULL_REFERENCE} instead
*/
public static final String COMPILER_PB_INCONSISTENT_NULL_CHECK = PLUGIN_ID + ".compiler.problem.inconsistentNullCheck"; //$NON-NLS-1$
/**
* Possible configurable option ID.
* @see #getDefaultOptions()
+ * @since 3.2
+ */
+ public static final String COMPILER_PB_UNUSED_LABEL = PLUGIN_ID + ".compiler.problem.unusedLabel"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
* @since 3.0
*/
public static final String COMPILER_PB_INVALID_JAVADOC = PLUGIN_ID + ".compiler.problem.invalidJavadoc"; //$NON-NLS-1$
@@ -533,6 +601,18 @@
/**
* Possible configurable option ID.
* @see #getDefaultOptions()
+ * @since 3.2
+ */
+ public static final String COMPILER_PB_FATAL_OPTIONAL_ERROR = PLUGIN_ID + ".compiler.problem.fatalOptionalError"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ * @since 3.2
+ */
+ public static final String COMPILER_PB_PARAMETER_ASSIGNMENT = PLUGIN_ID + ".compiler.problem.parameterAssignment"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
* @since 2.0
*/
public static final String COMPILER_SOURCE = PLUGIN_ID + ".compiler.source"; //$NON-NLS-1$
@@ -577,7 +657,7 @@
* @see #getDefaultOptions()
* @since 3.0
*/
- public static final String COMPILER_TASK_CASE_SENSITIVE = PLUGIN_ID + ".compiler.taskCaseSensitive"; //$NON-NLS-1$
+ public static final String COMPILER_TASK_CASE_SENSITIVE = PLUGIN_ID + ".compiler.taskCaseSensitive"; //$NON-NLS-1$
/**
* Possible configurable option ID.
* @see #getDefaultOptions()
@@ -605,6 +685,30 @@
/**
* Possible configurable option ID.
* @see #getDefaultOptions()
+ * @since 3.2
+ */
+ public static final String COMPILER_PB_NULL_REFERENCE = PLUGIN_ID + ".compiler.problem.nullReference"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ * @since 3.3
+ */
+ public static final String COMPILER_PB_POTENTIAL_NULL_REFERENCE = PLUGIN_ID + ".compiler.problem.potentialNullReference"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ * @since 3.3
+ */
+ public static final String COMPILER_PB_REDUNDANT_NULL_CHECK = PLUGIN_ID + ".compiler.problem.redundantNullCheck"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ * @since 3.3
+ */
+ public static final String COMPILER_PB_OVERRIDING_METHOD_WITHOUT_SUPER_INVOCATION = PLUGIN_ID + ".compiler.problem.overridingMethodWithoutSuperInvocation"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
*/
public static final String CORE_JAVA_BUILD_ORDER = PLUGIN_ID + ".computeJavaBuildOrder"; //$NON-NLS-1$
/**
@@ -624,7 +728,13 @@
* @see #getDefaultOptions()
* @since 2.1
*/
- public static final String CORE_JAVA_BUILD_CLEAN_OUTPUT_FOLDER = PLUGIN_ID + ".builder.cleanOutputFolder"; //$NON-NLS-1$
+ public static final String CORE_JAVA_BUILD_CLEAN_OUTPUT_FOLDER = PLUGIN_ID + ".builder.cleanOutputFolder"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ * @since 3.2
+ */
+ public static final String CORE_JAVA_BUILD_RECREATE_MODIFIED_CLASS_FILES_IN_OUTPUT_FOLDER = PLUGIN_ID + ".builder.recreateModifiedClassFileInOutputFolder"; //$NON-NLS-1$
/**
* Possible configurable option ID.
* @see #getDefaultOptions()
@@ -658,7 +768,7 @@
/**
* Possible configurable option ID.
* @see #getDefaultOptions()
- * @since 2.1
+ * @since 2.1
*/
public static final String CORE_ENABLE_CLASSPATH_EXCLUSION_PATTERNS = PLUGIN_ID + ".classpath.exclusionPatterns"; //$NON-NLS-1$
/**
@@ -669,13 +779,13 @@
public static final String CORE_ENABLE_CLASSPATH_MULTIPLE_OUTPUT_LOCATIONS = PLUGIN_ID + ".classpath.multipleOutputLocations"; //$NON-NLS-1$
/**
* Default task tag
- * @deprecated - should use #DEFAULT_TASK_TAGS instead
+ * @deprecated Use {@link #DEFAULT_TASK_TAGS} instead
* @since 2.1
*/
public static final String DEFAULT_TASK_TAG = "TODO"; //$NON-NLS-1$
/**
* Default task priority
- * @deprecated - should use #DEFAULT_TASK_PRIORITIES instead
+ * @deprecated Use {@link #DEFAULT_TASK_PRIORITIES} instead
* @since 2.1
*/
public static final String DEFAULT_TASK_PRIORITY = "NORMAL"; //$NON-NLS-1$
@@ -776,6 +886,18 @@
/**
* Possible configurable option ID.
* @see #getDefaultOptions()
+ * @since 3.2
+ */
+ public static final String CODEASSIST_DEPRECATION_CHECK = PLUGIN_ID + ".codeComplete.deprecationCheck"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ * @since 3.2
+ */
+ public static final String CODEASSIST_CAMEL_CASE_MATCH = PLUGIN_ID + ".codeComplete.camelCaseMatch"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
* @since 2.0
*/
public static final String CODEASSIST_IMPLICIT_QUALIFICATION = PLUGIN_ID + ".codeComplete.forceImplicitQualification"; //$NON-NLS-1$
@@ -839,9 +961,19 @@
* @since 3.1
*/
public static final String CODEASSIST_DISCOURAGED_REFERENCE_CHECK= PLUGIN_ID + ".codeComplete.discouragedReferenceCheck"; //$NON-NLS-1$
-
- // *************** Possible values for configurable options. ********************
-
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ * @since 3.3
+ */
+ public static final String CODEASSIST_SUGGEST_STATIC_IMPORTS= PLUGIN_ID + ".codeComplete.suggestStaticImports"; //$NON-NLS-1$
+ /**
+ * Possible configurable option ID.
+ * @see #getDefaultOptions()
+ * @since 3.2
+ */
+ public static final String TIMEOUT_FOR_PARAMETER_NAME_FROM_ATTACHED_JAVADOC = PLUGIN_ID + ".timeoutForParameterNameFromAttachedJavadoc"; //$NON-NLS-1$
+
/**
* Possible configurable option value.
* @see #getDefaultOptions()
@@ -893,6 +1025,18 @@
/**
* Possible configurable option value.
* @see #getDefaultOptions()
+ * @since 3.2
+ */
+ public static final String VERSION_1_6 = "1.6"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions()
+ * @since 3.3
+ */
+ public static final String VERSION_1_7 = "1.7"; //$NON-NLS-1$
+ /**
+ * Possible configurable option value.
+ * @see #getDefaultOptions()
* @since 2.0
*/
public static final String ABORT = "abort"; //$NON-NLS-1$
@@ -1014,12 +1158,22 @@
public static final String NEVER = "never"; //$NON-NLS-1$
/**
+ * Value of the content-type for Java source files. Use this value to retrieve the Java content type
+ * from the content type manager, and to add new Java-like extensions to this content type.
+ *
+ * @see org.eclipse.core.runtime.content.IContentTypeManager#getContentType(String)
+ * @see #getJavaLikeExtensions()
+ * @since 3.2
+ */
+ public static final String JAVA_SOURCE_CONTENT_TYPE = JavaCore.PLUGIN_ID+".javaSource" ; //$NON-NLS-1$
+
+ /**
* Creates the Java core plug-in.
* <p>
- * The plug-in instance is created automatically by the
+ * The plug-in instance is created automatically by the
* Eclipse platform. Clients must not call.
* </p>
- *
+ *
* @since 3.0
*/
public JavaCore() {
@@ -1035,7 +1189,7 @@
* and any reconcile operation (POST_RECONCILE).
* For finer control of the notification, use <code>addElementChangedListener(IElementChangedListener,int)</code>,
* which allows to specify a different eventMask.
- *
+ *
* @param listener the listener
* @see ElementChangedEvent
*/
@@ -1048,20 +1202,20 @@
* Has no effect if an identical listener is already registered.
* After completion of this method, the given listener will be registered for exactly
* the specified events. If they were previously registered for other events, they
- * will be deregistered.
+ * will be deregistered.
* <p>
* Once registered, a listener starts receiving notification of changes to
- * java elements in the model. The listener continues to receive
- * notifications until it is replaced or removed.
+ * java elements in the model. The listener continues to receive
+ * notifications until it is replaced or removed.
* </p>
* <p>
* Listeners can listen for several types of event as defined in <code>ElementChangeEvent</code>.
* Clients are free to register for any number of event types however if they register
* for more than one, it is their responsibility to ensure they correctly handle the
- * case where the same java element change shows up in multiple notifications.
+ * case where the same java element change shows up in multiple notifications.
* Clients are guaranteed to receive only the events for which they are registered.
* </p>
- *
+ *
* @param listener the listener
* @param eventMask the bit-wise OR of all event types of interest to the listener
* @see IElementChangedListener
@@ -1089,23 +1243,83 @@
if (attributes != null && element != null)
attributes.put(ATT_HANDLE_ID, element.getHandleIdentifier());
}
-
+
+ private static void addNonJavaResources(Object[] nonJavaResources,
+ IContainer container,
+ int rootPathSegmentCounts,
+ ArrayList collector) {
+ for (int i = 0, max = nonJavaResources.length; i < max; i++) {
+ Object nonJavaResource = nonJavaResources[i];
+ if (nonJavaResource instanceof IFile) {
+ IFile file = (IFile) nonJavaResource;
+ IPath path = file.getFullPath().removeFirstSegments(rootPathSegmentCounts);
+ IResource member = container.findMember(path);
+ if (member != null && member.exists()) {
+ collector.add(member);
+ }
+ } else if (nonJavaResource instanceof IFolder) {
+ IFolder folder = (IFolder) nonJavaResource;
+ IResource[] members = null;
+ try {
+ members = folder.members();
+ } catch (CoreException e) {
+ // ignore
+ }
+ if (members != null) {
+ addNonJavaResources(members, container, rootPathSegmentCounts, collector);
+ }
+ }
+ }
+ }
+
/**
- * Adds the given listener for POST_CHANGE resource change events to the Java core.
- * The listener is guarantied to be notified of the POST_CHANGE resource change event before
+ * Adds the given listener for POST_CHANGE resource change events to the Java core.
+ * The listener is guaranteed to be notified of the POST_CHANGE resource change event before
* the Java core starts processing the resource change event itself.
* <p>
* Has no effect if an identical listener is already registered.
* </p>
- *
+ *
* @param listener the listener
* @see #removePreProcessingResourceChangedListener(IResourceChangeListener)
* @since 3.0
+ * @deprecated use addPreProcessingResourceChangedListener(listener, IResourceChangeEvent.POST_CHANGE) instead
*/
public static void addPreProcessingResourceChangedListener(IResourceChangeListener listener) {
- JavaModelManager.getJavaModelManager().deltaState.addPreResourceChangedListener(listener);
+ addPreProcessingResourceChangedListener(listener, IResourceChangeEvent.POST_CHANGE);
}
-
+
+ /**
+ * Adds the given listener for resource change events of the given types to the Java core.
+ * The listener is guaranteed to be notified of the resource change event before
+ * the Java core starts processing the resource change event itself.
+ * <p>
+ * If an identical listener is already registered, the given event types are added to the event types
+ * of interest to the listener.
+ * </p>
+ * <p>
+ * Supported event types are:
+ * <ul>
+ * <li>{@link IResourceChangeEvent#PRE_BUILD}</li>
+ * <li>{@link IResourceChangeEvent#POST_BUILD}</li>
+ * <li>{@link IResourceChangeEvent#POST_CHANGE}</li>
+ * <li>{@link IResourceChangeEvent#PRE_DELETE}</li>
+ * <li>{@link IResourceChangeEvent#PRE_CLOSE}</li>
+ * </ul>
+ * This list may increase in the future.
+ * </p>
+ *
+ * @param listener the listener
+ * @param eventMask the bit-wise OR of all event types of interest to the
+ * listener
+ * @see #removePreProcessingResourceChangedListener(IResourceChangeListener)
+ * @see IResourceChangeEvent
+ * @since 3.2
+ */
+ public static void addPreProcessingResourceChangedListener(IResourceChangeListener listener, int eventMask) {
+ JavaModelManager.getJavaModelManager().deltaState.addPreResourceChangedListener(listener, eventMask);
+ }
+
/**
* Configures the given marker for the given Java element.
* Used for markers, which denote a Java element rather than a resource.
@@ -1121,12 +1335,12 @@
if (marker != null && element != null)
marker.setAttribute(ATT_HANDLE_ID, element.getHandleIdentifier());
}
-
+
/**
* Returns the Java model element corresponding to the given handle identifier
* generated by <code>IJavaElement.getHandleIdentifier()</code>, or
* <code>null</code> if unable to create the associated element.
- *
+ *
* @param handleIdentifier the given handle identifier
* @return the Java element corresponding to the handle identifier
*/
@@ -1139,9 +1353,9 @@
* generated by <code>IJavaElement.getHandleIdentifier()</code>, or
* <code>null</code> if unable to create the associated element.
* If the returned Java element is an <code>ICompilationUnit</code>, its owner
- * is the given owner if such a working copy exists, otherwise the compilation unit
+ * is the given owner if such a working copy exists, otherwise the compilation unit
* is a primary compilation unit.
- *
+ *
* @param handleIdentifier the given handle identifier
* @param owner the owner of the returned compilation unit, ignored if the returned
* element is not a compilation unit
@@ -1156,21 +1370,22 @@
JavaModel model = JavaModelManager.getJavaModelManager().getJavaModel();
return model.getHandleFromMemento(memento, owner);
}
-
+
/**
* Returns the Java element corresponding to the given file, or
* <code>null</code> if unable to associate the given file
* with a Java element.
*
* <p>The file must be one of:<ul>
- * <li>a <code>.java</code> file - the element returned is the corresponding <code>ICompilationUnit</code></li>
+ * <li>a file with one of the {@link JavaCore#getJavaLikeExtensions()
+ * Java-like extensions} - the element returned is the corresponding <code>ICompilationUnit</code></li>
* <li>a <code>.class</code> file - the element returned is the corresponding <code>IClassFile</code></li>
* <li>a <code>.jar</code> file - the element returned is the corresponding <code>IPackageFragmentRoot</code></li>
* </ul>
* <p>
* Creating a Java element has the side effect of creating and opening all of the
* element's parents if they are not yet open.
- *
+ *
* @param file the given file
* @return the Java element corresponding to the given file, or
* <code>null</code> if unable to associate the given file
@@ -1187,7 +1402,7 @@
* <p>
* Creating a Java element has the side effect of creating and opening all of the
* element's parents if they are not yet open.
- *
+ *
* @param folder the given folder
* @return the package fragment or package fragment root corresponding to the given folder, or
* <code>null</code> if unable to associate the given folder with a Java element
@@ -1202,7 +1417,7 @@
* project's parents if they are not yet open.
* <p>
* Note that no check is done at this time on the existence or the java nature of this project.
- *
+ *
* @param project the given project
* @return the Java project corresponding to the given project, null if the given project is null
*/
@@ -1220,7 +1435,8 @@
* <p>
* The resource must be one of:<ul>
* <li>a project - the element returned is the corresponding <code>IJavaProject</code></li>
- * <li>a <code>.java</code> file - the element returned is the corresponding <code>ICompilationUnit</code></li>
+ * <li>a file with one of the {@link JavaCore#getJavaLikeExtensions()
+ * Java-like extensions} - the element returned is the corresponding <code>ICompilationUnit</code></li>
* <li>a <code>.class</code> file - the element returned is the corresponding <code>IClassFile</code></li>
* <li>a <code>.jar</code> file - the element returned is the corresponding <code>IPackageFragmentRoot</code></li>
* <li>a folder - the element returned is the corresponding <code>IPackageFragmentRoot</code>
@@ -1230,7 +1446,7 @@
* <p>
* Creating a Java element has the side effect of creating and opening all of the
* element's parents if they are not yet open.
- *
+ *
* @param resource the given resource
* @return the Java element corresponding to the given resource, or
* <code>null</code> if unable to associate the given resource
@@ -1240,8 +1456,36 @@
return JavaModelManager.create(resource, null/*unknown java project*/);
}
/**
+ * Returns the Java element corresponding to the given file, its project being the given
+ * project. Returns <code>null</code> if unable to associate the given resource
+ * with a Java element.
+ *<p>
+ * The resource must be one of:<ul>
+ * <li>a project - the element returned is the corresponding <code>IJavaProject</code></li>
+ * <li>a file with one of the {@link JavaCore#getJavaLikeExtensions()
+ * Java-like extensions} - the element returned is the corresponding <code>ICompilationUnit</code></li>
+ * <li>a <code>.class</code> file - the element returned is the corresponding <code>IClassFile</code></li>
+ * <li>a <code>.jar</code> file - the element returned is the corresponding <code>IPackageFragmentRoot</code></li>
+ * <li>a folder - the element returned is the corresponding <code>IPackageFragmentRoot</code>
+ * or <code>IPackageFragment</code></li>
+ * <li>the workspace root resource - the element returned is the <code>IJavaModel</code></li>
+ * </ul>
+ * <p>
+ * Creating a Java element has the side effect of creating and opening all of the
+ * element's parents if they are not yet open.
+ *
+ * @param resource the given resource
+ * @return the Java element corresponding to the given file, or
+ * <code>null</code> if unable to associate the given file
+ * with a Java element
+ * @since 3.3
+ */
+ public static IJavaElement create(IResource resource, IJavaProject project) {
+ return JavaModelManager.create(resource, project);
+ }
+ /**
* Returns the Java model.
- *
+ *
* @param root the given root
* @return the Java model, or <code>null</code> if the root is null
*/
@@ -1255,7 +1499,7 @@
* Creates and returns a class file element for
* the given <code>.class</code> file. Returns <code>null</code> if unable
* to recognize the class file.
- *
+ *
* @param file the given <code>.class</code> file
* @return a class file element for the given <code>.class</code> file, or <code>null</code> if unable
* to recognize the class file
@@ -1265,11 +1509,12 @@
}
/**
* Creates and returns a compilation unit element for
- * the given <code>.java</code> file. Returns <code>null</code> if unable
+ * the given source file (i.e. a file with one of the {@link JavaCore#getJavaLikeExtensions()
+ * Java-like extensions}). Returns <code>null</code> if unable
* to recognize the compilation unit.
- *
- * @param file the given <code>.java</code> file
- * @return a compilation unit element for the given <code>.java</code> file, or <code>null</code> if unable
+ *
+ * @param file the given source file
+ * @return a compilation unit element for the given source file, or <code>null</code> if unable
* to recognize the compilation unit
*/
public static ICompilationUnit createCompilationUnitFrom(IFile file) {
@@ -1278,8 +1523,8 @@
/**
* Creates and returns a handle for the given JAR file.
* The Java model associated with the JAR's project may be
- * created as a side effect.
- *
+ * created as a side effect.
+ *
* @param file the given JAR file
* @return a handle for the given JAR file, or <code>null</code> if unable to create a JAR package fragment root.
* (for example, if the JAR file represents a non-Java resource)
@@ -1288,33 +1533,33 @@
return JavaModelManager.createJarPackageFragmentRootFrom(file, null/*unknown java project*/);
}
- /**
+ /**
* Answers the project specific value for a given classpath container.
* In case this container path could not be resolved, then will answer <code>null</code>.
* Both the container path and the project context are supposed to be non-null.
* <p>
- * The containerPath is a formed by a first ID segment followed with extra segments, which can be
- * used as additional hints for resolution. If no container was ever recorded for this container path
- * onto this project (using <code>setClasspathContainer</code>, then a
- * <code>ClasspathContainerInitializer</code> will be activated if any was registered for this container
+ * The containerPath is a formed by a first ID segment followed with extra segments, which can be
+ * used as additional hints for resolution. If no container was ever recorded for this container path
+ * onto this project (using <code>setClasspathContainer</code>, then a
+ * <code>ClasspathContainerInitializer</code> will be activated if any was registered for this container
* ID onto the extension point "org.eclipse.jdt.core.classpathContainerInitializer".
* <p>
* There is no assumption that the returned container must answer the exact same containerPath
- * when requested <code>IClasspathContainer#getPath</code>.
+ * when requested <code>IClasspathContainer#getPath</code>.
* Indeed, the containerPath is just an indication for resolving it to an actual container object.
* <p>
- * Classpath container values are persisted locally to the workspace, but
- * are not preserved from a session to another. It is thus highly recommended to register a
- * <code>ClasspathContainerInitializer</code> for each referenced container
+ * Classpath container values are persisted locally to the workspace, but
+ * are not preserved from a session to another. It is thus highly recommended to register a
+ * <code>ClasspathContainerInitializer</code> for each referenced container
* (through the extension point "org.eclipse.jdt.core.ClasspathContainerInitializer").
* <p>
* @param containerPath the name of the container, which needs to be resolved
* @param project a specific project in which the container is being resolved
* @return the corresponding classpath container or <code>null</code> if unable to find one.
- *
+ *
* @exception JavaModelException if an exception occurred while resolving the container, or if the resolved container
- * contains illegal entries (contains CPE_CONTAINER entries or null entries).
- *
+ * contains illegal entries (contains CPE_CONTAINER entries or null entries).
+ *
* @see ClasspathContainerInitializer
* @see IClasspathContainer
* @see #setClasspathContainer(IPath, IJavaProject[], IClasspathContainer[], IProgressMonitor)
@@ -1327,18 +1572,18 @@
if (container == JavaModelManager.CONTAINER_INITIALIZATION_IN_PROGRESS) {
return manager.getPreviousSessionContainer(containerPath, project);
}
- return container;
+ return container;
}
/**
- * Helper method finding the classpath container initializer registered for a given classpath container ID
+ * Helper method finding the classpath container initializer registered for a given classpath container ID
* or <code>null</code> if none was found while iterating over the contributions to extension point to
* the extension point "org.eclipse.jdt.core.classpathContainerInitializer".
* <p>
* A containerID is the first segment of any container path, used to identify the registered container initializer.
* <p>
* @param containerID - a containerID identifying a registered initializer
- * @return ClasspathContainerInitializer - the registered classpath container initializer or <code>null</code> if
+ * @return ClasspathContainerInitializer - the registered classpath container initializer or <code>null</code> if
* none was found.
* @since 2.1
*/
@@ -1364,42 +1609,50 @@
for(int i = 0; i < extensions.length; i++){
IConfigurationElement [] configElements = extensions[i].getConfigurationElements();
for(int j = 0; j < configElements.length; j++){
- String initializerID = configElements[j].getAttribute("id"); //$NON-NLS-1$
+ IConfigurationElement configurationElement = configElements[j];
+ String initializerID = configurationElement.getAttribute("id"); //$NON-NLS-1$
if (initializerID != null && initializerID.equals(containerID)){
- if (JavaModelManager.CP_RESOLVE_VERBOSE) {
- Util.verbose(
- "CPContainer INIT - found initializer\n" + //$NON-NLS-1$
- " container ID: " + containerID + '\n' + //$NON-NLS-1$
- " class: " + configElements[j].getAttribute("class")); //$NON-NLS-1$ //$NON-NLS-2$
- }
+ if (JavaModelManager.CP_RESOLVE_VERBOSE_ADVANCED)
+ verbose_found_container_initializer(containerID, configurationElement);
try {
- Object execExt = configElements[j].createExecutableExtension("class"); //$NON-NLS-1$
+ Object execExt = configurationElement.createExecutableExtension("class"); //$NON-NLS-1$
if (execExt instanceof ClasspathContainerInitializer){
return (ClasspathContainerInitializer)execExt;
}
} catch(CoreException e) {
// executable extension could not be created: ignore this initializer
if (JavaModelManager.CP_RESOLVE_VERBOSE) {
- Util.verbose(
- "CPContainer INIT - failed to instanciate initializer\n" + //$NON-NLS-1$
- " container ID: " + containerID + '\n' + //$NON-NLS-1$
- " class: " + configElements[j].getAttribute("class"), //$NON-NLS-1$ //$NON-NLS-2$
- System.err);
+ verbose_failed_to_instanciate_container_initializer(containerID, configurationElement);
e.printStackTrace();
- }
+ }
}
}
}
- }
+ }
}
return null;
}
+ private static void verbose_failed_to_instanciate_container_initializer(String containerID, IConfigurationElement configurationElement) {
+ Util.verbose(
+ "CPContainer INIT - failed to instanciate initializer\n" + //$NON-NLS-1$
+ " container ID: " + containerID + '\n' + //$NON-NLS-1$
+ " class: " + configurationElement.getAttribute("class"), //$NON-NLS-1$ //$NON-NLS-2$
+ System.err);
+ }
+
+ private static void verbose_found_container_initializer(String containerID, IConfigurationElement configurationElement) {
+ Util.verbose(
+ "CPContainer INIT - found initializer\n" + //$NON-NLS-1$
+ " container ID: " + containerID + '\n' + //$NON-NLS-1$
+ " class: " + configurationElement.getAttribute("class")); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
/**
* Returns the path held in the given classpath variable.
- * Returns <node>null</code> if unable to bind.
+ * Returns <code>null</code> if unable to bind.
* <p>
- * Classpath variable values are persisted locally to the workspace, and
+ * Classpath variable values are persisted locally to the workspace, and
* are preserved from session to session.
* <p>
* Note that classpath variables can be contributed registered initializers for,
@@ -1409,7 +1662,7 @@
* each session.
*
* @param variableName the name of the classpath variable
- * @return the path, or <code>null</code> if none
+ * @return the path, or <code>null</code> if none
* @see #setClasspathVariable(String, IPath)
*/
public static IPath getClasspathVariable(final String variableName) {
@@ -1419,73 +1672,101 @@
if (variablePath == JavaModelManager.VARIABLE_INITIALIZATION_IN_PROGRESS){
return manager.getPreviousSessionVariable(variableName);
}
-
+
if (variablePath != null) {
+ if (variablePath == JavaModelManager.CP_ENTRY_IGNORE_PATH)
+ return null;
return variablePath;
}
// even if persisted value exists, initializer is given priority, only if no initializer is found the persisted value is reused
final ClasspathVariableInitializer initializer = JavaCore.getClasspathVariableInitializer(variableName);
if (initializer != null){
- if (JavaModelManager.CP_RESOLVE_VERBOSE){
- Util.verbose(
- "CPVariable INIT - triggering initialization\n" + //$NON-NLS-1$
- " variable: " + variableName + '\n' + //$NON-NLS-1$
- " initializer: " + initializer + '\n' + //$NON-NLS-1$
- " invocation stack trace:"); //$NON-NLS-1$
- new Exception("<Fake exception>").printStackTrace(System.out); //$NON-NLS-1$
- }
- JavaModelManager.getJavaModelManager().variablePut(variableName, JavaModelManager.VARIABLE_INITIALIZATION_IN_PROGRESS); // avoid initialization cycles
+ if (JavaModelManager.CP_RESOLVE_VERBOSE)
+ verbose_triggering_variable_initialization(variableName, initializer);
+ if (JavaModelManager.CP_RESOLVE_VERBOSE_ADVANCED)
+ verbose_triggering_variable_initialization_invocation_trace();
+ manager.variablePut(variableName, JavaModelManager.VARIABLE_INITIALIZATION_IN_PROGRESS); // avoid initialization cycles
boolean ok = false;
try {
// let OperationCanceledException go through
// (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=59363)
initializer.initialize(variableName);
-
- variablePath = JavaModelManager.getJavaModelManager().variableGet(variableName); // initializer should have performed side-effect
+
+ variablePath = manager.variableGet(variableName); // initializer should have performed side-effect
if (variablePath == JavaModelManager.VARIABLE_INITIALIZATION_IN_PROGRESS) return null; // break cycle (initializer did not init or reentering call)
- if (JavaModelManager.CP_RESOLVE_VERBOSE){
- Util.verbose(
- "CPVariable INIT - after initialization\n" + //$NON-NLS-1$
- " variable: " + variableName +'\n' + //$NON-NLS-1$
- " variable path: " + variablePath); //$NON-NLS-1$
- }
+ if (JavaModelManager.CP_RESOLVE_VERBOSE_ADVANCED)
+ verbose_variable_value_after_initialization(variableName, variablePath);
+ manager.variablesWithInitializer.add(variableName);
ok = true;
} catch (RuntimeException e) {
- if (JavaModelManager.CP_RESOLVE_VERBOSE) {
+ if (JavaModelManager.CP_RESOLVE_VERBOSE)
e.printStackTrace();
- }
throw e;
} catch (Error e) {
- if (JavaModelManager.CP_RESOLVE_VERBOSE) {
+ if (JavaModelManager.CP_RESOLVE_VERBOSE)
e.printStackTrace();
- }
throw e;
} finally {
if (!ok) JavaModelManager.getJavaModelManager().variablePut(variableName, null); // flush cache
}
} else {
- if (JavaModelManager.CP_RESOLVE_VERBOSE){
- Util.verbose(
- "CPVariable INIT - no initializer found\n" + //$NON-NLS-1$
- " variable: " + variableName); //$NON-NLS-1$
- }
+ if (JavaModelManager.CP_RESOLVE_VERBOSE_ADVANCED)
+ verbose_no_variable_initializer_found(variableName);
}
return variablePath;
}
+ private static void verbose_no_variable_initializer_found(String variableName) {
+ Util.verbose(
+ "CPVariable INIT - no initializer found\n" + //$NON-NLS-1$
+ " variable: " + variableName); //$NON-NLS-1$
+ }
+
+ private static void verbose_variable_value_after_initialization(String variableName, IPath variablePath) {
+ Util.verbose(
+ "CPVariable INIT - after initialization\n" + //$NON-NLS-1$
+ " variable: " + variableName +'\n' + //$NON-NLS-1$
+ " variable path: " + variablePath); //$NON-NLS-1$
+ }
+
+ private static void verbose_triggering_variable_initialization(String variableName, ClasspathVariableInitializer initializer) {
+ Util.verbose(
+ "CPVariable INIT - triggering initialization\n" + //$NON-NLS-1$
+ " variable: " + variableName + '\n' + //$NON-NLS-1$
+ " initializer: " + initializer); //$NON-NLS-1$
+ }
+
+ private static void verbose_triggering_variable_initialization_invocation_trace() {
+ Util.verbose(
+ "CPVariable INIT - triggering initialization\n" + //$NON-NLS-1$
+ " invocation trace:"); //$NON-NLS-1$
+ new Exception("<Fake exception>").printStackTrace(System.out); //$NON-NLS-1$
+ }
+
/**
- * Helper method finding the classpath variable initializer registered for a given classpath variable name
+ * Returns deprecation message of a given classpath variable.
+ *
+ * @param variableName
+ * @return A string if the classpath variable is deprecated, <code>null</code> otherwise.
+ * @since 3.3
+ */
+ public static String getClasspathVariableDeprecationMessage(String variableName) {
+ return (String) JavaModelManager.getJavaModelManager().deprecatedVariables.get(variableName);
+ }
+
+ /**
+ * Helper method finding the classpath variable initializer registered for a given classpath variable name
* or <code>null</code> if none was found while iterating over the contributions to extension point to
* the extension point "org.eclipse.jdt.core.classpathVariableInitializer".
* <p>
* @param variable the given variable
- * @return ClasspathVariableInitializer - the registered classpath variable initializer or <code>null</code> if
+ * @return ClasspathVariableInitializer - the registered classpath variable initializer or <code>null</code> if
* none was found.
* @since 2.1
*/
public static ClasspathVariableInitializer getClasspathVariableInitializer(String variable){
-
+
Plugin jdtCorePlugin = JavaCore.getPlugin();
if (jdtCorePlugin == null) return null;
@@ -1495,41 +1776,58 @@
for(int i = 0; i < extensions.length; i++){
IConfigurationElement [] configElements = extensions[i].getConfigurationElements();
for(int j = 0; j < configElements.length; j++){
+ IConfigurationElement configElement = configElements[j];
try {
- String varAttribute = configElements[j].getAttribute("variable"); //$NON-NLS-1$
+ String varAttribute = configElement.getAttribute("variable"); //$NON-NLS-1$
if (variable.equals(varAttribute)) {
- if (JavaModelManager.CP_RESOLVE_VERBOSE) {
- Util.verbose(
- "CPVariable INIT - found initializer\n" + //$NON-NLS-1$
- " variable: " + variable + '\n' + //$NON-NLS-1$
- " class: " + configElements[j].getAttribute("class")); //$NON-NLS-1$ //$NON-NLS-2$
- }
- Object execExt = configElements[j].createExecutableExtension("class"); //$NON-NLS-1$
+ if (JavaModelManager.CP_RESOLVE_VERBOSE_ADVANCED)
+ verbose_found_variable_initializer(variable, configElement);
+ Object execExt = configElement.createExecutableExtension("class"); //$NON-NLS-1$
if (execExt instanceof ClasspathVariableInitializer){
- return (ClasspathVariableInitializer)execExt;
+ ClasspathVariableInitializer initializer = (ClasspathVariableInitializer)execExt;
+ String deprecatedAttribute = configElement.getAttribute("deprecated"); //$NON-NLS-1$
+ if (deprecatedAttribute != null) {
+ JavaModelManager.getJavaModelManager().deprecatedVariables.put(variable, deprecatedAttribute);
+ }
+ String readOnlyAttribute = configElement.getAttribute("readOnly"); //$NON-NLS-1$
+ if (JavaModelManager.TRUE.equals(readOnlyAttribute)) {
+ JavaModelManager.getJavaModelManager().readOnlyVariables.add(variable);
+ }
+ return initializer;
}
}
} catch(CoreException e){
// executable extension could not be created: ignore this initializer
if (JavaModelManager.CP_RESOLVE_VERBOSE) {
- Util.verbose(
- "CPContainer INIT - failed to instanciate initializer\n" + //$NON-NLS-1$
- " variable: " + variable + '\n' + //$NON-NLS-1$
- " class: " + configElements[j].getAttribute("class"), //$NON-NLS-1$ //$NON-NLS-2$
- System.err);
+ verbose_failed_to_instanciate_variable_initializer(variable, configElement);
e.printStackTrace();
- }
+ }
}
}
- }
+ }
}
return null;
- }
-
+ }
+
+ private static void verbose_failed_to_instanciate_variable_initializer(String variable, IConfigurationElement configElement) {
+ Util.verbose(
+ "CPContainer INIT - failed to instanciate initializer\n" + //$NON-NLS-1$
+ " variable: " + variable + '\n' + //$NON-NLS-1$
+ " class: " + configElement.getAttribute("class"), //$NON-NLS-1$ //$NON-NLS-2$
+ System.err);
+ }
+
+ private static void verbose_found_variable_initializer(String variable, IConfigurationElement configElement) {
+ Util.verbose(
+ "CPVariable INIT - found initializer\n" + //$NON-NLS-1$
+ " variable: " + variable + '\n' + //$NON-NLS-1$
+ " class: " + configElement.getAttribute("class")); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
/**
* Returns the names of all known classpath variables.
* <p>
- * Classpath variable values are persisted locally to the workspace, and
+ * Classpath variable values are persisted locally to the workspace, and
* are preserved from session to session.
* <p>
*
@@ -1545,21 +1843,21 @@
* These options allow to configure the behaviour of the underlying components.
* The client may safely use the result as a template that they can modify and
* then pass to <code>setOptions</code>.
- *
- * Helper constants have been defined on JavaCore for each of the option ID and
+ *
+ * Helper constants have been defined on JavaCore for each of the option ID and
* their possible constant values.
- *
+ *
* Note: more options might be added in further releases.
* <pre>
* RECOGNIZED OPTIONS:
- *
+ *
* COMPILER / Setting Compliance Level
* Select the compliance level for the compiler. In "1.3" mode, source and target settings
* should not go beyond "1.3" level.
* - option id: "org.eclipse.jdt.core.compiler.compliance"
- * - possible values: { "1.3", "1.4", "1.5" }
+ * - possible values: { "1.3", "1.4", "1.5", "1.6", "1.7" }
* - default: "1.4"
- *
+ *
* COMPILER / Setting Source Compatibility Mode
* Specify whether which source level compatibility is used. From 1.4 on, 'assert' is a keyword
* reserved for assertion support. Also note, than when toggling to 1.4 mode, the target VM
@@ -1567,58 +1865,63 @@
* Source level 1.5 is necessary to enable generics, autoboxing, covariance, annotations, enumerations
* enhanced for loop, static imports and varargs. Once toggled, the target VM level should be set to "1.5"
* and the compliance mode should be "1.5".
+ * Source level 1.6 is necessary to enable the computation of stack map tables. Once toggled, the target
+ * VM level should be set to "1.6" and the compliance mode should be "1.6".
+ * Once the source level 1.7 is toggled, the target VM level should be set to "1.7" and the compliance mode
+ * should be "1.7".
* - option id: "org.eclipse.jdt.core.compiler.source"
- * - possible values: { "1.3", "1.4", "1.5" }
+ * - possible values: { "1.3", "1.4", "1.5", "1.6", "1.7" }
* - default: "1.3"
- *
+ *
* COMPILER / Defining Target Java Platform
* For binary compatibility reason, .class files can be tagged to with certain VM versions and later.
- * Note that "1.4" target require to toggle compliance mode to "1.4" too. Similarily, "1.5" target require
- * to toggle compliance mode to "1.5".
+ * Note that "1.4" target requires to toggle compliance mode to "1.4", "1.5" target requires
+ * to toggle compliance mode to "1.5", "1.6" target requires to toggle compliance mode to "1.6" and
+ * "1.7" target requires to toggle compliance mode to "1.7".
* - option id: "org.eclipse.jdt.core.compiler.codegen.targetPlatform"
- * - possible values: { "1.1", "1.2", "1.3", "1.4", "1.5" }
+ * - possible values: { "1.1", "1.2", "1.3", "1.4", "1.5", "1.6", "1.7" }
* - default: "1.2"
*
* COMPILER / Generating Local Variable Debug Attribute
- * When generated, this attribute will enable local variable names
- * to be displayed in debugger, only in place where variables are
+ * When generated, this attribute will enable local variable names
+ * to be displayed in debugger, only in place where variables are
* definitely assigned (.class file is then bigger)
* - option id: "org.eclipse.jdt.core.compiler.debug.localVariable"
* - possible values: { "generate", "do not generate" }
* - default: "generate"
*
- * COMPILER / Generating Line Number Debug Attribute
- * When generated, this attribute will enable source code highlighting in debugger
+ * COMPILER / Generating Line Number Debug Attribute
+ * When generated, this attribute will enable source code highlighting in debugger
* (.class file is then bigger).
* - option id: "org.eclipse.jdt.core.compiler.debug.lineNumber"
* - possible values: { "generate", "do not generate" }
* - default: "generate"
- *
- * COMPILER / Generating Source Debug Attribute
- * When generated, this attribute will enable the debugger to present the
+ *
+ * COMPILER / Generating Source Debug Attribute
+ * When generated, this attribute will enable the debugger to present the
* corresponding source code.
* - option id: "org.eclipse.jdt.core.compiler.debug.sourceFile"
* - possible values: { "generate", "do not generate" }
* - default: "generate"
- *
+ *
* COMPILER / Preserving Unused Local Variables
- * Unless requested to preserve unused local variables (that is, never read), the
+ * Unless requested to preserve unused local variables (that is, never read), the
* compiler will optimize them out, potentially altering debugging
* - option id: "org.eclipse.jdt.core.compiler.codegen.unusedLocal"
* - possible values: { "preserve", "optimize out" }
* - default: "preserve"
- *
+ *
* COMPILER / Inline JSR Bytecode Instruction
* When enabled, the compiler will no longer generate JSR instructions, but rather inline corresponding
* subroutine code sequences (mostly corresponding to try finally blocks). The generated code will thus
- * get bigger, but will load faster on virtual machines since the verification process is then much simpler.
+ * get bigger, but will load faster on virtual machines since the verification process is then much simpler.
* This mode is anticipating support for the Java Specification Request 202.
* Note that JSR inlining is optional only for target platform lesser than 1.5. From 1.5 on, the JSR
* inlining is mandatory (also see related setting "org.eclipse.jdt.core.compiler.codegen.targetPlatform").
* - option id: "org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode"
* - possible values: { "enabled", "disabled" }
* - default: "disabled"
- *
+ *
* COMPILER / Javadoc Comment Support
* When this support is disabled, the compiler will ignore all javadoc problems options settings
* and will not report any javadoc problem. It will also not find any reference in javadoc comment and
@@ -1628,23 +1931,23 @@
* - default: "enabled"
*
* COMPILER / Reporting Attempt to Override Package-Default Method
- * A package default method is not visible in a different package, and thus
- * cannot be overridden. When enabling this option, the compiler will signal
+ * A package default method is not visible in a different package, and thus
+ * cannot be overridden. When enabling this option, the compiler will signal
* such scenarii either as an error or a warning.
* - option id: "org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod"
* - possible values: { "error", "warning", "ignore" }
* - default: "warning"
*
* COMPILER / Reporting Method With Constructor Name
- * Naming a method with a constructor name is generally considered poor
- * style programming. When enabling this option, the compiler will signal such
+ * Naming a method with a constructor name is generally considered poor
+ * style programming. When enabling this option, the compiler will signal such
* scenarii either as an error or a warning.
* - option id: "org.eclipse.jdt.core.compiler.problem.methodWithConstructorName"
* - possible values: { "error", "warning", "ignore" }
* - default: "warning"
*
* COMPILER / Reporting Deprecation
- * When enabled, the compiler will signal use of deprecated API either as an
+ * When enabled, the compiler will signal use of deprecated API either as an
* error or a warning.
* - option id: "org.eclipse.jdt.core.compiler.problem.deprecation"
* - possible values: { "error", "warning", "ignore" }
@@ -1668,22 +1971,22 @@
* Locally to a try statement, some catch blocks may hide others . For example,
* try { throw new java.io.CharConversionException();
* } catch (java.io.CharConversionException e) {
- * } catch (java.io.IOException e) {}.
- * When enabling this option, the compiler will issue an error or a warning for hidden
+ * } catch (java.io.IOException e) {}.
+ * When enabling this option, the compiler will issue an error or a warning for hidden
* catch blocks corresponding to checked exceptions
* - option id: "org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock"
* - possible values: { "error", "warning", "ignore" }
* - default: "warning"
*
* COMPILER / Reporting Unused Local
- * When enabled, the compiler will issue an error or a warning for unused local
+ * When enabled, the compiler will issue an error or a warning for unused local
* variables (that is, variables never read from)
* - option id: "org.eclipse.jdt.core.compiler.problem.unusedLocal"
* - possible values: { "error", "warning", "ignore" }
* - default: "ignore"
*
* COMPILER / Reporting Unused Parameter
- * When enabled, the compiler will issue an error or a warning for unused method
+ * When enabled, the compiler will issue an error or a warning for unused method
* parameters (that is, parameters never read from)
* - option id: "org.eclipse.jdt.core.compiler.problem.unusedParameter"
* - possible values: { "error", "warning", "ignore" }
@@ -1703,15 +2006,25 @@
* - possible values: { "enabled", "disabled" }
* - default: "disabled"
*
+ * COMPILER / Consider Reference in Doc Comment for Unused Parameter Check
+ * When enabled, the compiler will consider doc comment references to parameters (i.e. @param clauses) for the unused
+ * parameter check. Thus, documented parameters will be considered as mandated as per doc contract.
+ * The severity of the unused parameter problem is controlled with option "org.eclipse.jdt.core.compiler.problem.unusedParameter".
+ * Note: this option has no effect until the doc comment support is enabled according to the
+ * option "org.eclipse.jdt.core.compiler.doc.comment.support".
+ * - option id: "org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocReference"
+ * - possible values: { "enabled", "disabled" }
+ * - default: "enabled"
+ *
* COMPILER / Reporting Unused Import
- * When enabled, the compiler will issue an error or a warning for unused import
- * reference
+ * When enabled, the compiler will issue an error or a warning for unused import
+ * reference
* - option id: "org.eclipse.jdt.core.compiler.problem.unusedImport"
* - possible values: { "error", "warning", "ignore" }
* - default: "warning"
*
* COMPILER / Reporting Unused Private Members
- * When enabled, the compiler will issue an error or a warning whenever a private
+ * When enabled, the compiler will issue an error or a warning whenever a private
* method or field is declared but never used within the same unit.
* - option id: "org.eclipse.jdt.core.compiler.problem.unusedPrivateMember"
* - possible values: { "error", "warning", "ignore" }
@@ -1723,30 +2036,30 @@
* - option id: "org.eclipse.jdt.core.compiler.problem.noEffectAssignment"
* - possible values: { "error", "warning", "ignore" }
* - default: "warning"
- *
+ *
* COMPILER / Reporting Empty Statements and Unnecessary Semicolons
* When enabled, the compiler will issue an error or a warning if an empty statement or a
* unnecessary semicolon is encountered.
* - option id: "org.eclipse.jdt.core.compiler.problem.emptyStatement"
* - possible values: { "error", "warning", "ignore" }
* - default: "ignore"
- *
+ *
* COMPILER / Reporting Unnecessary Type Check
- * When enabled, the compiler will issue an error or a warning when a cast or an instanceof operation
+ * When enabled, the compiler will issue an error or a warning when a cast or an instanceof operation
* is unnecessary.
* - option id: "org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck"
* - possible values: { "error", "warning", "ignore" }
* - default: "ignore"
- *
+ *
* COMPILER / Reporting Unnecessary Else
* When enabled, the compiler will issue an error or a warning when a statement is unnecessarily
* nested within an else clause (in situation where then clause is not completing normally).
* - option id: "org.eclipse.jdt.core.compiler.problem.unnecessaryElse"
* - possible values: { "error", "warning", "ignore" }
* - default: "ignore"
- *
+ *
* COMPILER / Reporting Synthetic Access Emulation
- * When enabled, the compiler will issue an error or a warning whenever it emulates
+ * When enabled, the compiler will issue an error or a warning whenever it emulates
* access to a non-accessible member of an enclosing type. Such access can have
* performance implications.
* - option id: "org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation"
@@ -1754,26 +2067,26 @@
* - default: "ignore"
*
* COMPILER / Reporting Non-Externalized String Literal
- * When enabled, the compiler will issue an error or a warning for non externalized
- * String literal (that is, not tagged with //$NON-NLS-<n>$).
+ * When enabled, the compiler will issue an error or a warning for non externalized
+ * String literal (that is, not tagged with //$NON-NLS-<n>$).
* - option id: "org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral"
* - possible values: { "error", "warning", "ignore" }
* - default: "ignore"
- *
+ *
* COMPILER / Reporting Usage of 'assert' Identifier
- * When enabled, the compiler will issue an error or a warning whenever 'assert' is
+ * When enabled, the compiler will issue an error or a warning whenever 'assert' is
* used as an identifier (reserved keyword in 1.4)
* - option id: "org.eclipse.jdt.core.compiler.problem.assertIdentifier"
* - possible values: { "error", "warning", "ignore" }
* - default: "warning"
- *
+ *
* COMPILER / Reporting Usage of 'enum' Identifier
- * When enabled, the compiler will issue an error or a warning whenever 'enum' is
+ * When enabled, the compiler will issue an error or a warning whenever 'enum' is
* used as an identifier (reserved keyword in 1.5)
* - option id: "org.eclipse.jdt.core.compiler.problem.enumIdentifier"
* - possible values: { "error", "warning", "ignore" }
* - default: "warning"
- *
+ *
* COMPILER / Reporting Non-Static Reference to a Static Member
* When enabled, the compiler will issue an error or a warning whenever a static field
* or method is accessed with an expression receiver. A reference to a static member should
@@ -1781,7 +2094,7 @@
* - option id: "org.eclipse.jdt.core.compiler.problem.staticAccessReceiver"
* - possible values: { "error", "warning", "ignore" }
* - default: "warning"
- *
+ *
* COMPILER / Reporting Indirect Reference to a Static Member
* When enabled, the compiler will issue an error or a warning whenever a static field
* or method is accessed in an indirect way. A reference to a static member should
@@ -1789,18 +2102,18 @@
* - option id: "org.eclipse.jdt.core.compiler.problem.indirectStaticAccess"
* - possible values: { "error", "warning", "ignore" }
* - default: "ignore"
- *
+ *
* COMPILER / Reporting Interface Method not Compatible with non-Inherited Methods
* When enabled, the compiler will issue an error or a warning whenever an interface
* defines a method incompatible with a non-inherited Object method. Until this conflict
- * is resolved, such an interface cannot be implemented, For example,
- * interface I {
+ * is resolved, such an interface cannot be implemented, For example,
+ * interface I {
* int clone();
- * }
+ * }
* - option id: "org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod"
* - possible values: { "error", "warning", "ignore" }
* - default: "warning"
- *
+ *
* COMPILER / Reporting Usage of char[] Expressions in String Concatenations
* When enabled, the compiler will issue an error or a warning whenever a char[] expression
* is used in String concatenations (for example, "hello" + new char[]{'w','o','r','l','d'}).
@@ -1823,16 +2136,17 @@
* - default: "ignore"
*
* COMPILER / Reporting Special Parameter Hiding another Field
- * When enabled, the compiler will signal cases where a constructor or setter method parameter declaration
+ * When enabled, the compiler will signal cases where a constructor or setter method parameter declaration
* is hiding some field (either locally, inherited or defined in enclosing type).
* The severity of the problem is controlled with option "org.eclipse.jdt.core.compiler.problem.localVariableHiding".
* - option id: "org.eclipse.jdt.core.compiler.problem.specialParameterHidingField"
* - possible values: { "enabled", "disabled" }
* - default: "disabled"
- *
- * COMPILER / Reporting Type Parameter Declaration Hiding another Type
- * When enabled, the compiler will issue an error or a warning whenever a type parameter
- * declaration is hiding some type.
+ *
+ * COMPILER / Reporting Type Declaration Hiding another Type
+ * When enabled, the compiler will issue an error or a warning in situations where a type parameter
+ * declaration is hiding some type, when a nested type is hiding some type parameter, or when
+ * a nested type is hiding another nested type defined in same unit.
* - option id: "org.eclipse.jdt.core.compiler.problem.typeParameterHiding"
* - possible values: { "error", "warning", "ignore" }
* - default: "warning"
@@ -1843,7 +2157,7 @@
* - option id: "org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment"
* - possible values: { "error", "warning", "ignore" }
* - default: "ignore"
- *
+ *
* COMPILER / Reporting Undocumented Empty Block
* When enabled, the compiler will issue an error or a warning when an empty block is detected and it is not
* documented with any comment.
@@ -1872,7 +2186,7 @@
* - option id: "org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding"
* - possible values: { "enabled", "disabled" }
* - default: "disabled"
- *
+ *
* COMPILER / Reporting Unqualified Access to Field
* When enabled, the compiler will issue an error or a warning when a field is access without any qualification.
* In order to improve code readability, it should be qualified, e.g. 'x' should rather be written 'this.x'.
@@ -1886,76 +2200,101 @@
* - option id: "org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation"
* - possible values: { "error", "warning", "ignore" }
* - default: "warning"
- *
+ *
+ * COMPILER / Reporting Raw Type Reference
+ * When enabled, the compiler will issue an error or a warning when detecting references to raw types. Raw types are
+ * discouraged, and are intended to help interfacing with legacy code. In the future, the language specification may
+ * reject raw references to generic types.
+ * - option id: "org.eclipse.jdt.core.compiler.problem.rawTypeReference"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "warning"
+ *
* COMPILER / Reporting final Bound for Type Parameter
- * When enabled, the compiler will issue an error or a warning whenever a generic type parameter is associated with a
+ * When enabled, the compiler will issue an error or a warning whenever a generic type parameter is associated with a
* bound corresponding to a final type; since final types cannot be further extended, the parameter is pretty useless.
* - option id: "org.eclipse.jdt.core.compiler.problem.finalParameterBound"
* - possible values: { "error", "warning", "ignore" }
* - default: "warning"
- *
+ *
* COMPILER / Reporting Missing Declaration of serialVersionUID Field on Serializable Class
- * When enabled, the compiler will issue an error or a warning whenever a serializable class is missing a local declaration
+ * When enabled, the compiler will issue an error or a warning whenever a serializable class is missing a local declaration
* of a serialVersionUID field. This field must be declared as static final and be of type long.
* - option id: "org.eclipse.jdt.core.compiler.problem.missingSerialVersion"
* - possible values: { "error", "warning", "ignore" }
* - default: "warning"
- *
+ *
* COMPILER / Reporting Varargs Argument Needing a Cast in Method/Constructor Invocation
* When enabled, the compiler will issue an error or a warning whenever a varargs arguments should be cast
- * when passed to a method/constructor invocation. (e.g. Class.getMethod(String name, Class ... args )
+ * when passed to a method/constructor invocation. (e.g. Class.getMethod(String name, Class ... args )
* invoked with arguments ("foo", null)).
* - option id: "org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast"
* - possible values: { "error", "warning", "ignore" }
* - default: "warning"
- *
- * COMPILER / Reporting Null Reference or Dereference
- * When enabled, the compiler will issue an error or a warning whenever assumption were made on a variable
- * with respect to holding null/non-null values, but the assumption is not followed in a consistent manner.
- * Situations include:
- * - if variable was assumed to be null and further used to access field or methods
- * - if variable was assumed to be null or non-null and further tested for null cases.
- *
+ *
+ * COMPILER / Reporting Null Dereference
+ * When enabled, the compiler will issue an error or a warning whenever a
+ * variable that is statically known to hold a null value is used to
+ * access a field or method.
+ *
* - option id: "org.eclipse.jdt.core.compiler.problem.nullReference"
* - possible values: { "error", "warning", "ignore" }
- * - default: "warning"
- *
+ * - default: "ignore"
+ *
+ * COMPILER / Reporting Potential Null Dereference
+ * When enabled, the compiler will issue an error or a warning whenever a
+ * variable that has formerly been tested against null but is not (no more)
+ * statically known to hold a non-null value is used to access a field or
+ * method.
+ *
+ * - option id: "org.eclipse.jdt.core.compiler.problem.potentialNullReference"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "ignore"
+ *
+ * COMPILER / Reporting Redundant Null Check
+ * When enabled, the compiler will issue an error or a warning whenever a
+ * variable that is statically known to hold a null or a non-null value
+ * is tested against null.
+ *
+ * - option id: "org.eclipse.jdt.core.compiler.problem.redundantNullCheck"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "ignore"
+ *
* COMPILER / Reporting Use of Annotation Type as Super Interface
* When enabled, the compiler will issue an error or a warning whenever an annotation type is used
* as a super-interface. Though legal, this is discouraged.
* - option id: "org.eclipse.jdt.core.compiler.problem.annotationSuperInterface"
* - possible values: { "error", "warning", "ignore" }
* - default: "warning"
- *
+ *
* COMPILER / Reporting Missing @Override Annotation
* When enabled, the compiler will issue an error or a warning whenever encountering a method
* declaration which overrides a superclass method but has no @Override annotation.
* - option id: "org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation"
* - possible values: { "error", "warning", "ignore" }
- * - default: "ignore"
- *
+ * - default: "ignore"
+ *
* COMPILER / Reporting Missing @Deprecated Annotation
* When enabled, the compiler will issue an error or a warning whenever encountering a declaration
- * carrying a @deprecated doc tag but has no corresponding @Deprecated annotation.
+ * carrying a @deprecated doc tag but having no corresponding @Deprecated annotation.
* - option id: "org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation"
* - possible values: { "error", "warning", "ignore" }
- * - default: "ignore"
- *
+ * - default: "ignore"
+ *
* COMPILER / Reporting Incomplete Enum Switch
- * When enabled, the compiler will issue an error or a warning whenever an enum constant has
- * no corresponding case label in an enum switch statement
- * type has no case label matching an enum constant.
+ * When enabled, the compiler will issue an error or a warning whenever
+ * an enum constant has no corresponding case label in an enum switch
+ * statement.
* - option id: "org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch"
* - possible values: { "error", "warning", "ignore" }
- * - default: "ignore"
- *
+ * - default: "ignore"
+ *
* COMPILER / Reporting Boxing/Unboxing Conversion
* When enabled, the compiler will issue an error or a warning whenever a boxing or an unboxing
* conversion is performed.
* - option id: "org.eclipse.jdt.core.compiler.problem.autoboxing"
* - possible values: { "error", "warning", "ignore" }
* - default: "ignore"
- *
+ *
* COMPILER / Reporting Invalid Javadoc Comment
* This is the generic control for the severity of Javadoc problems.
* When enabled, the compiler will issue an error or a warning for a problem in Javadoc.
@@ -1967,8 +2306,8 @@
* Set the minimum visibility level for Javadoc tag problems. Below this level problems will be ignored.
* - option id: "org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility"
* - possible values: { "public", "protected", "default", "private" }
- * - default: "private"
- *
+ * - default: "public"
+ *
* COMPILER / Reporting Invalid Javadoc Tags
* When enabled, the compiler will signal unbound or unexpected reference tags in Javadoc.
* A 'throws' tag referencing an undeclared exception would be considered as unexpected.
@@ -1978,24 +2317,24 @@
* The severity of the problem is controlled with option "org.eclipse.jdt.core.compiler.problem.invalidJavadoc".
* - option id: "org.eclipse.jdt.core.compiler.problem.invalidJavadocTags"
* - possible values: { "disabled", "enabled" }
- * - default: "enabled"
- *
+ * - default: "disabled"
+ *
* COMPILER / Reporting Invalid Javadoc Tags with Deprecated References
* Specify whether the compiler will report deprecated references used in Javadoc tags.
* <br>Note that this diagnosis can be enabled based on the visibility of the construct associated with the Javadoc;
* also see the setting "org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility".
* - option id: "org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef"
* - possible values: { "enabled", "disabled" }
- * - default: "enabled"
- *
+ * - default: "disabled"
+ *
* COMPILER / Reporting Invalid Javadoc Tags with Not Visible References
* Specify whether the compiler will report non-visible references used in Javadoc tags.
* <br>Note that this diagnosis can be enabled based on the visibility of the construct associated with the Javadoc;
* also see the setting "org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility".
* - option id: "org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef"
* - possible values: { "enabled", "disabled" }
- * - default: "enabled"
- *
+ * - default: "disabled"
+ *
* COMPILER / Reporting Missing Javadoc Tags
* This is the generic control for the severity of Javadoc missing tag problems.
* When enabled, the compiler will issue an error or a warning when tags are missing in Javadoc comments.
@@ -2005,19 +2344,19 @@
* - option id: "org.eclipse.jdt.core.compiler.problem.missingJavadocTags"
* - possible values: { "error", "warning", "ignore" }
* - default: "ignore"
- *
+ *
* COMPILER / Visibility Level For Missing Javadoc Tags
* Set the minimum visibility level for Javadoc missing tag problems. Below this level problems will be ignored.
* - option id: "org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility"
* - possible values: { "public", "protected", "default", "private" }
- * - default: "private"
- *
+ * - default: "public"
+ *
* COMPILER / Reporting Missing Javadoc Tags on Overriding Methods
* Specify whether the compiler will verify overriding methods in order to report Javadoc missing tag problems.
* - option id: "org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding"
* - possible values: { "enabled", "disabled" }
* - default: "disabled"
- *
+ *
* COMPILER / Reporting Missing Javadoc Comments
* This is the generic control for the severity of missing Javadoc comment problems.
* When enabled, the compiler will issue an error or a warning when Javadoc comments are missing.
@@ -2027,39 +2366,51 @@
* - option id: "org.eclipse.jdt.core.compiler.problem.missingJavadocComments"
* - possible values: { "error", "warning", "ignore" }
* - default: "ignore"
- *
+ *
* COMPILER / Visibility Level For Missing Javadoc Comments
* Set the minimum visibility level for missing Javadoc problems. Below this level problems will be ignored.
* - option id: "org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility"
* - possible values: { "public", "protected", "default", "private" }
* - default: "public"
- *
+ *
* COMPILER / Reporting Missing Javadoc Comments on Overriding Methods
* Specify whether the compiler will verify overriding methods in order to report missing Javadoc comment problems.
* - option id: "org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding"
* - possible values: { "enabled", "disabled" }
* - default: "disabled"
- *
- * COMPILER / Maximum number of problems reported per compilation unit
+ *
+ * COMPILER / Maximum Number of Problems Reported per Compilation Unit
* Specify the maximum number of problems reported on each compilation unit.
* - option id: "org.eclipse.jdt.core.compiler.maxProblemPerUnit"
* - possible values: "<n>" where <n> is zero or a positive integer (if zero then all problems are reported).
* - default: "100"
- *
+ *
+ * COMPILER / Treating Optional Error as Fatal
+ * When enabled, optional errors (i.e. optional problems which severity is set to "error") will be treated as standard
+ * compiler errors, yielding problem methods/types preventing from running offending code until the issue got resolved.
+ * When disabled, optional errors are only considered as warnings, still carrying an error indication to make them more
+ * severe. Note that by default, errors are fatal, whether they are optional or not.
+ * - option id: "org.eclipse.jdt.core.compiler.problem.fatalOptionalError"
+ * - possible values: { "enabled", "disabled" }
+ * - default: "enabled"
+ *
* COMPILER / Defining the Automatic Task Tags
* When the tag list is not empty, the compiler will issue a task marker whenever it encounters
- * one of the corresponding tag inside any comment in Java source code.
- * Generated task messages will include the tag, and range until the next line separator or comment ending.
+ * one of the corresponding tags inside any comment in Java source code.
+ * Generated task messages will start with the tag, and range until the next line separator,
+ * comment ending, or tag.
+ * When a given line of code bears multiple tags, each tag will be reported separately.
+ * Moreover, a tag immediately followed by another tag will be reported using the contents of the
+ * next non-empty tag of the line, if any.
* Note that tasks messages are trimmed. If a tag is starting with a letter or digit, then it cannot be leaded by
* another letter or digit to be recognized ("fooToDo" will not be recognized as a task for tag "ToDo", but "foo#ToDo"
* will be detected for either tag "ToDo" or "#ToDo"). Respectively, a tag ending with a letter or digit cannot be followed
* by a letter or digit to be recognized ("ToDofoo" will not be recognized as a task for tag "ToDo", but "ToDo:foo" will
* be detected either for tag "ToDo" or "ToDo:").
- * Note: the tasks are ordered, and the first matching tag will be selected; e.g. "TODO,TODO!" will match "TODO!" against "TODO" first.
* - option id: "org.eclipse.jdt.core.compiler.taskTags"
- * - possible values: { "<tag>[,<tag>]*" } where <tag> is a String without any wild-card or leading/trailing spaces
+ * - possible values: { "<tag>[,<tag>]*" } where <tag> is a String without any wild-card or leading/trailing spaces
* - default: "TODO,FIXME,XXX"
- *
+ *
* COMPILER / Defining the Automatic Task Priorities
* In parallel with the Automatic Task Tags, this list defines the priorities (high, normal or low)
* of the task markers issued by the compiler.
@@ -2067,7 +2418,7 @@
* - option id: "org.eclipse.jdt.core.compiler.taskPriorities"
* - possible values: { "<priority>[,<priority>]*" } where <priority> is one of "HIGH", "NORMAL" or "LOW"
* - default: "NORMAL,HIGH,NORMAL"
- *
+ *
* COMPILER / Determining whether task tags are case-sensitive
* When enabled, task tags are considered in a case-sensitive way.
* - option id: "org.eclipse.jdt.core.compiler.taskCaseSensitive"
@@ -2089,7 +2440,7 @@
* - default: "warning"
*
* COMPILER / Determining Effect of @SuppressWarnings
- * When enabled, the @SuppressWarnings annotation can be used to suppress some compiler warnings.
+ * When enabled, the @SuppressWarnings annotation can be used to suppress some compiler warnings.
* When disabled, all @SupressWarnings annotations are ignored; i.e., warnings are reported.
* - option id: "org.eclipse.jdt.core.compiler.problem.suppressWarnings"
* - possible values: { "enabled", "disabled" }
@@ -2102,236 +2453,300 @@
* - possible values: { "error", "warning", "ignore" }
* - default: "warning"
*
+ * COMPILER / Reporting Unreferenced Label
+ * When enabled, the compiler will issue an error or a warning when encountering a labeled statement which label
+ * is never explicitly referenced. A label is considered to be referenced if its name explicitly appears behind a break
+ * or continue statement; for instance the following label would be considered unreferenced; LABEL: { break; }
+ * - option id: "org.eclipse.jdt.core.compiler.problem.unusedLabel"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "warning"
+ *
+ * COMPILER / Reporting Parameter Assignment
+ * When enabled, the compiler will issue an error or a warning if a parameter is
+ * assigned to.
+ * - option id: "org.eclipse.jdt.core.compiler.problem.parameterAssignment"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "ignore"
+ *
+ * COMPILER / Reporting Switch Fall-Through Case
+ * When enabled, the compiler will issue an error or a warning if a case may be
+ * entered by falling through previous case. Empty cases are allowed.
+ * - option id: "org.eclipse.jdt.core.compiler.problem.fallthroughCase"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "ignore"
+ *
+ * COMPILER / Reporting Overriding method that doesn't call the super method invocation
+ * When enabled, the compiler will issue an error or a warning if a method is overriding a method without calling
+ * the super invocation.
+ * - option id: "org.eclipse.jdt.core.compiler.problem.overridingMethodWithoutSuperInvocation"
+ * - possible values: { "error", "warning", "ignore" }
+ * - default: "ignore"
+ *
* BUILDER / Specifying Filters for Resource Copying Control
* Allow to specify some filters to control the resource copy process.
* - option id: "org.eclipse.jdt.core.builder.resourceCopyExclusionFilter"
* - possible values: { "<name>[,<name>]* } where <name> is a file name pattern (* and ? wild-cards allowed)
* or the name of a folder which ends with '/'
* - default: ""
- *
+ *
* BUILDER / Abort if Invalid Classpath
* Allow to toggle the builder to abort if the classpath is invalid
* - option id: "org.eclipse.jdt.core.builder.invalidClasspath"
* - possible values: { "abort", "ignore" }
* - default: "abort"
- *
+ *
* BUILDER / Cleaning Output Folder(s)
* Indicate whether the JavaBuilder is allowed to clean the output folders
* when performing full build operations.
* - option id: "org.eclipse.jdt.core.builder.cleanOutputFolder"
* - possible values: { "clean", "ignore" }
* - default: "clean"
- *
+ *
+ * BUILDER / Recreate Modified class files in Output Folder
+ * Indicate whether the JavaBuilder should check for any changes to .class files
+ * in the output folders while performing incremental build operations. If changes
+ * are detected to managed .class files, then a full build is performed, otherwise
+ * the changes are left as is. Tools further altering generated .class files, like optimizers,
+ * should ensure this option remains set in its default state of ignore.
+ * - option id: "org.eclipse.jdt.core.builder.recreateModifiedClassFileInOutputFolder"
+ * - possible values: { "enabled", "ignore" }
+ * - default: "ignore"
+ *
* BUILDER / Reporting Duplicate Resources
* Indicate the severity of the problem reported when more than one occurrence
* of a resource is to be copied into the output location.
* - option id: "org.eclipse.jdt.core.builder.duplicateResourceTask"
* - possible values: { "error", "warning" }
* - default: "warning"
- *
+ *
* JAVACORE / Computing Project Build Order
* Indicate whether JavaCore should enforce the project build order to be based on
* the classpath prerequisite chain. When requesting to compute, this takes over
* the platform default order (based on project references).
* - option id: "org.eclipse.jdt.core.computeJavaBuildOrder"
* - possible values: { "compute", "ignore" }
- * - default: "ignore"
- *
- * JAVACORE / Specify Default Source Encoding Format
- * Get the encoding format for compiled sources. This setting is read-only, it is equivalent
- * to 'ResourcesPlugin.getEncoding()'.
+ * - default: "ignore"
+ *
+ * JAVACORE / Default Source Encoding Format
+ * Get the default encoding format of source files. This value is
+ * immutable and preset to the result of ResourcesPlugin.getEncoding().
+ * It is offered as a convenience shortcut only.
* - option id: "org.eclipse.jdt.core.encoding"
- * - possible values: { any of the supported encoding name}.
- * - default: <platform default>
- *
+ * - value: <immutable, platform default value>
+ *
* JAVACORE / Reporting Incomplete Classpath
- * Indicate the severity of the problem reported when an entry on the classpath does not exist,
+ * Indicate the severity of the problem reported when an entry on the classpath does not exist,
* is not legite or is not visible (for example, a referenced project is closed).
* - option id: "org.eclipse.jdt.core.incompleteClasspath"
* - possible values: { "error", "warning"}
* - default: "error"
- *
+ *
* JAVACORE / Reporting Classpath Cycle
* Indicate the severity of the problem reported when a project is involved in a cycle.
* - option id: "org.eclipse.jdt.core.circularClasspath"
* - possible values: { "error", "warning" }
* - default: "error"
- *
+ *
* JAVACORE / Reporting Incompatible JDK Level for Required Binaries
- * Indicate the severity of the problem reported when a project prerequisites another project
+ * Indicate the severity of the problem reported when a project prerequisites another project
* or library with an incompatible target JDK level (e.g. project targeting 1.1 vm, but compiled against 1.4 libraries).
* - option id: "org.eclipse.jdt.core.incompatibleJDKLevel"
* - possible values: { "error", "warning", "ignore" }
* - default: "ignore"
- *
+ *
* JAVACORE / Enabling Usage of Classpath Exclusion Patterns
* When disabled, no entry on a project classpath can be associated with
* an exclusion pattern.
* - option id: "org.eclipse.jdt.core.classpath.exclusionPatterns"
* - possible values: { "enabled", "disabled" }
* - default: "enabled"
- *
+ *
* JAVACORE / Enabling Usage of Classpath Multiple Output Locations
* When disabled, no entry on a project classpath can be associated with
* a specific output location, preventing thus usage of multiple output locations.
* - option id: "org.eclipse.jdt.core.classpath.multipleOutputLocations"
* - possible values: { "enabled", "disabled" }
* - default: "enabled"
- *
- * FORMATTER / Inserting New Line Before Opening Brace
+ *
+ * JAVACORE / Set the timeout value for retrieving the method's parameter names from javadoc
+ * Timeout in milliseconds to retrieve the method's parameter names from javadoc.
+ * If the value is 0, the parameter names are not fetched and the raw names are returned.
+ * - option id: "org.eclipse.jdt.core.timeoutForParameterNameFromAttachedJavadoc"
+ * - possible values: "<n>", where n is an integer greater than or equal to 0
+ * - default: "50"
+ *
+ * DEPRECATED SEE DefaultCodeFormatterOptions: FORMATTER / Inserting New Line Before Opening Brace
* When Insert, a new line is inserted before an opening brace, otherwise nothing
* is inserted
* - option id: "org.eclipse.jdt.core.formatter.newline.openingBrace"
* - possible values: { "insert", "do not insert" }
* - default: "do not insert"
- *
- * FORMATTER / Inserting New Line Inside Control Statement
+ *
+ * DEPRECATED SEE DefaultCodeFormatterOptions: FORMATTER / Inserting New Line Inside Control Statement
* When Insert, a new line is inserted between } and following else, catch, finally
* - option id: "org.eclipse.jdt.core.formatter.newline.controlStatement"
* - possible values: { "insert", "do not insert" }
* - default: "do not insert"
- *
- * FORMATTER / Clearing Blank Lines
+ *
+ * DEPRECATED SEE DefaultCodeFormatterOptions: Clearing Blank Lines
* When Clear all, all blank lines are removed. When Preserve one, only one is kept
* and all others removed.
* - option id: "org.eclipse.jdt.core.formatter.newline.clearAll"
* - possible values: { "clear all", "preserve one" }
* - default: "preserve one"
- *
- * FORMATTER / Inserting New Line Between Else/If
- * When Insert, a blank line is inserted between an else and an if when they are
+ *
+ * DEPRECATED SEE DefaultCodeFormatterOptions: Inserting New Line Between Else/If
+ * When Insert, a blank line is inserted between an else and an if when they are
* contiguous. When choosing to not insert, else-if will be kept on the same
* line when possible.
* - option id: "org.eclipse.jdt.core.formatter.newline.elseIf"
* - possible values: { "insert", "do not insert" }
* - default: "do not insert"
- *
- * FORMATTER / Inserting New Line In Empty Block
+ *
+ * DEPRECATED SEE DefaultCodeFormatterOptions: Inserting New Line In Empty Block
* When insert, a line break is inserted between contiguous { and }, if } is not followed
* by a keyword.
* - option id: "org.eclipse.jdt.core.formatter.newline.emptyBlock"
* - possible values: { "insert", "do not insert" }
* - default: "insert"
- *
- * FORMATTER / Splitting Lines Exceeding Length
+ *
+ * DEPRECATED SEE DefaultCodeFormatterOptions: Splitting Lines Exceeding Length
* Enable splitting of long lines (exceeding the configurable length). Length of 0 will
* disable line splitting
* - option id: "org.eclipse.jdt.core.formatter.lineSplit"
* - possible values: "<n>", where n is zero or a positive integer
* - default: "80"
- *
- * FORMATTER / Compacting Assignment
+ *
+ * DEPRECATED SEE DefaultCodeFormatterOptions: Compacting Assignment
* Assignments can be formatted asymmetrically, for example 'int x= 2;', when Normal, a space
* is inserted before the assignment operator
* - option id: "org.eclipse.jdt.core.formatter.style.assignment"
* - possible values: { "compact", "normal" }
* - default: "normal"
- *
- * FORMATTER / Defining Indentation Character
+ *
+ * DEPRECATED SEE DefaultCodeFormatterOptions: Defining Indentation Character
* Either choose to indent with tab characters or spaces
* - option id: "org.eclipse.jdt.core.formatter.tabulation.char"
* - possible values: { "tab", "space" }
* - default: "tab"
- *
- * FORMATTER / Defining Space Indentation Length
- * When using spaces, set the amount of space characters to use for each
+ *
+ * DEPRECATED SEE DefaultCodeFormatterOptions: Defining Space Indentation Length
+ * When using spaces, set the amount of space characters to use for each
* indentation mark.
* - option id: "org.eclipse.jdt.core.formatter.tabulation.size"
* - possible values: "<n>", where n is a positive integer
* - default: "4"
- *
- * FORMATTER / Inserting space in cast expression
+ *
+ * DEPRECATED SEE DefaultCodeFormatterOptions: Inserting space in cast expression
* When Insert, a space is added between the type and the expression in a cast expression.
* - option id: "org.eclipse.jdt.core.formatter.space.castexpression"
* - possible values: { "insert", "do not insert" }
* - default: "insert"
- *
- * CODEASSIST / Activate Visibility Sensitive Completion
+ *
+ * CODEASSIST / Activate Visibility Sensitive Completion
* When active, completion doesn't show that you can not see
* (for example, you can not see private methods of a super class).
* - option id: "org.eclipse.jdt.core.codeComplete.visibilityCheck"
* - possible values: { "enabled", "disabled" }
* - default: "disabled"
- *
- * CODEASSIST / Automatic Qualification of Implicit Members
+ *
+ * CODEASSIST / Activate Deprecation Sensitive Completion
+ * When enabled, completion doesn't propose deprecated members and types.
+ * - option id: "org.eclipse.jdt.core.codeComplete.deprecationCheck"
+ * - possible values: { "enabled", "disabled" }
+ * - default: "disabled"
+ *
+ * CODEASSIST / Automatic Qualification of Implicit Members
* When active, completion automatically qualifies completion on implicit
* field references and message expressions.
* - option id: "org.eclipse.jdt.core.codeComplete.forceImplicitQualification"
* - possible values: { "enabled", "disabled" }
* - default: "disabled"
- *
- * CODEASSIST / Define the Prefixes for Field Name
+ *
+ * CODEASSIST / Define the Prefixes for Field Name
* When the prefixes is non empty, completion for field name will begin with
* one of the proposed prefixes.
* - option id: "org.eclipse.jdt.core.codeComplete.fieldPrefixes"
- * - possible values: { "<prefix>[,<prefix>]*" } where <prefix> is a String without any wild-card
+ * - possible values: { "<prefix>[,<prefix>]*" } where <prefix> is a String without any wild-card
* - default: ""
- *
- * CODEASSIST / Define the Prefixes for Static Field Name
+ *
+ * CODEASSIST / Define the Prefixes for Static Field Name
* When the prefixes is non empty, completion for static field name will begin with
* one of the proposed prefixes.
* - option id: "org.eclipse.jdt.core.codeComplete.staticFieldPrefixes"
- * - possible values: { "<prefix>[,<prefix>]*" } where <prefix> is a String without any wild-card
+ * - possible values: { "<prefix>[,<prefix>]*" } where <prefix> is a String without any wild-card
* - default: ""
- *
- * CODEASSIST / Define the Prefixes for Local Variable Name
+ *
+ * CODEASSIST / Define the Prefixes for Local Variable Name
* When the prefixes is non empty, completion for local variable name will begin with
* one of the proposed prefixes.
* - option id: "org.eclipse.jdt.core.codeComplete.localPrefixes"
- * - possible values: { "<prefix>[,<prefix>]*" } where <prefix> is a String without any wild-card
+ * - possible values: { "<prefix>[,<prefix>]*" } where <prefix> is a String without any wild-card
* - default: ""
- *
- * CODEASSIST / Define the Prefixes for Argument Name
+ *
+ * CODEASSIST / Define the Prefixes for Argument Name
* When the prefixes is non empty, completion for argument name will begin with
* one of the proposed prefixes.
* - option id: "org.eclipse.jdt.core.codeComplete.argumentPrefixes"
- * - possible values: { "<prefix>[,<prefix>]*" } where <prefix> is a String without any wild-card
+ * - possible values: { "<prefix>[,<prefix>]*" } where <prefix> is a String without any wild-card
* - default: ""
- *
- * CODEASSIST / Define the Suffixes for Field Name
+ *
+ * CODEASSIST / Define the Suffixes for Field Name
* When the suffixes is non empty, completion for field name will end with
* one of the proposed suffixes.
* - option id: "org.eclipse.jdt.core.codeComplete.fieldSuffixes"
- * - possible values: { "<suffix>[,<suffix>]*" } where <suffix> is a String without any wild-card
+ * - possible values: { "<suffix>[,<suffix>]*" } where <suffix> is a String without any wild-card
* - default: ""
- *
- * CODEASSIST / Define the Suffixes for Static Field Name
+ *
+ * CODEASSIST / Define the Suffixes for Static Field Name
* When the suffixes is non empty, completion for static field name will end with
* one of the proposed suffixes.
* - option id: "org.eclipse.jdt.core.codeComplete.staticFieldSuffixes"
- * - possible values: { "<suffix>[,<suffix>]*" } where <suffix> is a String without any wild-card
+ * - possible values: { "<suffix>[,<suffix>]*" } where <suffix> is a String without any wild-card
* - default: ""
- *
- * CODEASSIST / Define the Suffixes for Local Variable Name
+ *
+ * CODEASSIST / Define the Suffixes for Local Variable Name
* When the suffixes is non empty, completion for local variable name will end with
* one of the proposed suffixes.
* - option id: "org.eclipse.jdt.core.codeComplete.localSuffixes"
- * - possible values: { "<suffix>[,<suffix>]*" } where <suffix> is a String without any wild-card
+ * - possible values: { "<suffix>[,<suffix>]*" } where <suffix> is a String without any wild-card
* - default: ""
- *
- * CODEASSIST / Define the Suffixes for Argument Name
+ *
+ * CODEASSIST / Define the Suffixes for Argument Name
* When the suffixes is non empty, completion for argument name will end with
* one of the proposed suffixes.
* - option id: "org.eclipse.jdt.core.codeComplete.argumentSuffixes"
- * - possible values: { "<suffix>[,<suffix>]*" } where <suffix> is a String without any wild-card
+ * - possible values: { "<suffix>[,<suffix>]*" } where <suffix> is a String without any wild-card
* - default: ""
- *
- * CODEASSIST / Activate Forbidden Reference Sensitive Completion
- * When active, completion doesn't show that have forbidden reference.
+ *
+ * CODEASSIST / Activate Forbidden Reference Sensitive Completion
+ * When enabled, completion doesn't propose elements which match a
+ * forbidden reference rule.
* - option id: "org.eclipse.jdt.core.codeComplete.forbiddenReferenceCheck"
* - possible values: { "enabled", "disabled" }
* - default: "enabled"
- *
- * CODEASSIST / Activate Discouraged Reference Sensitive Completion
- * When active, completion doesn't show that have discouraged reference.
+ *
+ * CODEASSIST / Activate Discouraged Reference Sensitive Completion
+ * When enabled, completion doesn't propose elements which match a
+ * discouraged reference rule.
* - option id: "org.eclipse.jdt.core.codeComplete.discouragedReferenceCheck"
* - possible values: { "enabled", "disabled" }
* - default: "disabled"
+ *
+ * CODEASSIST / Activate Camel Case Sensitive Completion
+ * When enabled, completion shows proposals whose name match the CamelCase
+ * pattern.
+ * - option id: "org.eclipse.jdt.core.codeComplete.camelCaseMatch"
+ * - possible values: { "enabled", "disabled" }
+ * - default: "enabled"
+ *
+ * CODEASSIST / Activate Suggestion of Static Import
+ * When enabled, completion proposals can contain static import
+ * pattern.
+ * - option id: "org.eclipse.jdt.core.codeComplete.suggestStaticImports"
+ * - possible values: { "enabled", "disabled" }
+ * - default: "enabled"
* </pre>
- *
- * @return a mutable table containing the default settings of all known options
- * (key type: <code>String</code>; value type: <code>String</code>)
- * @see #setOptions(Hashtable)
*/
public static Hashtable getDefaultOptions(){
return JavaModelManager.getJavaModelManager().getDefaultOptions();
@@ -2339,7 +2754,7 @@
/**
* Returns the workspace root default charset encoding.
- *
+ *
* @return the name of the default charset encoding for workspace root.
* @see IContainer#getDefaultCharset()
* @see ResourcesPlugin#getEncoding()
@@ -2359,22 +2774,226 @@
}
/**
+ * Returns an array that contains the resources generated by the Java builder when building the
+ * compilation units contained in the given region.
+ * <p>The contents of the array is accurate only if the elements of the given region have been built.</p>
+ * <p>The given region can contain instances of:</p>
+ * <ul>
+ * <li><code>org.eclipse.jdt.core.ICompilationUnit</code></li>
+ * <li><code>org.eclipse.jdt.core.IPackageFragment</code></li>
+ * <li><code>org.eclipse.jdt.core.IPackageFragmentRoot</code></li>
+ * <li><code>org.eclipse.jdt.core.IJavaProject</code></li>
+ * </ul>
+ * <p>All other types of <code>org.eclipse.jdt.core.IJavaElement</code> are ignored.</p>
+ *
+ * @param region the given region
+ * @param includesNonJavaResources a flag that indicates if non-java resources should be included
+ *
+ * @return an array that contains the resources generated by the Java builder when building the
+ * compilation units contained in the given region, an empty array if none
+ * @exception IllegalArgumentException if the given region is <code>null</code>
+ * @since 3.3
+ */
+ public static IResource[] getGeneratedResources(IRegion region, boolean includesNonJavaResources) {
+ if (region == null) throw new IllegalArgumentException("region cannot be null"); //$NON-NLS-1$
+ IJavaElement[] elements = region.getElements();
+ HashMap projectsStates = new HashMap();
+ ArrayList collector = new ArrayList();
+ for (int i = 0, max = elements.length; i < max; i++) {
+ // collect all the java project
+ IJavaElement element = elements[i];
+ IJavaProject javaProject = element.getJavaProject();
+ IProject project = javaProject.getProject();
+ State state = null;
+ State currentState = (State) projectsStates.get(project);
+ if (currentState != null) {
+ state = currentState;
+ } else {
+ state = (State) JavaModelManager.getJavaModelManager().getLastBuiltState(project, null);
+ if (state != null) {
+ projectsStates.put(project, state);
+ }
+ }
+ if (state == null) continue;
+ if (element.getElementType() == IJavaElement.JAVA_PROJECT) {
+ IPackageFragmentRoot[] roots = null;
+ try {
+ roots = javaProject.getPackageFragmentRoots();
+ } catch (JavaModelException e) {
+ // ignore
+ }
+ if (roots == null) continue;
+ IRegion region2 = JavaCore.newRegion();
+ for (int j = 0; j < roots.length; j++) {
+ region2.add(roots[j]);
+ }
+ IResource[] res = getGeneratedResources(region2, includesNonJavaResources);
+ for (int j = 0, max2 = res.length; j < max2; j++) {
+ collector.add(res[j]);
+ }
+ continue;
+ }
+ IPath outputLocation = null;
+ try {
+ outputLocation = javaProject.getOutputLocation();
+ } catch (JavaModelException e) {
+ // ignore
+ }
+ IJavaElement root = element;
+ while (root != null && root.getElementType() != IJavaElement.PACKAGE_FRAGMENT_ROOT) {
+ root = root.getParent();
+ }
+ if (root == null) continue;
+ IPackageFragmentRoot packageFragmentRoot = (IPackageFragmentRoot) root;
+ int rootPathSegmentCounts = packageFragmentRoot.getPath().segmentCount();
+ try {
+ IClasspathEntry entry = packageFragmentRoot.getRawClasspathEntry();
+ IPath entryOutputLocation = entry.getOutputLocation();
+ if (entryOutputLocation != null) {
+ outputLocation = entryOutputLocation;
+ }
+ } catch (JavaModelException e) {
+ e.printStackTrace();
+ }
+ if (outputLocation == null) continue;
+ IContainer container = (IContainer) project.getWorkspace().getRoot().findMember(outputLocation);
+ switch(element.getElementType()) {
+ case IJavaElement.COMPILATION_UNIT :
+ // get the .class files generated when this element was built
+ ICompilationUnit unit = (ICompilationUnit) element;
+ getGeneratedResource(unit, container, state, rootPathSegmentCounts, collector);
+ break;
+ case IJavaElement.PACKAGE_FRAGMENT :
+ // collect all the .class files generated when all the units in this package were built
+ IPackageFragment fragment = (IPackageFragment) element;
+ ICompilationUnit[] compilationUnits = null;
+ try {
+ compilationUnits = fragment.getCompilationUnits();
+ } catch (JavaModelException e) {
+ // ignore
+ }
+ if (compilationUnits == null) continue;
+ for (int j = 0, max2 = compilationUnits.length; j < max2; j++) {
+ getGeneratedResource(compilationUnits[j], container, state, rootPathSegmentCounts, collector);
+ }
+ if (includesNonJavaResources) {
+ // retrieve all non-java resources from the output location using the package fragment path
+ Object[] nonJavaResources = null;
+ try {
+ nonJavaResources = fragment.getNonJavaResources();
+ } catch (JavaModelException e) {
+ // ignore
+ }
+ if (nonJavaResources != null) {
+ addNonJavaResources(nonJavaResources, container, rootPathSegmentCounts, collector);
+ }
+ }
+ break;
+ case IJavaElement.PACKAGE_FRAGMENT_ROOT :
+ // collect all the .class files generated when all the units in this package were built
+ IPackageFragmentRoot fragmentRoot = (IPackageFragmentRoot) element;
+ if (fragmentRoot.isArchive()) continue;
+ IJavaElement[] children = null;
+ try {
+ children = fragmentRoot.getChildren();
+ } catch (JavaModelException e) {
+ // ignore
+ }
+ if (children == null) continue;
+ for (int j = 0, max2 = children.length; j < max2; j++) {
+ fragment = (IPackageFragment) children[j];
+ ICompilationUnit[] units = null;
+ try {
+ units = fragment.getCompilationUnits();
+ } catch (JavaModelException e) {
+ // ignore
+ }
+ if (units == null) continue;
+ for (int n = 0, max3 = units.length; n < max3; n++) {
+ getGeneratedResource(units[n], container, state, rootPathSegmentCounts, collector);
+ }
+ if (includesNonJavaResources) {
+ // retrieve all non-java resources from the output location using the package fragment path
+ Object[] nonJavaResources = null;
+ try {
+ nonJavaResources = fragment.getNonJavaResources();
+ } catch (JavaModelException e) {
+ // ignore
+ }
+ if (nonJavaResources != null) {
+ addNonJavaResources(nonJavaResources, container, rootPathSegmentCounts, collector);
+ }
+ }
+ }
+ break;
+ }
+ }
+ int size = collector.size();
+ if (size != 0) {
+ IResource[] result = new IResource[size];
+ collector.toArray(result);
+ return result;
+ }
+ return NO_GENERATED_RESOURCES;
+ }
+
+ private static void getGeneratedResource(ICompilationUnit unit,
+ IContainer container,
+ State state,
+ int rootPathSegmentCounts,
+ ArrayList collector) {
+ IResource resource = unit.getResource();
+ char[][] typeNames = state.getDefinedTypeNamesFor(resource.getProjectRelativePath().toString());
+ if (typeNames != null) {
+ IPath path = unit.getPath().removeFirstSegments(rootPathSegmentCounts).removeLastSegments(1);
+ for (int j = 0, max2 = typeNames.length; j < max2; j++) {
+ IPath localPath = path.append(new String(typeNames[j]) + ".class"); //$NON-NLS-1$
+ IResource member = container.findMember(localPath);
+ if (member != null && member.exists()) {
+ collector.add(member);
+ }
+ }
+ } else {
+ IPath path = unit.getPath().removeFirstSegments(rootPathSegmentCounts).removeLastSegments(1);
+ path = path.append(Util.getNameWithoutJavaLikeExtension(unit.getElementName()) + ".class"); //$NON-NLS-1$
+ IResource member = container.findMember(path);
+ if (member != null && member.exists()) {
+ collector.add(member);
+ }
+ }
+ }
+
+ /**
* Returns the single instance of the Java core plug-in runtime class.
* Equivalent to <code>(JavaCore) getPlugin()</code>.
- *
+ *
* @return the single instance of the Java core plug-in runtime class
*/
public static JavaCore getJavaCore() {
return (JavaCore) getPlugin();
}
-
+
+ /**
+ * Returns the list of known Java-like extensions.
+ * Java like extension are defined in the {@link org.eclipse.core.runtime.Platform#getContentTypeManager()
+ * content type manager} for the {@link #JAVA_SOURCE_CONTENT_TYPE}.
+ * Note that a Java-like extension doesn't include the leading dot ('.').
+ * Also note that the "java" extension is always defined as a Java-like extension.
+ *
+ * @return the list of known Java-like extensions.
+ * @since 3.2
+ */
+ public static String[] getJavaLikeExtensions() {
+ return CharOperation.toStrings(Util.getJavaLikeExtensions());
+ }
+
/**
* Helper method for returning one option value only. Equivalent to <code>(String)JavaCore.getOptions().get(optionName)</code>
* Note that it may answer <code>null</code> if this option does not exist.
* <p>
* For a complete description of the configurable options, see <code>getDefaultOptions</code>.
* </p>
- *
+ *
* @param optionName the name of an option
* @return the String value of a given option
* @see JavaCore#getDefaultOptions()
@@ -2384,15 +3003,14 @@
public static String getOption(String optionName) {
return JavaModelManager.getJavaModelManager().getOption(optionName);
}
-
+
/**
* Returns the table of the current options. Initially, all options have their default values,
* and this method returns a table that includes all known options.
- * <p>
- * For a complete description of the configurable options, see <code>getDefaultOptions</code>.
- * </p>
- *
- * @return table of current settings of all options
+ * <p>For a complete description of the configurable options, see <code>getDefaultOptions</code>.</p>
+ * <p>Returns a default set of options even if the platform is not running.</p>
+ *
+ * @return table of current settings of all options
* (key type: <code>String</code>; value type: <code>String</code>)
* @see #getDefaultOptions()
* @see JavaCorePreferenceInitializer for changing default settings
@@ -2403,7 +3021,7 @@
/**
* Returns the single instance of the Java core plug-in runtime class.
- *
+ *
* @return the single instance of the Java core plug-in runtime class
*/
public static Plugin getPlugin() {
@@ -2411,9 +3029,9 @@
}
/**
- * This is a helper method, which returns the resolved classpath entry denoted
- * by a given entry (if it is a variable entry). It is obtained by resolving the variable
- * reference in the first segment. Returns <node>null</code> if unable to resolve using
+ * This is a helper method, which returns the resolved classpath entry denoted
+ * by a given entry (if it is a variable entry). It is obtained by resolving the variable
+ * reference in the first segment. Returns <code>null</code> if unable to resolve using
* the following algorithm:
* <ul>
* <li> if variable segment cannot be resolved, returns <code>null</code></li>
@@ -2427,62 +3045,60 @@
* NOTE: This helper method does not handle classpath containers, for which should rather be used
* <code>JavaCore#getClasspathContainer(IPath, IJavaProject)</code>.
* <p>
- *
+ *
* @param entry the given variable entry
* @return the resolved library or project classpath entry, or <code>null</code>
* if the given variable entry could not be resolved to a valid classpath entry
*/
public static IClasspathEntry getResolvedClasspathEntry(IClasspathEntry entry) {
-
+
if (entry.getEntryKind() != IClasspathEntry.CPE_VARIABLE)
return entry;
-
+
IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
IPath resolvedPath = JavaCore.getResolvedVariablePath(entry.getPath());
if (resolvedPath == null)
return null;
-
+
Object target = JavaModel.getTarget(workspaceRoot, resolvedPath, false);
if (target == null)
return null;
-
+
// inside the workspace
if (target instanceof IResource) {
IResource resolvedResource = (IResource) target;
- if (resolvedResource != null) {
- switch (resolvedResource.getType()) {
-
- case IResource.PROJECT :
- // internal project
- return JavaCore.newProjectEntry(
- resolvedPath,
- entry.getAccessRules(),
- entry.combineAccessRules(),
- entry.getExtraAttributes(),
- entry.isExported());
- case IResource.FILE :
- if (org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(resolvedResource.getName())) {
- // internal binary archive
- return JavaCore.newLibraryEntry(
- resolvedPath,
- getResolvedVariablePath(entry.getSourceAttachmentPath()),
- getResolvedVariablePath(entry.getSourceAttachmentRootPath()),
- entry.getAccessRules(),
- entry.getExtraAttributes(),
- entry.isExported());
- }
- break;
-
- case IResource.FOLDER :
- // internal binary folder
+ switch (resolvedResource.getType()) {
+
+ case IResource.PROJECT :
+ // internal project
+ return JavaCore.newProjectEntry(
+ resolvedPath,
+ entry.getAccessRules(),
+ entry.combineAccessRules(),
+ entry.getExtraAttributes(),
+ entry.isExported());
+ case IResource.FILE :
+ if (org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(resolvedResource.getName())) {
+ // internal binary archive
return JavaCore.newLibraryEntry(
resolvedPath,
getResolvedVariablePath(entry.getSourceAttachmentPath()),
getResolvedVariablePath(entry.getSourceAttachmentRootPath()),
- entry.getAccessRules(),
- entry.getExtraAttributes(),
+ entry.getAccessRules(),
+ entry.getExtraAttributes(),
entry.isExported());
- }
+ }
+ break;
+
+ case IResource.FOLDER :
+ // internal binary folder
+ return JavaCore.newLibraryEntry(
+ resolvedPath,
+ getResolvedVariablePath(entry.getSourceAttachmentPath()),
+ getResolvedVariablePath(entry.getSourceAttachmentRootPath()),
+ entry.getAccessRules(),
+ entry.getExtraAttributes(),
+ entry.isExported());
}
}
// outside the workspace
@@ -2490,7 +3106,7 @@
File externalFile = JavaModel.getFile(target);
if (externalFile != null) {
String fileName = externalFile.getName().toLowerCase();
- if (fileName.endsWith(SuffixConstants.SUFFIX_STRING_jar) || fileName.endsWith(SuffixConstants.SUFFIX_STRING_zip)) {
+ if (fileName.endsWith(SuffixConstants.SUFFIX_STRING_jar) || fileName.endsWith(SuffixConstants.SUFFIX_STRING_zip)) {
// external binary archive
return JavaCore.newLibraryEntry(
resolvedPath,
@@ -2518,211 +3134,275 @@
/**
* Resolve a variable path (helper method).
- *
+ *
* @param variablePath the given variable path
* @return the resolved variable path or <code>null</code> if none
*/
public static IPath getResolvedVariablePath(IPath variablePath) {
-
+
if (variablePath == null)
return null;
int count = variablePath.segmentCount();
if (count == 0)
return null;
-
- // lookup variable
+
+ // lookup variable
String variableName = variablePath.segment(0);
IPath resolvedPath = JavaCore.getClasspathVariable(variableName);
if (resolvedPath == null)
return null;
-
+
// append path suffix
if (count > 1) {
resolvedPath = resolvedPath.append(variablePath.removeFirstSegments(1));
}
- return resolvedPath;
+ return resolvedPath;
}
/**
- * Answers the shared working copies currently registered for this buffer factory.
- * Working copies can be shared by several clients using the same buffer factory,see
+ * Answers the shared working copies currently registered for this buffer factory.
+ * Working copies can be shared by several clients using the same buffer factory,see
* <code>IWorkingCopy.getSharedWorkingCopy</code>.
- *
+ *
* @param factory the given buffer factory
* @return the list of shared working copies for a given buffer factory
- * @see IWorkingCopy
* @since 2.0
- * @deprecated - should use #getWorkingCopies(WorkingCopyOwner) instead
+ * @deprecated Use {@link #getWorkingCopies(WorkingCopyOwner)} instead
*/
public static IWorkingCopy[] getSharedWorkingCopies(IBufferFactory factory){
-
+
// if factory is null, default factory must be used
if (factory == null) factory = BufferManager.getDefaultBufferManager().getDefaultBufferFactory();
return getWorkingCopies(BufferFactoryWrapper.create(factory));
}
-
+
/**
* Returns the names of all defined user libraries. The corresponding classpath container path
- * is the name appended to the USER_LIBRARY_CONTAINER_ID.
+ * is the name appended to the USER_LIBRARY_CONTAINER_ID.
* @return Return an array containing the names of all known user defined.
* @since 3.0
*/
public static String[] getUserLibraryNames() {
- return UserLibraryManager.getUserLibraryNames();
+ return JavaModelManager.getUserLibraryManager().getUserLibraryNames();
}
/**
- * Returns the working copies that have the given owner.
+ * Returns the working copies that have the given owner.
* Only compilation units in working copy mode are returned.
* If the owner is <code>null</code>, primary working copies are returned.
- *
- * @param owner the given working copy owner or <null> for primary working copy owner
+ *
+ * @param owner the given working copy owner or <code>null</code> for primary working copy owner
* @return the list of working copies for a given owner
* @since 3.0
*/
public static ICompilationUnit[] getWorkingCopies(WorkingCopyOwner owner){
-
+
JavaModelManager manager = JavaModelManager.getJavaModelManager();
if (owner == null) owner = DefaultWorkingCopyOwner.PRIMARY;
ICompilationUnit[] result = manager.getWorkingCopies(owner, false/*don't add primary WCs*/);
if (result == null) return JavaModelManager.NO_WORKING_COPY;
return result;
}
-
+
/**
- * Initializes JavaCore internal structures to allow subsequent operations (such
- * as the ones that need a resolved classpath) to run full speed. A client may
- * choose to call this method in a background thread early after the workspace
+ * Initializes JavaCore internal structures to allow subsequent operations (such
+ * as the ones that need a resolved classpath) to run full speed. A client may
+ * choose to call this method in a background thread early after the workspace
* has started so that the initialization is transparent to the user.
* <p>
- * However calling this method is optional. Services will lazily perform
- * initialization when invoked. This is only a way to reduce initialization
- * overhead on user actions, if it can be performed before at some
+ * However calling this method is optional. Services will lazily perform
+ * initialization when invoked. This is only a way to reduce initialization
+ * overhead on user actions, if it can be performed before at some
* appropriate moment.
* </p><p>
* This initialization runs accross all Java projects in the workspace. Thus the
* workspace root scheduling rule is used during this operation.
* </p><p>
- * This method may return before the initialization is complete. The
+ * This method may return before the initialization is complete. The
* initialization will then continue in a background thread.
* </p><p>
* This method can be called concurrently.
* </p>
- *
+ *
* @param monitor a progress monitor, or <code>null</code> if progress
* reporting and cancellation are not desired
- * @exception CoreException if the initialization fails,
+ * @exception CoreException if the initialization fails,
* the status of the exception indicates the reason of the failure
* @since 3.1
*/
public static void initializeAfterLoad(IProgressMonitor monitor) throws CoreException {
- Job job = new Job(Messages.javamodel_initialization) {
- protected IStatus run(IProgressMonitor progressMonitor) {
- // dummy query for waiting until the indexes are ready and classpath containers/variables are initialized
- SearchEngine engine = new SearchEngine();
- IJavaSearchScope scope = SearchEngine.createWorkspaceScope(); // initialize all containers and variables
- try {
- engine.searchAllTypeNames(
- null,
- "!@$#!@".toCharArray(), //$NON-NLS-1$
- SearchPattern.R_PATTERN_MATCH | SearchPattern.R_CASE_SENSITIVE,
- IJavaSearchConstants.CLASS,
- scope,
- new TypeNameRequestor() {
- public void acceptType(
- int modifiers,
- char[] packageName,
- char[] simpleTypeName,
- char[][] enclosingTypeNames,
- String path) {
- // no type to accept
- }
- },
- // will not activate index query caches if indexes are not ready, since it would take to long
- // to wait until indexes are fully rebuild
- IJavaSearchConstants.CANCEL_IF_NOT_READY_TO_SEARCH,
- progressMonitor == null ? null : new SubProgressMonitor(progressMonitor, 99) // 99% of the time is spent in the dummy search
- );
- } catch (JavaModelException e) {
- // /search failed: ignore
- } catch (OperationCanceledException e) {
- if (progressMonitor != null && progressMonitor.isCanceled())
- throw e;
- // else indexes were not ready: catch the exception so that jars are still refreshed
+ try {
+ if (monitor != null) monitor.beginTask(Messages.javamodel_initialization, 100);
+
+ // initialize all containers and variables
+ JavaModelManager manager = JavaModelManager.getJavaModelManager();
+ try {
+ if (monitor != null) {
+ monitor.subTask(Messages.javamodel_configuring_classpath_containers);
+ manager.batchContainerInitializationsProgress.set(new SubProgressMonitor(monitor, 50)); // 50% of the time is spent in initializing containers and variables
}
- // check if the build state version number has changed since last session
- // (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=98969)
- QualifiedName qName = new QualifiedName(JavaCore.PLUGIN_ID, "stateVersionNumber"); //$NON-NLS-1$
- IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
- String versionNumber = null;
- try {
- versionNumber = root.getPersistentProperty(qName);
- } catch (CoreException e) {
- // could not read version number: consider it is new
+ // all classpaths in the workspace are going to be resolved, ensure that containers are initialized in one batch
+ manager.batchContainerInitializations = true;
+
+ // avoid leaking source attachment properties (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=183413)
+ IJavaProject[] projects = manager.getJavaModel().getJavaProjects();
+ for (int i = 0, length = projects.length; i < length; i++) {
+ IClasspathEntry[] classpath;
+ try {
+ classpath = ((JavaProject) projects[i]).getResolvedClasspath();
+ } catch (JavaModelException e) {
+ // project no longer exist: ignore
+ continue;
+ }
+ if (classpath != null) {
+ for (int j = 0, length2 = classpath.length; j < length2; j++) {
+ IClasspathEntry entry = classpath[j];
+ if (entry.getSourceAttachmentPath() != null)
+ Util.setSourceAttachmentProperty(entry.getPath(), null);
+ // else source might have been attached by IPackageFragmentRoot#attachSource(...), we keep it
+ }
+ }
}
- final JavaModel model = JavaModelManager.getJavaModelManager().getJavaModel();
- String newVersionNumber = Byte.toString(State.VERSION);
- if (!newVersionNumber.equals(versionNumber)) {
- // build state version number has changed: touch every projects to force a rebuild
- if (JavaBuilder.DEBUG)
- System.out.println("Build state version number has changed"); //$NON-NLS-1$
- IWorkspaceRunnable runnable = new IWorkspaceRunnable() {
- public void run(IProgressMonitor progressMonitor2) throws CoreException {
- IJavaProject[] projects = null;
- try {
- projects = model.getJavaProjects();
- } catch (JavaModelException e) {
- // could not get Java projects: ignore
- }
- if (projects != null) {
- for (int i = 0, length = projects.length; i < length; i++) {
- IJavaProject project = projects[i];
- try {
- if (JavaBuilder.DEBUG)
- System.out.println("Touching " + project.getElementName()); //$NON-NLS-1$
- project.getProject().touch(progressMonitor2);
- } catch (CoreException e) {
- // could not touch this project: ignore
- }
+
+ // initialize delta state
+ manager.deltaState.rootsAreStale = true; // in case it was already initialized before we cleaned up the source attachment proprties
+ manager.deltaState.initializeRoots();
+ } finally {
+ manager.batchContainerInitializationsProgress.set(null);
+ }
+
+ // dummy query for waiting until the indexes are ready
+ SearchEngine engine = new SearchEngine();
+ IJavaSearchScope scope = SearchEngine.createWorkspaceScope();
+ try {
+ if (monitor != null)
+ monitor.subTask(Messages.javamodel_configuring_searchengine);
+ engine.searchAllTypeNames(
+ null,
+ SearchPattern.R_EXACT_MATCH,
+ "!@$#!@".toCharArray(), //$NON-NLS-1$
+ SearchPattern.R_PATTERN_MATCH | SearchPattern.R_CASE_SENSITIVE,
+ IJavaSearchConstants.CLASS,
+ scope,
+ new TypeNameRequestor() {
+ public void acceptType(
+ int modifiers,
+ char[] packageName,
+ char[] simpleTypeName,
+ char[][] enclosingTypeNames,
+ String path) {
+ // no type to accept
+ }
+ },
+ // will not activate index query caches if indexes are not ready, since it would take to long
+ // to wait until indexes are fully rebuild
+ IJavaSearchConstants.CANCEL_IF_NOT_READY_TO_SEARCH,
+ monitor == null ? null : new SubProgressMonitor(monitor, 49) // 49% of the time is spent in the dummy search
+ );
+ } catch (JavaModelException e) {
+ // /search failed: ignore
+ } catch (OperationCanceledException e) {
+ if (monitor != null && monitor.isCanceled())
+ throw e;
+ // else indexes were not ready: catch the exception so that jars are still refreshed
+ }
+
+ // check if the build state version number has changed since last session
+ // (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=98969)
+ if (monitor != null)
+ monitor.subTask(Messages.javamodel_getting_build_state_number);
+ QualifiedName qName = new QualifiedName(JavaCore.PLUGIN_ID, "stateVersionNumber"); //$NON-NLS-1$
+ IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+ String versionNumber = null;
+ try {
+ versionNumber = root.getPersistentProperty(qName);
+ } catch (CoreException e) {
+ // could not read version number: consider it is new
+ }
+ final JavaModel model = manager.getJavaModel();
+ String newVersionNumber = Byte.toString(State.VERSION);
+ if (!newVersionNumber.equals(versionNumber)) {
+ // build state version number has changed: touch every projects to force a rebuild
+ if (JavaBuilder.DEBUG)
+ System.out.println("Build state version number has changed"); //$NON-NLS-1$
+ IWorkspaceRunnable runnable = new IWorkspaceRunnable() {
+ public void run(IProgressMonitor progressMonitor2) throws CoreException {
+ IJavaProject[] projects = null;
+ try {
+ projects = model.getJavaProjects();
+ } catch (JavaModelException e) {
+ // could not get Java projects: ignore
+ }
+ if (projects != null) {
+ for (int i = 0, length = projects.length; i < length; i++) {
+ IJavaProject project = projects[i];
+ try {
+ if (JavaBuilder.DEBUG)
+ System.out.println("Touching " + project.getElementName()); //$NON-NLS-1$
+ project.getProject().touch(progressMonitor2);
+ } catch (CoreException e) {
+ // could not touch this project: ignore
}
}
}
- };
- try {
- ResourcesPlugin.getWorkspace().run(runnable, progressMonitor);
- } catch (CoreException e) {
- // could not touch all projects
}
- try {
- root.setPersistentProperty(qName, newVersionNumber);
- } catch (CoreException e) {
- Util.log(e, "Could not persist build state version number"); //$NON-NLS-1$
- }
- }
-
- // ensure external jars are refreshed (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=93668)
+ };
+ if (monitor != null)
+ monitor.subTask(Messages.javamodel_building_after_upgrade);
try {
- model.refreshExternalArchives(
- null/*refresh all projects*/,
- progressMonitor == null ? null : new SubProgressMonitor(progressMonitor, 1) // 1% of the time is spent in jar refresh
- );
- } catch (JavaModelException e) {
- // refreshing failed: ignore
+ ResourcesPlugin.getWorkspace().run(runnable, monitor);
+ } catch (CoreException e) {
+ // could not touch all projects
}
-
- return Status.OK_STATUS;
+ try {
+ root.setPersistentProperty(qName, newVersionNumber);
+ } catch (CoreException e) {
+ Util.log(e, "Could not persist build state version number"); //$NON-NLS-1$
+ }
}
- public boolean belongsTo(Object family) {
- return PLUGIN_ID.equals(family);
+
+ // ensure external jars are refreshed (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=93668)
+ try {
+ if (monitor != null)
+ monitor.subTask(Messages.javamodel_refreshing_external_jars);
+ model.refreshExternalArchives(
+ null/*refresh all projects*/,
+ monitor == null ? null : new SubProgressMonitor(monitor, 1) // 1% of the time is spent in jar refresh
+ );
+ } catch (JavaModelException e) {
+ // refreshing failed: ignore
}
- };
- job.setPriority(Job.SHORT);
- job.schedule(2000); // wait for the startup activity to calm down
-
+
+ } finally {
+ if (monitor != null) monitor.done();
+ }
}
-
+
+ /**
+ * Returns whether a given classpath variable is read-only or not.
+ *
+ * @param variableName
+ * @return <code>true</code> if the classpath variable is read-only,
+ * <code>false</code> otherwise.
+ * @since 3.3
+ */
+ public static boolean isClasspathVariableReadOnly(String variableName) {
+ return JavaModelManager.getJavaModelManager().readOnlyVariables.contains(variableName);
+ }
+
+ /**
+ * Returns whether the given file name's extension is a Java-like extension.
+ *
+ * @return whether the given file name's extension is a Java-like extension
+ * @see #getJavaLikeExtensions()
+ * @since 3.2
+ */
+ public static boolean isJavaLikeFileName(String fileName) {
+ return Util.isJavaLikeFileName(fileName);
+ }
+
/**
* Returns whether the given marker references the given Java element.
* Used for markers, which denote a Java element rather than a resource.
@@ -2730,10 +3410,10 @@
* @param element the element
* @param marker the marker
* @return <code>true</code> if the marker references the element, false otherwise
- * @exception CoreException if the <code>IMarker.getAttribute</code> on the marker fails
+ * @exception CoreException if the <code>IMarker.getAttribute</code> on the marker fails
*/
public static boolean isReferencedBy(IJavaElement element, IMarker marker) throws CoreException {
-
+
// only match units or classfiles
if (element instanceof IMember){
IMember member = (IMember) element;
@@ -2743,16 +3423,16 @@
element = member.getCompilationUnit();
}
}
- if (element == null) return false;
+ if (element == null) return false;
if (marker == null) return false;
String markerHandleId = (String)marker.getAttribute(ATT_HANDLE_ID);
if (markerHandleId == null) return false;
-
+
IJavaElement markerElement = JavaCore.create(markerHandleId);
while (true){
if (element.equals(markerElement)) return true; // external elements may still be equal with different handleIDs.
-
+
// cycle through enclosing types in case marker is associated with a classfile (15568)
if (markerElement instanceof IClassFile){
IType enclosingType = ((IClassFile)markerElement).getType().getDeclaringType();
@@ -2773,10 +3453,10 @@
* @param element the element
* @param markerDelta the marker delta
* @return <code>true</code> if the marker delta references the element
- * @exception CoreException if the <code>IMarkerDelta.getAttribute</code> on the marker delta fails
+ * @exception CoreException if the <code>IMarkerDelta.getAttribute</code> on the marker delta fails
*/
public static boolean isReferencedBy(IJavaElement element, IMarkerDelta markerDelta) throws CoreException {
-
+
// only match units or classfiles
if (element instanceof IMember){
IMember member = (IMember) element;
@@ -2786,16 +3466,16 @@
element = member.getCompilationUnit();
}
}
- if (element == null) return false;
+ if (element == null) return false;
if (markerDelta == null) return false;
String markerDeltarHandleId = (String)markerDelta.getAttribute(ATT_HANDLE_ID);
if (markerDeltarHandleId == null) return false;
-
+
IJavaElement markerElement = JavaCore.create(markerDeltarHandleId);
while (true){
if (element.equals(markerElement)) return true; // external elements may still be equal with different handleIDs.
-
+
// cycle through enclosing types in case marker is associated with a classfile (15568)
if (markerElement instanceof IClassFile){
IType enclosingType = ((IClassFile)markerElement).getType().getDeclaringType();
@@ -2808,22 +3488,29 @@
}
return false;
}
-
+
/**
* Creates and returns a new access rule with the given file pattern and kind.
- *
+ * <p>
+ * The rule kind is one of {@link IAccessRule#K_ACCESSIBLE}, {@link IAccessRule#K_DISCOURAGED},
+ * or {@link IAccessRule#K_NON_ACCESSIBLE}, optionally combined with {@link IAccessRule#IGNORE_IF_BETTER},
+ * e..g. <code>IAccessRule.K_NON_ACCESSIBLE | IAccessRule.IGNORE_IF_BETTER</code>.
+ * </p>
+ *
* @param filePattern the file pattern this access rule should match
- * @param kind one of IAccessRule#K_ACCESSIBLE, IAcccessRule#K_STRICTLY_NON_ACCESSIBLE, or IAcccessRule#K_LOOSELY_NON_ACCESSIBLE
+ * @param kind one of {@link IAccessRule#K_ACCESSIBLE}, {@link IAccessRule#K_DISCOURAGED},
+ * or {@link IAccessRule#K_NON_ACCESSIBLE}, optionally combined with
+ * {@link IAccessRule#IGNORE_IF_BETTER}
* @return a new access rule
* @since 3.1
*/
public static IAccessRule newAccessRule(IPath filePattern, int kind) {
return new ClasspathAccessRule(filePattern, kind);
}
-
+
/**
* Creates and returns a new classpath attribute with the given name and the given value.
- *
+ *
* @return a new classpath attribute
* @since 3.1
*/
@@ -2840,7 +3527,7 @@
* @param containerPath the path identifying the container, it must be formed of two
* segments
* @return a new container classpath entry
- *
+ *
* @see JavaCore#getClasspathContainer(IPath, IJavaProject)
* @since 2.0
*/
@@ -2856,14 +3543,14 @@
* Creates and returns a new classpath entry of kind <code>CPE_CONTAINER</code>
* for the given path. This method is fully equivalent to calling
* {@link #newContainerEntry(IPath, IAccessRule[], IClasspathAttribute[], boolean)
- * newContainerEntry(containerPath, new IAccessRule[0], new IClasspathAttribute[0], isExported)}.
- *
+ * newContainerEntry(containerPath, new IAccessRule[0], new IClasspathAttribute[0], isExported)}.
+ *
* @param containerPath the path identifying the container, it must be formed of at least
* one segment (ID+hints)
* @param isExported a boolean indicating whether this entry is contributed to dependent
* projects in addition to the output location
* @return a new container classpath entry
- *
+ *
* @see JavaCore#getClasspathContainer(IPath, IJavaProject)
* @see JavaCore#setClasspathContainer(IPath, IJavaProject[], IClasspathContainer[], IProgressMonitor)
* @since 2.0
@@ -2899,12 +3586,12 @@
* Example of an ClasspathContainerInitializer for a classpath container denoting a default JDK container:
* <pre>
* containerEntry = JavaCore.newContainerEntry(new Path("MyProvidedJDK/default"));
- *
+ *
* <extension
* point="org.eclipse.jdt.core.classpathContainerInitializer">
* <containerInitializer
* id="MyProvidedJDK"
- * class="com.example.MyInitializer"/>
+ * class="com.example.MyInitializer"/>
* </pre>
* <p>
* The access rules determine the set of accessible source and class files
@@ -2913,7 +3600,7 @@
* See {@link IAccessRule} for a detailed description of access
* rules. Note that if an entry defined by the container defines access rules,
* then these access rules are combined with the given access rules.
- * The given access rules are considered first, then the entry's access rules are
+ * The given access rules are considered first, then the entry's access rules are
* considered.
* </p>
* <p>
@@ -2926,13 +3613,13 @@
* projects. If not exported, dependent projects will not see any of the classes from this entry.
* If exported, dependent projects will concatenate the accessible files patterns of this entry with the
* accessible files patterns of the projects, and they will concatenate the non accessible files patterns of this entry
- * with the non accessible files patterns of the project.
+ * with the non accessible files patterns of the project.
* </p>
* <p>
* Note that this operation does not attempt to validate classpath containers
* or access the resources at the given paths.
* </p>
- *
+ *
* @param containerPath the path identifying the container, it must be formed of at least
* one segment (ID+hints)
* @param accessRules the possibly empty list of access rules for this entry
@@ -2940,21 +3627,22 @@
* @param isExported a boolean indicating whether this entry is contributed to dependent
* projects in addition to the output location
* @return a new container classpath entry
- *
+ *
* @see JavaCore#getClasspathContainer(IPath, IJavaProject)
* @see JavaCore#setClasspathContainer(IPath, IJavaProject[], IClasspathContainer[], IProgressMonitor)
* @see JavaCore#newContainerEntry(IPath, boolean)
* @see JavaCore#newAccessRule(IPath, int)
* @since 3.1
- */
+ */
public static IClasspathEntry newContainerEntry(
- IPath containerPath,
- IAccessRule[] accessRules,
+ IPath containerPath,
+ IAccessRule[] accessRules,
IClasspathAttribute[] extraAttributes,
boolean isExported) {
-
- if (containerPath == null) Assert.isTrue(false, "Container path cannot be null"); //$NON-NLS-1$
- if (containerPath.segmentCount() < 1) {
+
+ if (containerPath == null) {
+ Assert.isTrue(false, "Container path cannot be null"); //$NON-NLS-1$
+ } else if (containerPath.segmentCount() < 1) {
Assert.isTrue(
false,
"Illegal classpath container path: \'" + containerPath.makeRelative().toString() + "\', must have at least one segment (containerID+hints)"); //$NON-NLS-1$//$NON-NLS-2$
@@ -2972,13 +3660,13 @@
accessRules,
true, // combine access rules
extraAttributes);
- }
-
+ }
+
/**
* Creates and returns a type hierarchy for all types in the given
- * region, considering subtypes within that region and considering types in the
- * working copies with the given owner.
- * In other words, the owner's working copies will take
+ * region, considering subtypes within that region and considering types in the
+ * working copies with the given owner.
+ * In other words, the owner's working copies will take
* precedence over their original compilation units in the workspace.
* <p>
* Note that if a working copy is empty, it will be as if the original compilation
@@ -3006,20 +3694,20 @@
op.runOperation(monitor);
return op.getResult();
}
-
+
/**
- * Creates and returns a new non-exported classpath entry of kind <code>CPE_LIBRARY</code> for the
- * JAR or folder identified by the given absolute path. This specifies that all package fragments
+ * Creates and returns a new non-exported classpath entry of kind <code>CPE_LIBRARY</code> for the
+ * JAR or folder identified by the given absolute path. This specifies that all package fragments
* within the root will have children of type <code>IClassFile</code>.
* This method is fully equivalent to calling
* {@link #newLibraryEntry(IPath, IPath, IPath, IAccessRule[], IClasspathAttribute[], boolean)
* newLibraryEntry(path, sourceAttachmentPath, sourceAttachmentRootPath, new IAccessRule[0], new IClasspathAttribute[0], false)}.
*
* @param path the absolute path of the binary archive
- * @param sourceAttachmentPath the absolute path of the corresponding source archive or folder,
+ * @param sourceAttachmentPath the absolute path of the corresponding source archive or folder,
* or <code>null</code> if none. Note, since 3.0, an empty path is allowed to denote no source attachment.
* and will be automatically converted to <code>null</code>.
- * @param sourceAttachmentRootPath the location of the root within the source archive or folder
+ * @param sourceAttachmentRootPath the location of the root of the source files within the source archive or folder
* or <code>null</code> if this location should be automatically detected.
* @return a new library classpath entry
*/
@@ -3027,9 +3715,9 @@
IPath path,
IPath sourceAttachmentPath,
IPath sourceAttachmentRootPath) {
-
+
return newLibraryEntry(
- path,
+ path,
sourceAttachmentPath,
sourceAttachmentRootPath,
ClasspathEntry.NO_ACCESS_RULES,
@@ -3039,17 +3727,17 @@
/**
* Creates and returns a new classpath entry of kind <code>CPE_LIBRARY</code> for the JAR or folder
- * identified by the given absolute path. This specifies that all package fragments within the root
+ * identified by the given absolute path. This specifies that all package fragments within the root
* will have children of type <code>IClassFile</code>.
* This method is fully equivalent to calling
* {@link #newLibraryEntry(IPath, IPath, IPath, IAccessRule[], IClasspathAttribute[], boolean)
* newLibraryEntry(path, sourceAttachmentPath, sourceAttachmentRootPath, new IAccessRule[0], new IClasspathAttribute[0], isExported)}.
- *
+ *
* @param path the absolute path of the binary archive
- * @param sourceAttachmentPath the absolute path of the corresponding source archive or folder,
+ * @param sourceAttachmentPath the absolute path of the corresponding source archive or folder,
* or <code>null</code> if none. Note, since 3.0, an empty path is allowed to denote no source attachment.
* and will be automatically converted to <code>null</code>.
- * @param sourceAttachmentRootPath the location of the root within the source archive or folder
+ * @param sourceAttachmentRootPath the location of the root of the source files within the source archive or folder
* or <code>null</code> if this location should be automatically detected.
* @param isExported indicates whether this entry is contributed to dependent
* projects in addition to the output location
@@ -3061,9 +3749,9 @@
IPath sourceAttachmentPath,
IPath sourceAttachmentRootPath,
boolean isExported) {
-
+
return newLibraryEntry(
- path,
+ path,
sourceAttachmentPath,
sourceAttachmentRootPath,
ClasspathEntry.NO_ACCESS_RULES,
@@ -3073,7 +3761,7 @@
/**
* Creates and returns a new classpath entry of kind <code>CPE_LIBRARY</code> for the JAR or folder
- * identified by the given absolute path. This specifies that all package fragments within the root
+ * identified by the given absolute path. This specifies that all package fragments within the root
* will have children of type <code>IClassFile</code>.
* <p>
* A library entry is used to denote a prerequisite JAR or root folder containing binaries.
@@ -3084,13 +3772,19 @@
* linked (see IFolder#createLink(...)).
* <p>
* e.g. Here are some examples of binary path usage<ul>
- * <li><code> "c:/jdk1.2.2/jre/lib/rt.jar" </code> - reference to an external JAR</li>
- * <li><code> "/Project/someLib.jar" </code> - reference to an internal JAR </li>
- * <li><code> "/Project/classes/" </code> - reference to an internal binary folder</li>
+ * <li><code> "c:\jdk1.2.2\jre\lib\rt.jar" </code> - reference to an external JAR on Windows</li>
+ * <li><code> "/Project/someLib.jar" </code> - reference to an internal JAR on Windows or Linux</li>
+ * <li><code> "/Project/classes/" </code> - reference to an internal binary folder on Windows or Linux</li>
* </ul>
- * Note that this operation does not attempt to validate or access the
+ * Note that on non-Windows platform, a path <code>"/some/lib.jar"</code> is ambiguous.
+ * It can be a path to an external JAR (its file system path being <code>"/some/lib.jar"</code>)
+ * or it can be a path to an internal JAR (<code>"some"</code> being a project in the workspace).
+ * Such an ambiguity is solved when the classpath entry is used (e.g. in {@link IJavaProject#getPackageFragmentRoots()}).
+ * If the resource <code>"lib.jar"</code> exists in project <code>"some"</code>, then it is considered an
+ * internal JAR. Otherwise it is an external JAR.
+ * <p>Also note that this operation does not attempt to validate or access the
* resources at the given paths.
- * <p>
+ * </p><p>
* The access rules determine the set of accessible class files
* in the library. If the list of access rules is empty then all files
* in this library are accessible.
@@ -3107,14 +3801,14 @@
* projects. If not exported, dependent projects will not see any of the classes from this entry.
* If exported, dependent projects will concatenate the accessible files patterns of this entry with the
* accessible files patterns of the projects, and they will concatenate the non accessible files patterns of this entry
- * with the non accessible files patterns of the project.
+ * with the non accessible files patterns of the project.
* </p>
- *
+ *
* @param path the absolute path of the binary archive
- * @param sourceAttachmentPath the absolute path of the corresponding source archive or folder,
+ * @param sourceAttachmentPath the absolute path of the corresponding source archive or folder,
* or <code>null</code> if none. Note, since 3.0, an empty path is allowed to denote no source attachment.
* and will be automatically converted to <code>null</code>.
- * @param sourceAttachmentRootPath the location of the root within the source archive or folder
+ * @param sourceAttachmentRootPath the location of the root of the source files within the source archive or folder
* or <code>null</code> if this location should be automatically detected.
* @param accessRules the possibly empty list of access rules for this entry
* @param extraAttributes the possibly empty list of extra attributes to persist with this entry
@@ -3127,10 +3821,10 @@
IPath path,
IPath sourceAttachmentPath,
IPath sourceAttachmentRootPath,
- IAccessRule[] accessRules,
+ IAccessRule[] accessRules,
IClasspathAttribute[] extraAttributes,
boolean isExported) {
-
+
if (path == null) Assert.isTrue(false, "Library path cannot be null"); //$NON-NLS-1$
if (!path.isAbsolute()) Assert.isTrue(false, "Path for IClasspathEntry must be absolute"); //$NON-NLS-1$
if (sourceAttachmentPath != null) {
@@ -3156,28 +3850,28 @@
false, // no access rules to combine
extraAttributes);
}
-
+
/**
* Creates and returns a new non-exported classpath entry of kind <code>CPE_PROJECT</code>
* for the project identified by the given absolute path.
* This method is fully equivalent to calling
* {@link #newProjectEntry(IPath, IAccessRule[], boolean, IClasspathAttribute[], boolean)
* newProjectEntry(path, new IAccessRule[0], true, new IClasspathAttribute[0], false)}.
- *
+ *
* @param path the absolute path of the binary archive
* @return a new project classpath entry
*/
public static IClasspathEntry newProjectEntry(IPath path) {
return newProjectEntry(path, false);
}
-
+
/**
* Creates and returns a new classpath entry of kind <code>CPE_PROJECT</code>
* for the project identified by the given absolute path.
* This method is fully equivalent to calling
* {@link #newProjectEntry(IPath, IAccessRule[], boolean, IClasspathAttribute[], boolean)
* newProjectEntry(path, new IAccessRule[0], true, new IClasspathAttribute[0], isExported)}.
- *
+ *
* @param path the absolute path of the prerequisite project
* @param isExported indicates whether this entry is contributed to dependent
* projects in addition to the output location
@@ -3185,9 +3879,9 @@
* @since 2.0
*/
public static IClasspathEntry newProjectEntry(IPath path, boolean isExported) {
-
+
if (!path.isAbsolute()) Assert.isTrue(false, "Path for IClasspathEntry must be absolute"); //$NON-NLS-1$
-
+
return newProjectEntry(
path,
ClasspathEntry.NO_ACCESS_RULES,
@@ -3202,11 +3896,11 @@
* <p>
* A project entry is used to denote a prerequisite project on a classpath.
* The referenced project will be contributed as a whole, either as sources (in the Java Model, it
- * contributes all its package fragment roots) or as binaries (when building, it contributes its
+ * contributes all its package fragment roots) or as binaries (when building, it contributes its
* whole output location).
* </p>
* <p>
- * A project reference allows to indirect through another project, independently from its internal layout.
+ * A project reference allows to indirect through another project, independently from its internal layout.
* </p><p>
* The prerequisite project is referred to using an absolute path relative to the workspace root.
* </p>
@@ -3219,7 +3913,7 @@
* <p>
* The <code>combineAccessRules</code> flag indicates whether access rules of one (or more)
* exported entry of the project should be combined with the given access rules. If they should
- * be combined, the given access rules are considered first, then the entry's access rules are
+ * be combined, the given access rules are considered first, then the entry's access rules are
* considered.
* </p>
* <p>
@@ -3232,9 +3926,9 @@
* projects. If not exported, dependent projects will not see any of the classes from this entry.
* If exported, dependent projects will concatenate the accessible files patterns of this entry with the
* accessible files patterns of the projects, and they will concatenate the non accessible files patterns of this entry
- * with the non accessible files patterns of the project.
+ * with the non accessible files patterns of the project.
* </p>
- *
+ *
* @param path the absolute path of the prerequisite project
* @param accessRules the possibly empty list of access rules for this entry
* @param combineAccessRules whether the access rules of the project's exported entries should be combined with the given access rules
@@ -3245,14 +3939,14 @@
* @since 3.1
*/
public static IClasspathEntry newProjectEntry(
- IPath path,
- IAccessRule[] accessRules,
+ IPath path,
+ IAccessRule[] accessRules,
boolean combineAccessRules,
IClasspathAttribute[] extraAttributes,
boolean isExported) {
-
+
if (!path.isAbsolute()) Assert.isTrue(false, "Path for IClasspathEntry must be absolute"); //$NON-NLS-1$
-
+
return new ClasspathEntry(
IPackageFragmentRoot.K_SOURCE,
IClasspathEntry.CPE_PROJECT,
@@ -3270,7 +3964,7 @@
/**
* Returns a new empty region.
- *
+ *
* @return a new empty region
*/
public static IRegion newRegion() {
@@ -3287,7 +3981,7 @@
* newSourceEntry(path, new IPath[] {}, new IPath[] {}, null);
* </pre>
* </p>
- *
+ *
* @param path the absolute workspace-relative path of a source folder
* @return a new source classpath entry
* @see #newSourceEntry(IPath, IPath[], IPath[], IPath)
@@ -3296,10 +3990,10 @@
return newSourceEntry(path, ClasspathEntry.INCLUDE_ALL, ClasspathEntry.EXCLUDE_NONE, null /*output location*/);
}
-
+
/**
* Creates and returns a new classpath entry of kind <code>CPE_SOURCE</code>
- * for the project's source folder identified by the given absolute
+ * for the project's source folder identified by the given absolute
* workspace-relative path but excluding all source files with paths
* matching any of the given patterns.
* <p>
@@ -3318,15 +4012,15 @@
*/
public static IClasspathEntry newSourceEntry(IPath path, IPath[] exclusionPatterns) {
- return newSourceEntry(path, ClasspathEntry.INCLUDE_ALL, exclusionPatterns, null /*output location*/);
+ return newSourceEntry(path, ClasspathEntry.INCLUDE_ALL, exclusionPatterns, null /*output location*/);
}
/**
* Creates and returns a new classpath entry of kind <code>CPE_SOURCE</code>
- * for the project's source folder identified by the given absolute
+ * for the project's source folder identified by the given absolute
* workspace-relative path but excluding all source files with paths
* matching any of the given patterns, and associated with a specific output location
- * (that is, ".class" files are not going to the project default output location).
+ * (that is, ".class" files are not going to the project default output location).
* <p>
* The convenience method is fully equivalent to:
* <pre>
@@ -3346,13 +4040,13 @@
return newSourceEntry(path, ClasspathEntry.INCLUDE_ALL, exclusionPatterns, specificOutputLocation);
}
-
+
/**
* Creates and returns a new classpath entry of kind <code>CPE_SOURCE</code>
- * for the project's source folder identified by the given absolute
+ * for the project's source folder identified by the given absolute
* workspace-relative path but excluding all source files with paths
* matching any of the given patterns, and associated with a specific output location
- * (that is, ".class" files are not going to the project default output location).
+ * (that is, ".class" files are not going to the project default output location).
* <p>
* The convenience method is fully equivalent to:
* <pre>
@@ -3373,16 +4067,16 @@
public static IClasspathEntry newSourceEntry(IPath path, IPath[] inclusionPatterns, IPath[] exclusionPatterns, IPath specificOutputLocation) {
return newSourceEntry(path, inclusionPatterns, exclusionPatterns, specificOutputLocation, ClasspathEntry.NO_EXTRA_ATTRIBUTES);
}
-
+
/**
* Creates and returns a new classpath entry of kind <code>CPE_SOURCE</code>
- * for the project's source folder identified by the given absolute
+ * for the project's source folder identified by the given absolute
* workspace-relative path using the given inclusion and exclusion patterns
* to determine which source files are included, and the given output path
* to control the output location of generated files.
* <p>
* The source folder is referred to using an absolute path relative to the
- * workspace root, e.g. <code>/Project/src</code>. A project's source
+ * workspace root, e.g. <code>/Project/src</code>. A project's source
* folders are located with that project. That is, a source classpath
* entry specifying the path <code>/P1/src</code> is only usable for
* project <code>P1</code>.
@@ -3394,11 +4088,11 @@
* includes all relevent files in the resource tree rooted at the source
* entry's path. On the other hand, specifying one or more inclusion
* patterns means that all <b>and only</b> files matching at least one of
- * the specified patterns are to be included. If exclusion patterns are
+ * the specified patterns are to be included. If exclusion patterns are
* specified, the initial set of files is then reduced by eliminating files
* matched by at least one of the exclusion patterns. Inclusion and
* exclusion patterns look like relative file paths with wildcards and are
- * interpreted relative to the source entry's path. File patterns are
+ * interpreted relative to the source entry's path. File patterns are
* case-sensitive can contain '**', '*' or '?' wildcards (see
* {@link IClasspathEntry#getExclusionPatterns()} for the full description
* of their syntax and semantics). The resulting set of files are included
@@ -3406,24 +4100,24 @@
* the root will have children of type <code>ICompilationUnit</code>.
* </p>
* <p>
- * For example, if the source folder path is
+ * For example, if the source folder path is
* <code>/Project/src</code>, there are no inclusion filters, and the
- * exclusion pattern is
+ * exclusion pattern is
* <code>com/xyz/tests/**</code>, then source files
* like <code>/Project/src/com/xyz/Foo.java</code>
* and <code>/Project/src/com/xyz/utils/Bar.java</code> would be included,
* whereas <code>/Project/src/com/xyz/tests/T1.java</code>
* and <code>/Project/src/com/xyz/tests/quick/T2.java</code> would be
- * excluded.
+ * excluded.
* </p>
* <p>
- * Additionally, a source entry can be associated with a specific output location.
- * By doing so, the Java builder will ensure that the generated ".class" files will
- * be issued inside this output location, as opposed to be generated into the
- * project default output location (when output location is <code>null</code>).
+ * Additionally, a source entry can be associated with a specific output location.
+ * By doing so, the Java builder will ensure that the generated ".class" files will
+ * be issued inside this output location, as opposed to be generated into the
+ * project default output location (when output location is <code>null</code>).
* Note that multiple source entries may target the same output location.
- * The output location is referred to using an absolute path relative to the
- * workspace root, e.g. <code>"/Project/bin"</code>, it must be located inside
+ * The output location is referred to using an absolute path relative to the
+ * workspace root, e.g. <code>"/Project/bin"</code>, it must be located inside
* the same project as the source folder.
* </p>
* <p>
@@ -3470,7 +4164,7 @@
false,
null,
false, // no access rules to combine
- extraAttributes);
+ extraAttributes);
}
/**
@@ -3478,15 +4172,15 @@
* for the given path. This method is fully equivalent to calling
* {@link #newVariableEntry(IPath, IPath, IPath, IAccessRule[], IClasspathAttribute[], boolean)
* newVariableEntry(variablePath, variableSourceAttachmentPath, sourceAttachmentRootPath, new IAccessRule[0], new IClasspathAttribute[0], false)}.
- *
+ *
* @param variablePath the path of the binary archive; first segment is the
* name of a classpath variable
- * @param variableSourceAttachmentPath the path of the corresponding source archive,
+ * @param variableSourceAttachmentPath the path of the corresponding source archive,
* or <code>null</code> if none; if present, the first segment is the
* name of a classpath variable (not necessarily the same variable
* as the one that begins <code>variablePath</code>)
- * @param sourceAttachmentRootPath the location of the root within the source archive
- * or <code>null</code> if <code>archivePath</code> is also <code>null</code>
+ * @param sourceAttachmentRootPath the location of the root of the source files within the source archive
+ * or <code>null</code> if <code>variableSourceAttachmentPath</code> is also <code>null</code>
* @return a new library classpath entry
*/
public static IClasspathEntry newVariableEntry(
@@ -3502,15 +4196,15 @@
* for the given path. This method is fully equivalent to calling
* {@link #newVariableEntry(IPath, IPath, IPath, IAccessRule[], IClasspathAttribute[], boolean)
* newVariableEntry(variablePath, variableSourceAttachmentPath, sourceAttachmentRootPath, new IAccessRule[0], new IClasspathAttribute[0], isExported)}.
- *
+ *
* @param variablePath the path of the binary archive; first segment is the
* name of a classpath variable
- * @param variableSourceAttachmentPath the path of the corresponding source archive,
+ * @param variableSourceAttachmentPath the path of the corresponding source archive,
* or <code>null</code> if none; if present, the first segment is the
* name of a classpath variable (not necessarily the same variable
* as the one that begins <code>variablePath</code>)
- * @param variableSourceAttachmentRootPath the location of the root within the source archive
- * or <code>null</code> if <code>archivePath</code> is also <code>null</code>
+ * @param variableSourceAttachmentRootPath the location of the root of the source files within the source archive
+ * or <code>null</code> if <code>variableSourceAttachmentPath</code> is also <code>null</code>
* @param isExported indicates whether this entry is contributed to dependent
* projects in addition to the output location
* @return a new variable classpath entry
@@ -3532,7 +4226,7 @@
}
/**
- * Creates and returns a new non-exported classpath entry of kind <code>CPE_VARIABLE</code>
+ * Creates and returns a new classpath entry of kind <code>CPE_VARIABLE</code>
* for the given path. The first segment of the path is the name of a classpath variable.
* The trailing segments of the path will be appended to resolved variable path.
* <p>
@@ -3541,15 +4235,15 @@
* <p>
* It is possible to register an automatic initializer (<code>ClasspathVariableInitializer</code>),
* which will be invoked through the extension point "org.eclipse.jdt.core.classpathVariableInitializer".
- * After resolution, a classpath variable entry may either correspond to a project or a library entry. </li>
+ * After resolution, a classpath variable entry may either correspond to a project or a library entry.
* <p>
* e.g. Here are some examples of variable path usage<ul>
- * <li> "JDTCORE" where variable <code>JDTCORE</code> is
+ * <li> "JDTCORE" where variable <code>JDTCORE</code> is
* bound to "c:/jars/jdtcore.jar". The resolved classpath entry is denoting the library "c:\jars\jdtcore.jar"</li>
- * <li> "JDTCORE" where variable <code>JDTCORE</code> is
+ * <li> "JDTCORE" where variable <code>JDTCORE</code> is
* bound to "/Project_JDTCORE". The resolved classpath entry is denoting the project "/Project_JDTCORE"</li>
* <li> "PLUGINS/com.example/example.jar" where variable <code>PLUGINS</code>
- * is bound to "c:/eclipse/plugins". The resolved classpath entry is denoting the library "c:/eclipse/plugins/com.example/example.jar"</li>
+ * is bound to "c:/eclipse/plugins". The resolved classpath entry is denoting the library "c:\eclipse\plugins\com.example\example.jar"</li>
* </ul>
* <p>
* The access rules determine the set of accessible class files
@@ -3567,7 +4261,7 @@
* projects. If not exported, dependent projects will not see any of the classes from this entry.
* If exported, dependent projects will concatenate the accessible files patterns of this entry with the
* accessible files patterns of the projects, and they will concatenate the non accessible files patterns of this entry
- * with the non accessible files patterns of the project.
+ * with the non accessible files patterns of the project.
* </p>
* <p>
* Note that this operation does not attempt to validate classpath variables
@@ -3576,24 +4270,24 @@
*
* @param variablePath the path of the binary archive; first segment is the
* name of a classpath variable
- * @param variableSourceAttachmentPath the path of the corresponding source archive,
+ * @param variableSourceAttachmentPath the path of the corresponding source archive,
* or <code>null</code> if none; if present, the first segment is the
* name of a classpath variable (not necessarily the same variable
* as the one that begins <code>variablePath</code>)
- * @param variableSourceAttachmentRootPath the location of the root within the source archive
- * or <code>null</code> if <code>archivePath</code> is also <code>null</code>
+ * @param variableSourceAttachmentRootPath the location of the root of the source files within the source archive
+ * or <code>null</code> if <code>variableSourceAttachmentPath</code> is also <code>null</code>
* @param accessRules the possibly empty list of access rules for this entry
* @param extraAttributes the possibly empty list of extra attributes to persist with this entry
* @param isExported indicates whether this entry is contributed to dependent
* projects in addition to the output location
* @return a new variable classpath entry
* @since 3.1
- */
+ */
public static IClasspathEntry newVariableEntry(
IPath variablePath,
IPath variableSourceAttachmentPath,
IPath variableSourceAttachmentRootPath,
- IAccessRule[] accessRules,
+ IAccessRule[] accessRules,
IClasspathAttribute[] extraAttributes,
boolean isExported) {
@@ -3603,7 +4297,7 @@
false,
"Illegal classpath variable path: \'" + variablePath.makeRelative().toString() + "\', must have at least one segment"); //$NON-NLS-1$//$NON-NLS-2$
}
-
+
return new ClasspathEntry(
IPackageFragmentRoot.K_SOURCE,
IClasspathEntry.CPE_VARIABLE,
@@ -3611,27 +4305,27 @@
ClasspathEntry.INCLUDE_ALL, // inclusion patterns
ClasspathEntry.EXCLUDE_NONE, // exclusion patterns
variableSourceAttachmentPath, // source attachment
- variableSourceAttachmentRootPath, // source attachment root
+ variableSourceAttachmentRootPath, // source attachment root
null, // specific output folder
isExported,
accessRules,
false, // no access rules to combine
extraAttributes);
- }
+ }
/**
* Removed the given classpath variable. Does nothing if no value was
* set for this classpath variable.
* <p>
* This functionality cannot be used while the resource tree is locked.
* <p>
- * Classpath variable values are persisted locally to the workspace, and
+ * Classpath variable values are persisted locally to the workspace, and
* are preserved from session to session.
* <p>
*
* @param variableName the name of the classpath variable
* @see #setClasspathVariable(String, IPath)
*
- * @deprecated - use version with extra IProgressMonitor
+ * @deprecated Use {@link #removeClasspathVariable(String, IProgressMonitor)} instead
*/
public static void removeClasspathVariable(String variableName) {
removeClasspathVariable(variableName, null);
@@ -3643,7 +4337,7 @@
* <p>
* This functionality cannot be used while the resource tree is locked.
* <p>
- * Classpath variable values are persisted locally to the workspace, and
+ * Classpath variable values are persisted locally to the workspace, and
* are preserved from session to session.
* <p>
*
@@ -3651,14 +4345,12 @@
* @param monitor the progress monitor to report progress
* @see #setClasspathVariable(String, IPath)
*/
- public static void removeClasspathVariable(
- String variableName,
- IProgressMonitor monitor) {
-
+ public static void removeClasspathVariable(String variableName, IProgressMonitor monitor) {
try {
- JavaModelManager.getJavaModelManager().updateVariableValues(new String[]{ variableName}, new IPath[]{ null }, monitor);
+ SetVariablesOperation operation = new SetVariablesOperation(new String[]{ variableName}, new IPath[]{ null }, true/*update preferences*/);
+ operation.runOperation(monitor);
} catch (JavaModelException e) {
- // cannot happen: ignore
+ Util.log(e, "Exception while removing variable " + variableName); //$NON-NLS-1$
}
}
@@ -3673,6 +4365,19 @@
}
/**
+ * Removes the file extension from the given file name, if it has a Java-like file
+ * extension. Otherwise the file name itself is returned.
+ * Note this removes the dot ('.') before the extension as well.
+ *
+ * @param fileName the name of a file
+ * @return the fileName without the Java-like extension
+ * @since 3.2
+ */
+ public static String removeJavaLikeExtension(String fileName) {
+ return Util.getNameWithoutJavaLikeExtension(fileName);
+ }
+
+ /**
* Removes the given pre-processing resource changed listener.
* <p>
* Has no affect if an identical listener is not registered.
@@ -3683,9 +4388,9 @@
public static void removePreProcessingResourceChangedListener(IResourceChangeListener listener) {
JavaModelManager.getJavaModelManager().deltaState.removePreResourceChangedListener(listener);
}
-
-
+
+
/**
* Runs the given action as an atomic Java model operation.
* <p>
@@ -3740,7 +4445,7 @@
* </p>
* <p>
* The supplied scheduling rule is used to determine whether this operation can be
- * run simultaneously with workspace changes in other threads. See
+ * run simultaneously with workspace changes in other threads. See
* <code>IWorkspace.run(...)</code> for more details.
* </p>
*
@@ -3760,37 +4465,37 @@
// use IWorkspace.run(...) to ensure that a build will be done in autobuild mode
workspace.run(new BatchOperation(action), rule, IWorkspace.AVOID_UPDATE, monitor);
}
- }
- /**
+ }
+ /**
* Bind a container reference path to some actual containers (<code>IClasspathContainer</code>).
* This API must be invoked whenever changes in container need to be reflected onto the JavaModel.
* Containers can have distinct values in different projects, therefore this API considers a
* set of projects with their respective containers.
* <p>
* <code>containerPath</code> is the path under which these values can be referenced through
- * container classpath entries (<code>IClasspathEntry#CPE_CONTAINER</code>). A container path
+ * container classpath entries (<code>IClasspathEntry#CPE_CONTAINER</code>). A container path
* is formed by a first ID segment followed with extra segments, which can be used as additional hints
- * for the resolution. The container ID is used to identify a <code>ClasspathContainerInitializer</code>
+ * for the resolution. The container ID is used to identify a <code>ClasspathContainerInitializer</code>
* registered on the extension point "org.eclipse.jdt.core.classpathContainerInitializer".
* <p>
- * There is no assumption that each individual container value passed in argument
- * (<code>respectiveContainers</code>) must answer the exact same path when requested
- * <code>IClasspathContainer#getPath</code>.
- * Indeed, the containerPath is just an indication for resolving it to an actual container object. It can be
+ * There is no assumption that each individual container value passed in argument
+ * (<code>respectiveContainers</code>) must answer the exact same path when requested
+ * <code>IClasspathContainer#getPath</code>.
+ * Indeed, the containerPath is just an indication for resolving it to an actual container object. It can be
* delegated to a <code>ClasspathContainerInitializer</code>, which can be activated through the extension
- * point "org.eclipse.jdt.core.ClasspathContainerInitializer").
+ * point "org.eclipse.jdt.core.ClasspathContainerInitializer").
* <p>
* In reaction to changing container values, the JavaModel will be updated to reflect the new
- * state of the updated container. A combined Java element delta will be notified to describe the corresponding
+ * state of the updated container. A combined Java element delta will be notified to describe the corresponding
* classpath changes resulting from the container update. This operation is batched, and automatically eliminates
* unnecessary updates (new container is same as old one). This operation acquires a lock on the workspace's root.
* <p>
* This functionality cannot be used while the workspace is locked, since
* it may create/remove some resource markers.
* <p>
- * Classpath container values are persisted locally to the workspace, but
- * are not preserved from a session to another. It is thus highly recommended to register a
- * <code>ClasspathContainerInitializer</code> for each referenced container
+ * Classpath container values are persisted locally to the workspace, but
+ * are not preserved from a session to another. It is thus highly recommended to register a
+ * <code>ClasspathContainerInitializer</code> for each referenced container
* (through the extension point "org.eclipse.jdt.core.ClasspathContainerInitializer").
* <p>
* Note: setting a container to <code>null</code> will cause it to be lazily resolved again whenever
@@ -3807,182 +4512,11 @@
* @see IClasspathContainer
* @since 2.0
*/
- public static void setClasspathContainer(final IPath containerPath, IJavaProject[] affectedProjects, IClasspathContainer[] respectiveContainers, IProgressMonitor monitor) throws JavaModelException {
-
- if (affectedProjects.length != respectiveContainers.length) Assert.isTrue(false, "Projects and containers collections should have the same size"); //$NON-NLS-1$
-
- if (monitor != null && monitor.isCanceled()) return;
-
- if (JavaModelManager.CP_RESOLVE_VERBOSE){
- Util.verbose(
- "CPContainer SET - setting container\n" + //$NON-NLS-1$
- " container path: " + containerPath + '\n' + //$NON-NLS-1$
- " projects: {" +//$NON-NLS-1$
- org.eclipse.jdt.internal.compiler.util.Util.toString(
- affectedProjects,
- new org.eclipse.jdt.internal.compiler.util.Util.Displayable(){
- public String displayString(Object o) { return ((IJavaProject) o).getElementName(); }
- }) +
- "}\n values: {\n" +//$NON-NLS-1$
- org.eclipse.jdt.internal.compiler.util.Util.toString(
- respectiveContainers,
- new org.eclipse.jdt.internal.compiler.util.Util.Displayable(){
- public String displayString(Object o) {
- StringBuffer buffer = new StringBuffer(" "); //$NON-NLS-1$
- if (o == null) {
- buffer.append("<null>"); //$NON-NLS-1$
- return buffer.toString();
- }
- IClasspathContainer container = (IClasspathContainer) o;
- buffer.append(container.getDescription());
- buffer.append(" {\n"); //$NON-NLS-1$
- IClasspathEntry[] entries = container.getClasspathEntries();
- if (entries != null){
- for (int i = 0; i < entries.length; i++){
- buffer.append(" "); //$NON-NLS-1$
- buffer.append(entries[i]);
- buffer.append('\n');
- }
- }
- buffer.append(" }"); //$NON-NLS-1$
- return buffer.toString();
- }
- }) +
- "\n }\n invocation stack trace:"); //$NON-NLS-1$
- new Exception("<Fake exception>").printStackTrace(System.out); //$NON-NLS-1$
- }
-
- JavaModelManager manager = JavaModelManager.getJavaModelManager();
- if (manager.containerPutIfInitializingWithSameEntries(containerPath, affectedProjects, respectiveContainers))
- return;
-
- final int projectLength = affectedProjects.length;
- final IJavaProject[] modifiedProjects;
- System.arraycopy(affectedProjects, 0, modifiedProjects = new IJavaProject[projectLength], 0, projectLength);
- final IClasspathEntry[][] oldResolvedPaths = new IClasspathEntry[projectLength][];
-
- // filter out unmodified project containers
- int remaining = 0;
- for (int i = 0; i < projectLength; i++){
-
- if (monitor != null && monitor.isCanceled()) return;
-
- JavaProject affectedProject = (JavaProject) affectedProjects[i];
- IClasspathContainer newContainer = respectiveContainers[i];
- if (newContainer == null) newContainer = JavaModelManager.CONTAINER_INITIALIZATION_IN_PROGRESS; // 30920 - prevent infinite loop
- boolean found = false;
- if (JavaProject.hasJavaNature(affectedProject.getProject())){
- IClasspathEntry[] rawClasspath = affectedProject.getRawClasspath();
- for (int j = 0, cpLength = rawClasspath.length; j <cpLength; j++) {
- IClasspathEntry entry = rawClasspath[j];
- if (entry.getEntryKind() == IClasspathEntry.CPE_CONTAINER && entry.getPath().equals(containerPath)){
- found = true;
- break;
- }
- }
- }
- if (!found){
- modifiedProjects[i] = null; // filter out this project - does not reference the container path, or isnt't yet Java project
- manager.containerPut(affectedProject, containerPath, newContainer);
- continue;
- }
- IClasspathContainer oldContainer = manager.containerGet(affectedProject, containerPath);
- if (oldContainer == JavaModelManager.CONTAINER_INITIALIZATION_IN_PROGRESS) {
-// Map previousContainerValues = (Map)JavaModelManager.getJavaModelManager().previousSessionContainers.get(affectedProject);
-// if (previousContainerValues != null){
-// IClasspathContainer previousContainer = (IClasspathContainer)previousContainerValues.get(containerPath);
-// if (previousContainer != null) {
-// if (JavaModelManager.CP_RESOLVE_VERBOSE){
-// StringBuffer buffer = new StringBuffer();
-// buffer.append("CPContainer INIT - reentering access to project container during its initialization, will see previous value\n"); //$NON-NLS-1$
-// buffer.append(" project: " + affectedProject.getElementName() + '\n'); //$NON-NLS-1$
-// buffer.append(" container path: " + containerPath + '\n'); //$NON-NLS-1$
-// buffer.append(" previous value: "); //$NON-NLS-1$
-// buffer.append(previousContainer.getDescription());
-// buffer.append(" {\n"); //$NON-NLS-1$
-// IClasspathEntry[] entries = previousContainer.getClasspathEntries();
-// if (entries != null){
-// for (int j = 0; j < entries.length; j++){
-// buffer.append(" "); //$NON-NLS-1$
-// buffer.append(entries[j]);
-// buffer.append('\n');
-// }
-// }
-// buffer.append(" }"); //$NON-NLS-1$
-// Util.verbose(buffer.toString());
-// }
-// JavaModelManager.getJavaModelManager().containerPut(affectedProject, containerPath, previousContainer);
-// }
-// oldContainer = null; //33695 - cannot filter out restored container, must update affected project to reset cached CP
-// } else {
- oldContainer = null;
-// }
- }
- if (oldContainer != null && oldContainer.equals(respectiveContainers[i])){
- modifiedProjects[i] = null; // filter out this project - container did not change
- continue;
- }
- remaining++;
- oldResolvedPaths[i] = affectedProject.getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/);
- manager.containerPut(affectedProject, containerPath, newContainer);
- }
-
- if (remaining == 0) return;
-
- // trigger model refresh
- try {
- final boolean canChangeResources = !ResourcesPlugin.getWorkspace().isTreeLocked();
- JavaCore.run(new IWorkspaceRunnable() {
- public void run(IProgressMonitor progressMonitor) throws CoreException {
- for(int i = 0; i < projectLength; i++){
-
- if (progressMonitor != null && progressMonitor.isCanceled()) return;
-
- JavaProject affectedProject = (JavaProject)modifiedProjects[i];
- if (affectedProject == null) continue; // was filtered out
-
- if (JavaModelManager.CP_RESOLVE_VERBOSE){
- Util.verbose(
- "CPContainer SET - updating affected project due to setting container\n" + //$NON-NLS-1$
- " project: " + affectedProject.getElementName() + '\n' + //$NON-NLS-1$
- " container path: " + containerPath); //$NON-NLS-1$
- }
-
- // force a refresh of the affected project (will compute deltas)
- affectedProject.setRawClasspath(
- affectedProject.getRawClasspath(),
- SetClasspathOperation.DO_NOT_SET_OUTPUT,
- progressMonitor,
- canChangeResources,
- oldResolvedPaths[i],
- false, // updating - no need for early validation
- false); // updating - no need to save
- }
- }
- },
- null/*no need to lock anything*/,
- monitor);
- } catch(CoreException e) {
- if (JavaModelManager.CP_RESOLVE_VERBOSE){
- Util.verbose(
- "CPContainer SET - FAILED DUE TO EXCEPTION\n" + //$NON-NLS-1$
- " container path: " + containerPath, //$NON-NLS-1$
- System.err);
- e.printStackTrace();
- }
- if (e instanceof JavaModelException) {
- throw (JavaModelException)e;
- } else {
- throw new JavaModelException(e);
- }
- } finally {
- for (int i = 0; i < projectLength; i++) {
- if (respectiveContainers[i] == null) {
- manager.containerPut(affectedProjects[i], containerPath, null); // reset init in progress marker
- }
- }
- }
-
+ public static void setClasspathContainer(IPath containerPath, IJavaProject[] affectedProjects, IClasspathContainer[] respectiveContainers, IProgressMonitor monitor) throws JavaModelException {
+ if (affectedProjects.length != respectiveContainers.length)
+ Assert.isTrue(false, "Projects and containers collections should have the same size"); //$NON-NLS-1$
+ SetContainerOperation operation = new SetContainerOperation(containerPath, affectedProjects, respectiveContainers);
+ operation.runOperation(monitor);
}
/**
@@ -3991,7 +4525,7 @@
* <p>
* This functionality cannot be used while the resource tree is locked.
* <p>
- * Classpath variable values are persisted locally to the workspace, and
+ * Classpath variable values are persisted locally to the workspace, and
* are preserved from session to session.
* <p>
*
@@ -4000,7 +4534,7 @@
* @throws JavaModelException
* @see #getClasspathVariable(String)
*
- * @deprecated - use API with IProgressMonitor
+ * @deprecated Use {@link #setClasspathVariable(String, IPath, IProgressMonitor)} instead
*/
public static void setClasspathVariable(String variableName, IPath path)
throws JavaModelException {
@@ -4014,7 +4548,7 @@
* <p>
* This functionality cannot be used while the resource tree is locked.
* <p>
- * Classpath variable values are persisted locally to the workspace, and
+ * Classpath variable values are persisted locally to the workspace, and
* are preserved from session to session.
* <p>
* Updating a variable with the same value has no effect.
@@ -4039,19 +4573,19 @@
* Sets the values of all the given classpath variables at once.
* Null paths can be used to request corresponding variable removal.
* <p>
- * A combined Java element delta will be notified to describe the corresponding
- * classpath changes resulting from the variables update. This operation is batched,
- * and automatically eliminates unnecessary updates (new variable is same as old one).
+ * A combined Java element delta will be notified to describe the corresponding
+ * classpath changes resulting from the variables update. This operation is batched,
+ * and automatically eliminates unnecessary updates (new variable is same as old one).
* This operation acquires a lock on the workspace's root.
* <p>
* This functionality cannot be used while the workspace is locked, since
* it may create/remove some resource markers.
* <p>
- * Classpath variable values are persisted locally to the workspace, and
+ * Classpath variable values are persisted locally to the workspace, and
* are preserved from session to session.
* <p>
* Updating a variable with the same value has no effect.
- *
+ *
* @param variableNames an array of names for the updated classpath variables
* @param paths an array of path updates for the modified classpath variables (null
* meaning that the corresponding value will be removed
@@ -4067,19 +4601,87 @@
throws JavaModelException {
if (variableNames.length != paths.length) Assert.isTrue(false, "Variable names and paths collections should have the same size"); //$NON-NLS-1$
- JavaModelManager.getJavaModelManager().updateVariableValues(variableNames, paths, monitor);
+ SetVariablesOperation operation = new SetVariablesOperation(variableNames, paths, true/*update preferences*/);
+ operation.runOperation(monitor);
}
/**
- * Sets the current table of options. All and only the options explicitly included in the given table
- * are remembered; all previous option settings are forgotten, including ones not explicitly
- * mentioned.
+ * Sets the default's compiler options inside the given options map according
+ * to the given compliance.
+ *
+ * <p>The given compliance must be one of the compliance supported by the compiler.
+ * See {@link #getDefaultOptions()} for a list of compliance values.</p>
+ *
+ * <p>The list of modified options is:</p>
+ * <ul>
+ * <li>{@link #COMPILER_CODEGEN_TARGET_PLATFORM}</li>
+ * <li>{@link #COMPILER_SOURCE}</li>
+ * <li>{@link #COMPILER_COMPLIANCE}</li>
+ * <li>{@link #COMPILER_PB_ASSERT_IDENTIFIER}</li>
+ * <li>{@link #COMPILER_PB_ENUM_IDENTIFIER}</li>
+ * </ul>
+ *
+ * <p>If the given compliance is unknown, the given map is unmodified.</p>
+ *
+ * @param compliance the given compliance
+ * @param options the given options map
+ * @since 3.3
+ */
+ public static void setComplianceOptions(String compliance, Map options) {
+ switch((int) (CompilerOptions.versionToJdkLevel(compliance) >>> 16)) {
+ case ClassFileConstants.MAJOR_VERSION_1_3:
+ options.put(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_1_3);
+ options.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_3);
+ options.put(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_1_1);
+ options.put(JavaCore.COMPILER_PB_ASSERT_IDENTIFIER, JavaCore.IGNORE);
+ options.put(JavaCore.COMPILER_PB_ENUM_IDENTIFIER, JavaCore.IGNORE);
+ break;
+ case ClassFileConstants.MAJOR_VERSION_1_4:
+ options.put(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_1_4);
+ options.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_3);
+ options.put(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_1_2);
+ options.put(JavaCore.COMPILER_PB_ASSERT_IDENTIFIER, JavaCore.WARNING);
+ options.put(JavaCore.COMPILER_PB_ENUM_IDENTIFIER, JavaCore.WARNING);
+ break;
+ case ClassFileConstants.MAJOR_VERSION_1_5:
+ options.put(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_1_5);
+ options.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_5);
+ options.put(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_1_5);
+ options.put(JavaCore.COMPILER_PB_ASSERT_IDENTIFIER, JavaCore.ERROR);
+ options.put(JavaCore.COMPILER_PB_ENUM_IDENTIFIER, JavaCore.ERROR);
+ options.put(JavaCore.COMPILER_CODEGEN_INLINE_JSR_BYTECODE, JavaCore.ENABLED);
+ break;
+ case ClassFileConstants.MAJOR_VERSION_1_6:
+ options.put(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_1_6);
+ options.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_6);
+ options.put(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_1_6);
+ options.put(JavaCore.COMPILER_PB_ASSERT_IDENTIFIER, JavaCore.ERROR);
+ options.put(JavaCore.COMPILER_PB_ENUM_IDENTIFIER, JavaCore.ERROR);
+ options.put(JavaCore.COMPILER_CODEGEN_INLINE_JSR_BYTECODE, JavaCore.ENABLED);
+ break;
+ case ClassFileConstants.MAJOR_VERSION_1_7:
+ options.put(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_1_7);
+ options.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_7);
+ options.put(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_1_7);
+ options.put(JavaCore.COMPILER_PB_ASSERT_IDENTIFIER, JavaCore.ERROR);
+ options.put(JavaCore.COMPILER_PB_ENUM_IDENTIFIER, JavaCore.ERROR);
+ options.put(JavaCore.COMPILER_CODEGEN_INLINE_JSR_BYTECODE, JavaCore.ENABLED);
+ }
+ }
+
+ /**
+ * Sets the current table of options. All and only the options explicitly
+ * included in the given table are remembered; all previous option settings
+ * are forgotten, including ones not explicitly mentioned.
* <p>
- * For a complete description of the configurable options, see <code>getDefaultOptions</code>.
+ * For a complete description of the configurable options, see
+ * <code>getDefaultOptions</code>.
* </p>
- *
- * @param newOptions the new options (key type: <code>String</code>; value type: <code>String</code>),
- * or <code>null</code> to reset all options to their default values
+ *
+ * @param newOptions
+ * the new options (key type: <code>String</code>; value type:
+ * <code>String</code>), or <code>null</code> to reset all
+ * options to their default values
* @see JavaCore#getDefaultOptions()
* @see JavaCorePreferenceInitializer for changing default settings
*/
@@ -4116,4 +4718,4 @@
super.start(context);
JavaModelManager.getJavaModelManager().startup();
}
-}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaModelException.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaModelException.java
index 5e20900..ed7842c 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaModelException.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaModelException.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/NamingConventions.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/NamingConventions.java
index 19cac72..c4d42a9 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/NamingConventions.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/NamingConventions.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -12,6 +12,7 @@
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.codeassist.impl.AssistOptions;
+import org.eclipse.jdt.internal.compiler.parser.ScannerHelper;
import org.eclipse.jdt.internal.core.INamingRequestor;
import org.eclipse.jdt.internal.core.InternalNamingConventions;
@@ -23,14 +24,14 @@
* <p>
* The possible options are :
* <ul>
- * <li>CODEASSIST_FIELD_PREFIXES : Define the Prefixes for Field Name.</li>
- * <li>CODEASSIST_STATIC_FIELD_PREFIXES : Define the Prefixes for Static Field Name.</li>
- * <li>CODEASSIST_LOCAL_PREFIXES : Define the Prefixes for Local Variable Name.</li>
- * <li>CODEASSIST_ARGUMENT_PREFIXES : Define the Prefixes for Argument Name.</li>
- * <li>CODEASSIST_FIELD_SUFFIXES : Define the Suffixes for Field Name.</li>
- * <li>CODEASSIST_STATIC_FIELD_SUFFIXES : Define the Suffixes for Static Field Name.</li>
- * <li>CODEASSIST_LOCAL_SUFFIXES : Define the Suffixes for Local Variable Name.</li>
- * <li>CODEASSIST_ARGUMENT_SUFFIXES : Define the Suffixes for Argument Name.</li>
+ * <li> {@link JavaCore#CODEASSIST_FIELD_PREFIXES} : Define the Prefixes for Field Name.</li>
+ * <li> {@link JavaCore#CODEASSIST_STATIC_FIELD_PREFIXES} : Define the Prefixes for Static Field Name.</li>
+ * <li> {@link JavaCore#CODEASSIST_LOCAL_PREFIXES} : Define the Prefixes for Local Variable Name.</li>
+ * <li> {@link JavaCore#CODEASSIST_ARGUMENT_PREFIXES} : Define the Prefixes for Argument Name.</li>
+ * <li> {@link JavaCore#CODEASSIST_FIELD_SUFFIXES} : Define the Suffixes for Field Name.</li>
+ * <li> {@link JavaCore#CODEASSIST_STATIC_FIELD_SUFFIXES} : Define the Suffixes for Static Field Name.</li>
+ * <li> {@link JavaCore#CODEASSIST_LOCAL_SUFFIXES} : Define the Suffixes for Local Variable Name.</li>
+ * <li> {@link JavaCore#CODEASSIST_ARGUMENT_SUFFIXES} : Define the Suffixes for Argument Name.</li>
* </ul>
* </p>
* <p>
@@ -51,7 +52,7 @@
private static final char[] GETTER_NAME = "get".toCharArray(); //$NON-NLS-1$
private static final char[] SETTER_NAME = "set".toCharArray(); //$NON-NLS-1$
- private static class NamingRequestor implements INamingRequestor {
+ static class NamingRequestor implements INamingRequestor {
private final static int SIZE = 10;
// for acceptNameWithPrefixAndSuffix
@@ -79,7 +80,7 @@
// for acceptNameWithoutPrefixAndSuffix
private char[][] otherResults = new char[SIZE][];
private int otherResultsCount = 0;
- public void acceptNameWithPrefixAndSuffix(char[] name, boolean isFirstPrefix, boolean isFirstSuffix) {
+ public void acceptNameWithPrefixAndSuffix(char[] name, boolean isFirstPrefix, boolean isFirstSuffix, int reusedCharacters) {
if(isFirstPrefix && isFirstSuffix) {
int length = this.firstPrefixAndFirstSuffixResults.length;
if(length == this.firstPrefixAndFirstSuffixResultsCount) {
@@ -127,7 +128,7 @@
}
}
- public void acceptNameWithPrefix(char[] name, boolean isFirstPrefix) {
+ public void acceptNameWithPrefix(char[] name, boolean isFirstPrefix, int reusedCharacters) {
if(isFirstPrefix) {
int length = this.firstPrefixResults.length;
if(length == this.firstPrefixResultsCount) {
@@ -153,7 +154,7 @@
}
}
- public void acceptNameWithSuffix(char[] name, boolean isFirstSuffix) {
+ public void acceptNameWithSuffix(char[] name, boolean isFirstSuffix, int reusedCharacters) {
if(isFirstSuffix) {
int length = this.firstSuffixResults.length;
if(length == this.firstSuffixResultsCount) {
@@ -179,7 +180,7 @@
}
}
- public void acceptNameWithoutPrefixAndSuffix(char[] name) {
+ public void acceptNameWithoutPrefixAndSuffix(char[] name, int reusedCharacters) {
int length = this.otherResults.length;
if(length == this.otherResultsCount) {
System.arraycopy(
@@ -242,8 +243,8 @@
char[] prefix = prefixes[i];
if (CharOperation.prefixEquals(prefix, name)) {
int currLen = prefix.length;
- boolean lastCharIsLetter = Character.isLetter(prefix[currLen - 1]);
- if(!lastCharIsLetter || (lastCharIsLetter && name.length > currLen && Character.isUpperCase(name[currLen]))) {
+ boolean lastCharIsLetter = ScannerHelper.isLetter(prefix[currLen - 1]);
+ if(!lastCharIsLetter || (lastCharIsLetter && name.length > currLen && ScannerHelper.isUpperCase(name[currLen]))) {
if (bestLength < currLen && name.length != currLen) {
withoutPrefixName = CharOperation.subarray(name, currLen, name.length);
bestLength = currLen;
@@ -269,7 +270,7 @@
}
}
- withoutSuffixName[0] = Character.toLowerCase(withoutSuffixName[0]);
+ withoutSuffixName[0] = ScannerHelper.toLowerCase(withoutSuffixName[0]);
return withoutSuffixName;
}
@@ -282,8 +283,8 @@
* name <code>preArgsuf</code>.
* </p>
* <p>
- * This method is affected by the following JavaCore options : CODEASSIST_ARGUMENT_PREFIXES and
- * CODEASSIST_ARGUMENT_SUFFIXES.
+ * This method is affected by the following JavaCore options : {@link JavaCore#CODEASSIST_ARGUMENT_PREFIXES} and
+ * {@link JavaCore#CODEASSIST_ARGUMENT_SUFFIXES}.
* </p>
* <p>
* For a complete description of these configurable options, see <code>getDefaultOptions</code>.
@@ -313,8 +314,8 @@
* name <code>preArgsuf</code>.
* </p>
* <p>
- * This method is affected by the following JavaCore options : CODEASSIST_ARGUMENT_PREFIXES and
- * CODEASSIST_ARGUMENT_SUFFIXES.
+ * This method is affected by the following JavaCore options : {@link JavaCore#CODEASSIST_ARGUMENT_PREFIXES} and
+ * {@link JavaCore#CODEASSIST_ARGUMENT_SUFFIXES}.
* </p>
* <p>
* For a complete description of these configurable options, see <code>getDefaultOptions</code>.
@@ -340,9 +341,9 @@
* name <code>preFieldsuf</code>.
* </p>
* <p>
- * This method is affected by the following JavaCore options : CODEASSIST_FIELD_PREFIXES,
- * CODEASSIST_FIELD_SUFFIXES for instance field and CODEASSIST_STATIC_FIELD_PREFIXES,
- * CODEASSIST_STATIC_FIELD_SUFFIXES for static field.
+ * This method is affected by the following JavaCore options : {@link JavaCore#CODEASSIST_FIELD_PREFIXES} } ,
+ * {@link JavaCore#CODEASSIST_FIELD_SUFFIXES} for instance field and {@link JavaCore#CODEASSIST_STATIC_FIELD_PREFIXES},
+ * {@link JavaCore#CODEASSIST_STATIC_FIELD_SUFFIXES} for static field.
* </p>
* <p>
* For a complete description of these configurable options, see <code>getDefaultOptions</code>.
@@ -376,9 +377,9 @@
* name <code>preFieldsuf</code>.
* </p>
* <p>
- * This method is affected by the following JavaCore options : CODEASSIST_FIELD_PREFIXES,
- * CODEASSIST_FIELD_SUFFIXES for instance field and CODEASSIST_STATIC_FIELD_PREFIXES,
- * CODEASSIST_STATIC_FIELD_SUFFIXES for static field.
+ * This method is affected by the following JavaCore options : {@link JavaCore#CODEASSIST_FIELD_PREFIXES},
+ * {@link JavaCore#CODEASSIST_FIELD_SUFFIXES} for instance field and {@link JavaCore#CODEASSIST_STATIC_FIELD_PREFIXES},
+ * {@link JavaCore#CODEASSIST_STATIC_FIELD_SUFFIXES} for static field.
* </p>
* <p>
* For a complete description of these configurable options, see <code>getDefaultOptions</code>.
@@ -406,8 +407,8 @@
* name <code>preLocalsuf</code>.
* </p>
* <p>
- * This method is affected by the following JavaCore options : CODEASSIST_LOCAL_PREFIXES and
- * CODEASSIST_LOCAL_SUFFIXES.
+ * This method is affected by the following JavaCore options : {@link JavaCore#CODEASSIST_LOCAL_PREFIXES} and
+ * {@link JavaCore#CODEASSIST_LOCAL_SUFFIXES}.
* </p>
* <p>
* For a complete description of these configurable options, see <code>getDefaultOptions</code>.
@@ -437,8 +438,8 @@
* name <code>preLocalsuf</code>.
* </p>
* <p>
- * This method is affected by the following JavaCore options : CODEASSIST_LOCAL_PREFIXES and
- * CODEASSIST_LOCAL_SUFFIXES.
+ * This method is affected by the following JavaCore options : {@link JavaCore#CODEASSIST_LOCAL_PREFIXES} and
+ * {@link JavaCore#CODEASSIST_LOCAL_SUFFIXES}.
* </p>
* <p>
* For a complete description of these configurable options, see <code>getDefaultOptions</code>.
@@ -465,8 +466,8 @@
* and <code>name</code>.
* </p>
* <p>
- * This method is affected by the following JavaCore options : CODEASSIST_ARGUMENT_PREFIXES and
- * CODEASSIST_ARGUMENT_SUFFIXES.
+ * This method is affected by the following JavaCore options : {@link JavaCore#CODEASSIST_ARGUMENT_PREFIXES} and
+ * {@link JavaCore#CODEASSIST_ARGUMENT_SUFFIXES}.
* </p>
* <p>
* For a complete description of these configurable options, see <code>getDefaultOptions</code>.
@@ -490,6 +491,7 @@
packageName,
qualifiedTypeName,
dim,
+ null,
excludedNames,
requestor);
@@ -506,8 +508,8 @@
* and <code>name</code>.
* </p>
* <p>
- * This method is affected by the following JavaCore options : CODEASSIST_ARGUMENT_PREFIXES and
- * CODEASSIST_ARGUMENT_SUFFIXES.
+ * This method is affected by the following JavaCore options : {@link JavaCore#CODEASSIST_ARGUMENT_PREFIXES} and
+ * {@link JavaCore#CODEASSIST_ARGUMENT_SUFFIXES}.
* </p>
* <p>
* For a complete description of these configurable options, see <code>getDefaultOptions</code>.
@@ -543,9 +545,9 @@
* and <code>name</code>.
* </p>
* <p>
- * This method is affected by the following JavaCore options : CODEASSIST_FIELD_PREFIXES,
- * CODEASSIST_FIELD_SUFFIXES and for instance field and CODEASSIST_STATIC_FIELD_PREFIXES,
- * CODEASSIST_STATIC_FIELD_SUFFIXES for static field.
+ * This method is affected by the following JavaCore options : {@link JavaCore#CODEASSIST_FIELD_PREFIXES},
+ * {@link JavaCore#CODEASSIST_FIELD_SUFFIXES} and for instance field and {@link JavaCore#CODEASSIST_STATIC_FIELD_PREFIXES},
+ * {@link JavaCore#CODEASSIST_STATIC_FIELD_SUFFIXES} for static field.
* </p>
* <p>
* For a complete description of these configurable options, see <code>getDefaultOptions</code>.
@@ -573,6 +575,7 @@
qualifiedTypeName,
dim,
modifiers,
+ null,
excludedNames,
requestor);
@@ -589,9 +592,9 @@
* and <code>name</code>.
* </p>
* <p>
- * This method is affected by the following JavaCore options : CODEASSIST_FIELD_PREFIXES,
- * CODEASSIST_FIELD_SUFFIXES and for instance field and CODEASSIST_STATIC_FIELD_PREFIXES,
- * CODEASSIST_STATIC_FIELD_SUFFIXES for static field.
+ * This method is affected by the following JavaCore options : {@link JavaCore#CODEASSIST_FIELD_PREFIXES},
+ * {@link JavaCore#CODEASSIST_FIELD_SUFFIXES} and for instance field and {@link JavaCore#CODEASSIST_STATIC_FIELD_PREFIXES},
+ * {@link JavaCore#CODEASSIST_STATIC_FIELD_SUFFIXES} for static field.
* </p>
* <p>
* For a complete description of these configurable options, see <code>getDefaultOptions</code>.
@@ -632,8 +635,8 @@
* and <code>name</code>.
* </p>
* <p>
- * This method is affected by the following JavaCore options : CODEASSIST_LOCAL_PREFIXES and
- * CODEASSIST_LOCAL_SUFFIXES.
+ * This method is affected by the following JavaCore options : {@link JavaCore#CODEASSIST_LOCAL_PREFIXES} and
+ * {@link JavaCore#CODEASSIST_LOCAL_SUFFIXES}.
* </p>
* <p>
* For a complete description of these configurable options, see <code>getDefaultOptions</code>.
@@ -657,6 +660,7 @@
packageName,
qualifiedTypeName,
dim,
+ null,
excludedNames,
requestor);
@@ -673,8 +677,8 @@
* and <code>name</code>.
* </p>
* <p>
- * This method is affected by the following JavaCore options : CODEASSIST_LOCAL_PREFIXES and
- * CODEASSIST_LOCAL_SUFFIXES.
+ * This method is affected by the following JavaCore options : {@link JavaCore#CODEASSIST_LOCAL_PREFIXES} and
+ * {@link JavaCore#CODEASSIST_LOCAL_SUFFIXES}.
* </p>
* <p>
* For a complete description of these configurable options, see <code>getDefaultOptions</code>.
@@ -711,9 +715,9 @@
* for boolean field or <code>getPreFieldNamesuf</code> for others.
* </p>
* <p>
- * This method is affected by the following JavaCore options : CODEASSIST_FIELD_PREFIXES,
- * CODEASSIST_FIELD_SUFFIXES for instance field and CODEASSIST_STATIC_FIELD_PREFIXES,
- * CODEASSIST_STATIC_FIELD_SUFFIXES for static field.
+ * This method is affected by the following JavaCore options : {@link JavaCore#CODEASSIST_FIELD_PREFIXES},
+ * {@link JavaCore#CODEASSIST_FIELD_SUFFIXES} for instance field and {@link JavaCore#CODEASSIST_STATIC_FIELD_PREFIXES},
+ * {@link JavaCore#CODEASSIST_STATIC_FIELD_SUFFIXES} for static field.
* </p>
* <p>
* For a complete description of these configurable options, see <code>getDefaultOptions</code>.
@@ -737,7 +741,7 @@
char[] name = removePrefixAndSuffixForFieldName(project, fieldName, modifiers);
int prefixLen = GETTER_BOOL_NAME.length;
if (CharOperation.prefixEquals(GETTER_BOOL_NAME, name)
- && name.length > prefixLen && Character.isUpperCase(name[prefixLen])) {
+ && name.length > prefixLen && ScannerHelper.isUpperCase(name[prefixLen])) {
return suggestNewName(name, excludedNames);
} else {
return suggestNewName(
@@ -763,9 +767,9 @@
* for boolean field or <code>getPreFieldNamesuf</code> for others.
* </p>
* <p>
- * This method is affected by the following JavaCore options : CODEASSIST_FIELD_PREFIXES,
- * CODEASSIST_FIELD_SUFFIXES for instance field and CODEASSIST_STATIC_FIELD_PREFIXES,
- * CODEASSIST_STATIC_FIELD_SUFFIXES for static field.
+ * This method is affected by the following JavaCore options : {@link JavaCore#CODEASSIST_FIELD_PREFIXES},
+ * {@link JavaCore#CODEASSIST_FIELD_SUFFIXES} for instance field and {@link JavaCore#CODEASSIST_STATIC_FIELD_PREFIXES},
+ * {@link JavaCore#CODEASSIST_STATIC_FIELD_SUFFIXES} for static field.
* </p>
* <p>
* For a complete description of these configurable options, see <code>getDefaultOptions</code>.
@@ -803,9 +807,9 @@
* If there is no prefix and suffix the proposal is <code>setPreFieldNamesuf</code>.
* </p>
* <p>
- * This method is affected by the following JavaCore options : CODEASSIST_FIELD_PREFIXES,
- * CODEASSIST_FIELD_SUFFIXES for instance field and CODEASSIST_STATIC_FIELD_PREFIXES,
- * CODEASSIST_STATIC_FIELD_SUFFIXES for static field.
+ * This method is affected by the following JavaCore options : {@link JavaCore#CODEASSIST_FIELD_PREFIXES},
+ * {@link JavaCore#CODEASSIST_FIELD_SUFFIXES} for instance field and {@link JavaCore#CODEASSIST_STATIC_FIELD_PREFIXES},
+ * {@link JavaCore#CODEASSIST_STATIC_FIELD_SUFFIXES} for static field.
* </p>
* <p>
* For a complete description of these configurable options, see <code>getDefaultOptions</code>.
@@ -830,7 +834,7 @@
char[] name = removePrefixAndSuffixForFieldName(project, fieldName, modifiers);
int prefixLen = GETTER_BOOL_NAME.length;
if (CharOperation.prefixEquals(GETTER_BOOL_NAME, name)
- && name.length > prefixLen && Character.isUpperCase(name[prefixLen])) {
+ && name.length > prefixLen && ScannerHelper.isUpperCase(name[prefixLen])) {
name = CharOperation.subarray(name, prefixLen, name.length);
return suggestNewName(
CharOperation.concat(SETTER_NAME, suggestAccessorName(project, name, modifiers)),
@@ -859,9 +863,9 @@
* If there is no prefix and suffix the proposal is <code>setPreFieldNamesuf</code>.
* </p>
* <p>
- * This method is affected by the following JavaCore options : CODEASSIST_FIELD_PREFIXES,
- * CODEASSIST_FIELD_SUFFIXES for instance field and CODEASSIST_STATIC_FIELD_PREFIXES,
- * CODEASSIST_STATIC_FIELD_SUFFIXES for static field.
+ * This method is affected by the following JavaCore options : {@link JavaCore#CODEASSIST_FIELD_PREFIXES},
+ * {@link JavaCore#CODEASSIST_FIELD_SUFFIXES} for instance field and {@link JavaCore#CODEASSIST_STATIC_FIELD_PREFIXES},
+ * {@link JavaCore#CODEASSIST_STATIC_FIELD_SUFFIXES} for static field.
* </p>
* <p>
* For a complete description of these configurable options, see <code>getDefaultOptions</code>.
@@ -892,8 +896,8 @@
private static char[] suggestAccessorName(IJavaProject project, char[] fieldName, int modifiers) {
char[] name = removePrefixAndSuffixForFieldName(project, fieldName, modifiers);
- if (name.length > 0 && Character.isLowerCase(name[0])) {
- name[0] = Character.toUpperCase(name[0]);
+ if (name.length > 0 && ScannerHelper.isLowerCase(name[0])) {
+ name[0] = ScannerHelper.toUpperCase(name[0]);
}
return name;
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/Signature.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/Signature.java
index b2fac6f..680eab7 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/Signature.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/Signature.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -14,14 +14,16 @@
import java.util.ArrayList;
import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.parser.ScannerHelper;
import org.eclipse.jdt.internal.core.util.Util;
/**
* Provides methods for encoding and decoding type and method signature strings.
* <p>
- * Signatures obtained from parsing source (".java") files differ subtly from
- * ones obtained from pre-compiled binary (".class") files in class names are
+ * Signatures obtained from parsing source files (i.e. files with one of the
+ * {@link JavaCore#getJavaLikeExtensions() Java-like extensions}) differ subtly
+ * from ones obtained from pre-compiled binary (".class") files in class names are
* usually left unresolved in the former. For example, the normal resolved form
* of the type "String" embeds the class's package name ("Ljava.lang.String;"
* or "Ljava/lang/String;"), whereas the unresolved form contains only what is
@@ -30,10 +32,10 @@
* <p>
* Generic types introduce to the Java language in J2SE 1.5 add three new
* facets to signatures: type variables, parameterized types with type arguments,
- * and formal type parameters. <it>Rich</it> signatures containing these facets
+ * and formal type parameters. <i>Rich</i> signatures containing these facets
* only occur when dealing with code that makes overt use of the new language
* features. All other code, and certainly all Java code written or compiled
- * with J2SE 1.4 or earlier, involved only <it>simple</it> signatures.
+ * with J2SE 1.4 or earlier, involved only <i>simple</i> signatures.
* </p>
* <p>
* Note that the "Q" and "!" formats are specific to Eclipse; the remainder
@@ -61,10 +63,14 @@
* ResolvedClassTypeSignature ::= // resolved named type (in compiled code)
* "L" + Identifier + OptionalTypeArguments
* ( ( "." | "/" ) + Identifier + OptionalTypeArguments )* + ";"
+ * | OptionalTypeParameters + "L" + Identifier +
+ * ( ( "." | "/" ) + Identifier )* + ";"
*
* UnresolvedClassTypeSignature ::= // unresolved named type (in source code)
* "Q" + Identifier + OptionalTypeArguments
* ( ( "." | "/" ) + Identifier + OptionalTypeArguments )* + ";"
+ * | OptionalTypeParameters "Q" + Identifier +
+ * ( ( "." | "/" ) + Identifier )* + ";"
*
* OptionalTypeArguments ::=
* "<" + TypeArgument+ + ">"
@@ -75,6 +81,10 @@
* | "*" // wildcard ?
* | "+" TypeSignature // wildcard ? extends X
* | "-" TypeSignature // wildcard ? super X
+ *
+ * OptionalTypeParameters ::=
+ * "<" + FormalTypeParameterSignature+ + ">"
+ * |
* </pre>
* </p>
* <p>
@@ -85,14 +95,15 @@
* <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>
- * <li><code>"QMap<QString;*>;"</code> denotes <code>Map<String,?></code> in source code</li>
+ * <li><code>"QMap<QString;*>;"</code> denotes <code>Map<String,?></code> in source code</li>
* <li><code>"Qjava.util.List<TV;>;"</code> denotes <code>java.util.List<V></code> in source code</li>
+ * <li><code>"<E;>Ljava.util.List;"</code> denotes <code><E>java.util.List</code> in source code</li>
* </ul>
* </p>
* <p>
* The syntax for a method signature is:
* <pre>
- * MethodSignature ::= "(" + ParamTypeSignature* + ")" + ReturnTypeSignature
+ * MethodSignature ::= OptionalTypeParameters + "(" + ParamTypeSignature* + ")" + ReturnTypeSignature
* ParamTypeSignature ::= TypeSignature
* ReturnTypeSignature ::= TypeSignature
* </pre>
@@ -208,7 +219,7 @@
/**
* Character constant indicating an unbound wildcard type argument
* in a signature.
- * Value is <code>'*'</code>.
+ * Value is <code>'*'</code>.
* @since 3.0
*/
public static final char C_STAR = '*';
@@ -300,7 +311,7 @@
/**
* Character constant indicating a capture of a wildcard type in a
- * signature.Value is <code>'!'</code>.
+ * signature. Value is <code>'!'</code>.
* @since 3.1
*/
public static final char C_CAPTURE = '!';
@@ -413,8 +424,6 @@
private static final char[] EXTENDS = "extends".toCharArray(); //$NON-NLS-1$
private static final char[] SUPER = "super".toCharArray(); //$NON-NLS-1$
private static final char[] CAPTURE = "capture-of".toCharArray(); //$NON-NLS-1$
-
- private static final String EMPTY = new String(CharOperation.NO_CHAR);
private Signature() {
// Not instantiable
@@ -434,7 +443,7 @@
case ',' :
return pos;
default:
- if (Character.isWhitespace(currentChar))
+ if (ScannerHelper.isWhitespace(currentChar))
return pos;
}
@@ -652,7 +661,7 @@
count++;
break;
default:
- if (currentChar == ' ' || Character.isWhitespace(currentChar)) {
+ if (currentChar == ' ' || ScannerHelper.isWhitespace(currentChar)) {
if (lastAppendedChar == C_DOT) { // allow spaces after a dot
pos = consumeWhitespace(typeName, pos, length) - 1; // will be incremented
break;
@@ -1409,7 +1418,7 @@
if (i < 0 || i >= length)
throw new IllegalArgumentException();
// iterate over bounds
- nextBound: while (methodOrTypeSignature[i] == ':') {
+ while (methodOrTypeSignature[i] == ':') {
i++; // skip colon
switch (methodOrTypeSignature[i]) {
case ':':
@@ -1597,9 +1606,9 @@
* For example:
* <pre>
* <code>
- * getQualifier("java.lang.Object") -> "java.lang"
- * getQualifier("Outer.Inner") -> "Outer"
- * getQualifier("java.util.List<java.lang.String>") -> "java.util"
+ * getQualifier("java.lang.Object") -> "java.lang"
+ * getQualifier("Outer.Inner") -> "Outer"
+ * getQualifier("java.util.List<java.lang.String>") -> "java.util"
* </code>
* </pre>
* </p>
@@ -1611,7 +1620,7 @@
*/
public static String getQualifier(String name) {
char[] qualifier = getQualifier(name.toCharArray());
- if (qualifier.length == 0) return EMPTY;
+ if (qualifier.length == 0) return org.eclipse.jdt.internal.compiler.util.Util.EMPTY_STRING;
return new String(qualifier);
}
/**
@@ -1840,10 +1849,10 @@
* For example:
* <pre>
* <code>
- * getSimpleName("java.lang.Object") -> "Object"
+ * getSimpleName("java.lang.Object") -> "Object"
* </code>
* <code>
- * getSimpleName("java.util.Map<java.lang.String, java.lang.Object>") -> "Map<String,Object>"
+ * getSimpleName("java.util.Map<java.lang.String, java.lang.Object>") -> "Map<String,Object>"
* </code>
* </pre>
* </p>
@@ -1918,6 +1927,10 @@
case '.':
if (depth == 0) {
lastDot = i;
+ char c = name[start];
+ if (c == C_EXTENDS || c == C_SUPER) {
+ buffer.append(c);
+ }
break lastDotLookup;
}
break;
@@ -2034,10 +2047,11 @@
* For example:
* <pre>
* <code>
- * getSimpleNames("java.lang.Object") -> {"java", "lang", "Object"}
- * getSimpleNames("Object") -> {"Object"}
- * getSimpleNames("") -> {}
- * getSimpleNames("java.util.List<java.lang.String>") -> {"java", "lang", "List<java.lang.String"}
+ * getSimpleNames("java.lang.Object") -> {"java", "lang", "Object"}
+ * getSimpleNames("Object") -> {"Object"}
+ * getSimpleNames("") -> {}
+ * getSimpleNames("java.util.List<java.lang.String>") ->
+ * {"java", "util", "List<java.lang.String>"}
* </code>
* </pre>
*
@@ -2058,8 +2072,8 @@
* For example (using equivalent string-based method):
* <pre>
* <code>
- * removeCapture("LTest<!+Ljava.lang.Throwable;>;")
- * will return: "LTest<+Ljava.lang.Throwable;>;"
+ * removeCapture("LTest<!+Ljava.lang.Throwable;>;")
+ * will return: "LTest<+Ljava.lang.Throwable;>;"
* </code>
* </pre>
* </p>
@@ -2072,25 +2086,7 @@
* @since 3.1
*/
public static char[] removeCapture(char[] methodOrTypeSignature) {
-
-// TODO (frederic) Create remove(char[], char) method on CharOperation and call it from here
- char[] result = null;
- int count = 0;
- for (int i = 0, length = methodOrTypeSignature.length; i < length; i++) {
- char c = methodOrTypeSignature[i];
- if (c == C_CAPTURE) {
- if (result == null) {
- result = new char[length];
- System.arraycopy(methodOrTypeSignature, 0, result, 0, i);
- count = i;
- }
- } else if (result != null) {
- result[count++] = c;
- }
- }
- if (result == null) return methodOrTypeSignature;
- System.arraycopy(result, 0, result = new char[count], 0, count);
- return result;
+ return CharOperation.remove(methodOrTypeSignature, C_CAPTURE);
}
/**
@@ -2102,8 +2098,8 @@
* For example:
* <pre>
* <code>
- * removeCapture("LTest<!+Ljava.lang.Throwable;>;")
- * will return: "LTest<+Ljava.lang.Throwable;>;"
+ * removeCapture("LTest<!+Ljava.lang.Throwable;>;")
+ * will return: "LTest<+Ljava.lang.Throwable;>;"
* </code>
* </pre>
* </p>
@@ -2411,7 +2407,7 @@
throw new IllegalArgumentException();
}
char c = string[start];
- if (c != C_CAPTURE) { //$NON-NLS-1$
+ if (c != C_CAPTURE) {
throw new IllegalArgumentException();
}
buffer.append(CAPTURE).append(' ');
@@ -2440,7 +2436,7 @@
throw new IllegalArgumentException();
}
char c = string[start];
- if (c != C_ARRAY) { //$NON-NLS-1$
+ if (c != C_ARRAY) {
throw new IllegalArgumentException();
}
@@ -2499,6 +2495,8 @@
}
int p = start + 1;
int checkpoint = buffer.length();
+ int innerTypeStart = -1;
+ boolean inAnonymousType = false;
while (true) {
if (p >= string.length) {
throw new IllegalArgumentException();
@@ -2531,6 +2529,8 @@
}
break;
case C_DOLLAR :
+ innerTypeStart = buffer.length();
+ inAnonymousType = false;
if (resolved) {
// once we hit "$" there are no more package prefixes
removePackageQualifiers = false;
@@ -2544,7 +2544,15 @@
}
break;
default :
- buffer.append(c);
+ if (innerTypeStart != -1 && !inAnonymousType && Character.isDigit(c)) {
+ inAnonymousType = true;
+ buffer.setLength(innerTypeStart); // remove '.'
+ buffer.insert(checkpoint, "new "); //$NON-NLS-1$
+ buffer.append("(){}"); //$NON-NLS-1$
+ }
+ if (!inAnonymousType)
+ buffer.append(c);
+ innerTypeStart = -1;
}
p++;
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ToolFactory.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ToolFactory.java
index 0416797..d8db37b 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ToolFactory.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ToolFactory.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -12,14 +12,17 @@
import java.io.File;
import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
+import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.*;
-import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.compiler.IScanner;
import org.eclipse.jdt.core.formatter.CodeFormatter;
+import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
import org.eclipse.jdt.core.util.ClassFileBytesDisassembler;
import org.eclipse.jdt.core.util.ClassFormatException;
import org.eclipse.jdt.core.util.IClassFileReader;
@@ -44,6 +47,33 @@
* @since 2.0
*/
public class ToolFactory {
+
+ /**
+ * This mode is used for formatting new code when some formatter options should not be used.
+ * In particular, options that preserve the indentation of comments are not used.
+ * In the future, newly added options may be ignored as well.
+ * <p>Clients that are formatting new code are recommended to use this mode.
+ * </p>
+ *
+ * @see DefaultCodeFormatterConstants#FORMATTER_NEVER_INDENT_BLOCK_COMMENTS_ON_FIRST_COLUMN
+ * @see DefaultCodeFormatterConstants#FORMATTER_NEVER_INDENT_LINE_COMMENTS_ON_FIRST_COLUMN
+ * @see #createCodeFormatter(Map, int)
+ * @since 3.3
+ */
+ public static final int M_FORMAT_NEW = new Integer(0).intValue();
+
+ /**
+ * This mode is used for formatting existing code when all formatter options should be used.
+ * In particular, options that preserve the indentation of comments are used.
+ * <p>Clients that are formatting existing code are recommended to use this mode.
+ * </p>
+ *
+ * @see DefaultCodeFormatterConstants#FORMATTER_NEVER_INDENT_BLOCK_COMMENTS_ON_FIRST_COLUMN
+ * @see DefaultCodeFormatterConstants#FORMATTER_NEVER_INDENT_LINE_COMMENTS_ON_FIRST_COLUMN
+ * @see #createCodeFormatter(Map, int)
+ * @since 3.3
+ */
+ public static final int M_FORMAT_EXISTING = new Integer(1).intValue();
/**
* Create an instance of a code formatter. A code formatter implementation can be contributed via the
@@ -53,7 +83,7 @@
* @return an instance of a code formatter
* @see ICodeFormatter
* @see ToolFactory#createDefaultCodeFormatter(Map)
- * @deprecated - should use #createCodeFormatter(Map) instead. Extension point is discontinued
+ * @deprecated Use {@link #createCodeFormatter(Map)} instead. Extension point is discontinued
*/
public static ICodeFormatter createCodeFormatter(){
@@ -83,7 +113,15 @@
}
/**
- * Create an instance of the built-in code formatter.
+ * Create an instance of the built-in code formatter.
+ * <p>The given options should at least provide the source level ({@link JavaCore#COMPILER_SOURCE}),
+ * the compiler compliance level ({@link JavaCore#COMPILER_COMPLIANCE}) and the target platform
+ * ({@link JavaCore#COMPILER_CODEGEN_TARGET_PLATFORM}).
+ * Without these options, it is not possible for the code formatter to know what kind of source it needs to format.
+ * </p><p>
+ * Note this is equivalent to <code>createCodeFormatter(options, M_FORMAT_NEW)</code>. Thus some code formatter options
+ * may be ignored. See @{link {@link #M_FORMAT_NEW} for more details.
+ * </p>
* @param options - the options map to use for formatting with the default code formatter. Recognized options
* are documented on <code>JavaCore#getDefaultOptions()</code>. If set to <code>null</code>, then use
* the current settings from <code>JavaCore#getOptions</code>.
@@ -93,43 +131,41 @@
* @since 3.0
*/
public static CodeFormatter createCodeFormatter(Map options){
- if (options == null) options = JavaCore.getOptions();
- return new DefaultCodeFormatter(options);
+ return createCodeFormatter(options, M_FORMAT_NEW);
}
/**
- * Create an instance of the built-in code formatter. A code formatter implementation can be contributed via the
- * extension point "org.eclipse.jdt.core.codeFormatter". If unable to find a registered extension, the factory will
- * default to using the default code formatter.
+ * Create an instance of the built-in code formatter.
+ * <p>The given options should at least provide the source level ({@link JavaCore#COMPILER_SOURCE}),
+ * the compiler compliance level ({@link JavaCore#COMPILER_COMPLIANCE}) and the target platform
+ * ({@link JavaCore#COMPILER_CODEGEN_TARGET_PLATFORM}).
+ * Without these options, it is not possible for the code formatter to know what kind of source it needs to format.
+ * </p>
+ * <p>The given mode determines what options should be enabled when formatting the code. It can have the following
+ * values: {@link #M_FORMAT_NEW}, {@link #M_FORMAT_EXISTING}, but other values may be added in the future.
+ * </p>
*
- * @param options - the options map to use for formatting with the default code formatter. Recognized options
+ * @param options the options map to use for formatting with the default code formatter. Recognized options
* are documented on <code>JavaCore#getDefaultOptions()</code>. If set to <code>null</code>, then use
* the current settings from <code>JavaCore#getOptions</code>.
+ * @param mode the given mode to modify the given options.
+ *
* @return an instance of the built-in code formatter
- * @see ICodeFormatter
- * @see ToolFactory#createCodeFormatter()
+ * @see CodeFormatter
* @see JavaCore#getOptions()
- * @deprecated - use #createCodeFormatter(Map) instead
+ * @since 3.3
*/
- public static ICodeFormatter createDefaultCodeFormatter(Map options){
+ public static CodeFormatter createCodeFormatter(Map options, int mode) {
if (options == null) options = JavaCore.getOptions();
- return new org.eclipse.jdt.internal.formatter.old.CodeFormatter(options);
- }
-
- /**
- * Create a classfile bytecode disassembler, able to produce a String representation of a given classfile.
- *
- * @return a classfile bytecode disassembler
- * @see org.eclipse.jdt.core.util.IClassFileDisassembler
- * @deprecated - should use factory method creating ClassFileBytesDisassembler instead
- */
- public static org.eclipse.jdt.core.util.IClassFileDisassembler createDefaultClassFileDisassembler(){
- class DeprecatedDisassembler extends Disassembler implements org.eclipse.jdt.core.util.IClassFileDisassembler {
- // for backward compatibility, defines a disassembler which implements IClassFileDisassembler
+ Map currentOptions = new HashMap(options);
+ if (mode == M_FORMAT_NEW) {
+ // disable the option for not indenting comments starting on first column
+ currentOptions.put(DefaultCodeFormatterConstants.FORMATTER_NEVER_INDENT_BLOCK_COMMENTS_ON_FIRST_COLUMN, DefaultCodeFormatterConstants.FALSE);
+ currentOptions.put(DefaultCodeFormatterConstants.FORMATTER_NEVER_INDENT_LINE_COMMENTS_ON_FIRST_COLUMN, DefaultCodeFormatterConstants.FALSE);
}
- return new DeprecatedDisassembler();
+ return new DefaultCodeFormatter(currentOptions);
}
-
+
/**
* Create a classfile bytecode disassembler, able to produce a String representation of a given classfile.
*
@@ -140,30 +176,20 @@
public static ClassFileBytesDisassembler createDefaultClassFileBytesDisassembler(){
return new Disassembler();
}
-
+
/**
- * Create a default classfile reader, able to expose the internal representation of a given classfile
- * according to the decoding flag used to initialize the reader.
- * Answer null if the file named fileName doesn't represent a valid .class file.
- * The fileName has to be an absolute OS path to the given .class file.
+ * Create a classfile bytecode disassembler, able to produce a String representation of a given classfile.
*
- * The decoding flags are described in IClassFileReader.
- *
- * @param fileName the name of the file to be read
- * @param decodingFlag the flag used to decode the class file reader.
- * @return a default classfile reader
- *
- * @see IClassFileReader
+ * @return a classfile bytecode disassembler
+ * @see org.eclipse.jdt.core.util.IClassFileDisassembler
+ * @deprecated Use {@link #createDefaultClassFileBytesDisassembler()} instead
*/
- public static IClassFileReader createDefaultClassFileReader(String fileName, int decodingFlag){
- try {
- return new ClassFileReader(Util.getFileByteContent(new File(fileName)), decodingFlag);
- } catch(ClassFormatException e) {
- return null;
- } catch(IOException e) {
- return null;
+ public static org.eclipse.jdt.core.util.IClassFileDisassembler createDefaultClassFileDisassembler(){
+ class DeprecatedDisassembler extends Disassembler implements org.eclipse.jdt.core.util.IClassFileDisassembler {
+ // for backward compatibility, defines a disassembler which implements IClassFileDisassembler
}
- }
+ return new DeprecatedDisassembler();
+ }
/**
* Create a classfile reader onto a classfile Java element.
@@ -198,9 +224,18 @@
String entryName = org.eclipse.jdt.internal.core.util.Util.concatWith(packageFragment.names, classFileName, '/');
return createDefaultClassFileReader(archiveName, entryName, decodingFlag);
} else {
- IPath location = classfile.getResource().getLocation();
- if (location == null) return null;
- return createDefaultClassFileReader(location.toOSString(), decodingFlag);
+ InputStream in = null;
+ try {
+ in = ((IFile) classfile.getResource()).getContents();
+ return createDefaultClassFileReader(in, decodingFlag);
+ } finally {
+ if (in != null)
+ try {
+ in.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
}
} catch(CoreException e){
// unable to read
@@ -212,6 +247,54 @@
/**
* Create a default classfile reader, able to expose the internal representation of a given classfile
* according to the decoding flag used to initialize the reader.
+ * Answer null if the input stream contents cannot be retrieved
+ *
+ * The decoding flags are described in IClassFileReader.
+ *
+ * @param stream the given input stream to read
+ * @param decodingFlag the flag used to decode the class file reader.
+ * @return a default classfile reader
+ *
+ * @see IClassFileReader
+ * @since 3.2
+ */
+ public static IClassFileReader createDefaultClassFileReader(InputStream stream, int decodingFlag) {
+ try {
+ return new ClassFileReader(Util.getInputStreamAsByteArray(stream, -1), decodingFlag);
+ } catch(ClassFormatException e) {
+ return null;
+ } catch(IOException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Create a default classfile reader, able to expose the internal representation of a given classfile
+ * according to the decoding flag used to initialize the reader.
+ * Answer null if the file named fileName doesn't represent a valid .class file.
+ * The fileName has to be an absolute OS path to the given .class file.
+ *
+ * The decoding flags are described in IClassFileReader.
+ *
+ * @param fileName the name of the file to be read
+ * @param decodingFlag the flag used to decode the class file reader.
+ * @return a default classfile reader
+ *
+ * @see IClassFileReader
+ */
+ public static IClassFileReader createDefaultClassFileReader(String fileName, int decodingFlag){
+ try {
+ return new ClassFileReader(Util.getFileByteContent(new File(fileName)), decodingFlag);
+ } catch(ClassFormatException e) {
+ return null;
+ } catch(IOException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Create a default classfile reader, able to expose the internal representation of a given classfile
+ * according to the decoding flag used to initialize the reader.
* Answer null if the file named zipFileName doesn't represent a valid zip file or if the zipEntryName
* is not a valid entry name for the specified zip file or if the bytes don't represent a valid
* .class file according to the JVM specifications.
@@ -253,7 +336,26 @@
}
}
}
- }
+ }
+
+ /**
+ * Create an instance of the built-in code formatter. A code formatter implementation can be contributed via the
+ * extension point "org.eclipse.jdt.core.codeFormatter". If unable to find a registered extension, the factory will
+ * default to using the default code formatter.
+ *
+ * @param options - the options map to use for formatting with the default code formatter. Recognized options
+ * are documented on <code>JavaCore#getDefaultOptions()</code>. If set to <code>null</code>, then use
+ * the current settings from <code>JavaCore#getOptions</code>.
+ * @return an instance of the built-in code formatter
+ * @see ICodeFormatter
+ * @see ToolFactory#createCodeFormatter()
+ * @see JavaCore#getOptions()
+ * @deprecated Use {@link #createCodeFormatter(Map)} instead
+ */
+ public static ICodeFormatter createDefaultCodeFormatter(Map options){
+ if (options == null) options = JavaCore.getOptions();
+ return new org.eclipse.jdt.internal.formatter.old.CodeFormatter(options);
+ }
/**
* Create a scanner, indicating the level of detail requested for tokenizing. The scanner can then be
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/WorkingCopyOwner.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/WorkingCopyOwner.java
index 24e5ece..e9ac262 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/WorkingCopyOwner.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/WorkingCopyOwner.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,61 +10,182 @@
*******************************************************************************/
package org.eclipse.jdt.core;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.internal.core.BufferManager;
+import org.eclipse.jdt.internal.core.CompilationUnit;
import org.eclipse.jdt.internal.core.DefaultWorkingCopyOwner;
+import org.eclipse.jdt.internal.core.ExternalJavaProject;
+import org.eclipse.jdt.internal.core.PackageFragment;
/**
- * The owner of an <code>ICompilationUnit</code> handle in working copy mode.
+ * The owner of an {@link ICompilationUnit} handle in working copy mode.
* An owner is used to identify a working copy and to create its buffer.
* <p>
* Clients should subclass this class to instantiate a working copy owner that is specific to their need and that
- * they can pass in to various APIs (e.g. <code>IType.resolveType(String, WorkingCopyOwner)</code>.
- * Clients can also override the default implementation of <code>createBuffer(ICompilationUnit)</code>.
+ * they can pass in to various APIs (e.g. {@link IType#resolveType(String, WorkingCopyOwner)}.
+ * Clients can also override the default implementation of {@link #createBuffer(ICompilationUnit)}.
* </p><p>
* Note: even though this class has no abstract method, which means that it provides functional default behavior,
* it is still an abstract class, as clients are intended to own their owner implementation.
* </p>
- * @see ICompilationUnit#becomeWorkingCopy(IProblemRequestor, org.eclipse.core.runtime.IProgressMonitor)
+ * @see ICompilationUnit#becomeWorkingCopy(org.eclipse.core.runtime.IProgressMonitor)
* @see ICompilationUnit#discardWorkingCopy()
* @see ICompilationUnit#getWorkingCopy(org.eclipse.core.runtime.IProgressMonitor)
* @since 3.0
*/
public abstract class WorkingCopyOwner {
-
+
/**
* Sets the buffer provider of the primary working copy owner. Note that even if the
* buffer provider is a working copy owner, only its <code>createBuffer(ICompilationUnit)</code>
- * method is used by the primary working copy owner. It doesn't replace the internal primary
+ * method is used by the primary working copy owner. It doesn't replace the internal primary
* working owner.
* <p>
* This method is for internal use by the jdt-related plug-ins.
* Clients outside of the jdt should not reference this method.
* </p>
- *
+ *
* @param primaryBufferProvider the primary buffer provider
*/
public static void setPrimaryBufferProvider(WorkingCopyOwner primaryBufferProvider) {
DefaultWorkingCopyOwner.PRIMARY.primaryBufferProvider = primaryBufferProvider;
}
-
+
/**
* Creates a buffer for the given working copy.
* The new buffer will be initialized with the contents of the underlying file
- * if and only if it was not already initialized by the compilation owner (a buffer is
+ * if and only if it was not already initialized by the compilation owner (a buffer is
* uninitialized if its content is <code>null</code>).
* <p>
* Note: This buffer will be associated to the working copy for its entire life-cycle. Another
* working copy on same unit but owned by a different owner would not share the same buffer
* unless its owner decided to implement such a sharing behaviour.
* </p>
- *
+ *
* @param workingCopy the working copy of the buffer
* @return IBuffer the created buffer for the given working copy
* @see IBuffer
*/
public IBuffer createBuffer(ICompilationUnit workingCopy) {
- return BufferManager.getDefaultBufferManager().createBuffer(workingCopy);
+ return BufferManager.createBuffer(workingCopy);
+ }
+
+ /**
+ * Returns the problem requestor used by a working copy of this working copy owner.
+ * <p>
+ * By default, no problem requestor is configured. Clients can override this
+ * method to provide a requestor.
+ * </p>
+ *
+ * @param workingCopy The problem requestor used for the given working copy.
+ * @return the problem requestor to be used by working copies of this working
+ * copy owner or <code>null</code> if no problem requestor is configured.
+ *
+ * @since 3.3
+ */
+ public IProblemRequestor getProblemRequestor(ICompilationUnit workingCopy) {
+ return null;
+ }
+
+ /**
+ * Returns a new working copy with the given name using this working copy owner to
+ * create its buffer.
+ * <p>
+ * This working copy always belongs to the default package in a package
+ * fragment root that corresponds to its Java project, and this Java project never exists.
+ * However this Java project has the given classpath that is used when resolving names
+ * in this working copy.
+ * </p><p>
+ * A DOM AST created using this working copy will have bindings resolved using the given
+ * classpath, and problem are reported to the given problem requestor.
+ * <p></p>
+ * <code>JavaCore#getOptions()</code> is used to create the DOM AST as it is not
+ * possible to set the options on the non-existing Java project.
+ * </p><p>
+ * When the working copy instance is created, an {@link IJavaElementDelta#ADDED added delta} is
+ * reported on this working copy.
+ * </p><p>
+ * Once done with the working copy, users of this method must discard it using
+ * {@link ICompilationUnit#discardWorkingCopy()}.
+ * </p><p>
+ * Note that when such working copy is committed, only its buffer is saved (see
+ * {@link IBuffer#save(IProgressMonitor, boolean)}) but no resource is created.
+ * </p><p>
+ * This method is not intended to be overriden by clients.
+ * </p>
+ *
+ * @param name the name of the working copy (e.g. "X.java")
+ * @param classpath the classpath used to resolve names in this working copy
+ * @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.
+ * @param monitor a progress monitor used to report progress while opening the working copy
+ * or <code>null</code> if no progress should be reported
+ * @throws JavaModelException if the contents of this working copy can
+ * not be determined.
+ * @return a new working copy
+ * @see ICompilationUnit#becomeWorkingCopy(IProblemRequestor, IProgressMonitor)
+ * @since 3.2
+ *
+ * @deprecated Use {@link #newWorkingCopy(String, IClasspathEntry[], IProgressMonitor)} instead.
+ * Note that if this deprecated method is used, problems may be reported twice
+ * if the given requestor is not the same as the current working copy owner one.
+ */
+ public final ICompilationUnit newWorkingCopy(String name, IClasspathEntry[] classpath, IProblemRequestor problemRequestor, IProgressMonitor monitor) throws JavaModelException {
+ ExternalJavaProject project = new ExternalJavaProject(classpath);
+ IPackageFragment parent = project.getPackageFragmentRoot(Path.EMPTY).getPackageFragment(IPackageFragment.DEFAULT_PACKAGE_NAME);
+ CompilationUnit result = new CompilationUnit((PackageFragment) parent, name, this);
+ result.becomeWorkingCopy(problemRequestor, monitor);
+ return result;
+ }
+
+ /**
+ * Returns a new working copy with the given name using this working copy owner to
+ * create its buffer.
+ * <p>
+ * This working copy always belongs to the default package in a package
+ * fragment root that corresponds to its Java project, and this Java project never exists.
+ * However this Java project has the given classpath that is used when resolving names
+ * in this working copy.
+ * </p><p>
+ * If a DOM AST is created using this working copy, then given classpath will be used
+ * if bindings need to be resolved. Problems will be reported to the problem requestor
+ * of the current working copy owner problem if it is not <code>null</code>.
+ * <p></p>
+ * Options used to create the DOM AST are got from {@link JavaCore#getOptions()}
+ * as it is not possible to set the options on a non-existing Java project.
+ * </p><p>
+ * When the working copy instance is created, an {@link IJavaElementDelta#ADDED added delta} is
+ * reported on this working copy.
+ * </p><p>
+ * Once done with the working copy, users of this method must discard it using
+ * {@link ICompilationUnit#discardWorkingCopy()}.
+ * </p><p>
+ * Note that when such working copy is committed, only its buffer is saved (see
+ * {@link IBuffer#save(IProgressMonitor, boolean)}) but no resource is created.
+ * </p><p>
+ * This method is not intended to be overriden by clients.
+ * </p>
+ *
+ * @param name the name of the working copy (e.g. "X.java")
+ * @param classpath the classpath used to resolve names in this working copy
+ * @param monitor a progress monitor used to report progress while opening the working copy
+ * or <code>null</code> if no progress should be reported
+ * @throws JavaModelException if the contents of this working copy can
+ * not be determined.
+ * @return a new working copy
+ * @see ICompilationUnit#becomeWorkingCopy(IProgressMonitor)
+ *
+ * @since 3.3
+ */
+ public final ICompilationUnit newWorkingCopy(String name, IClasspathEntry[] classpath, IProgressMonitor monitor) throws JavaModelException {
+ ExternalJavaProject project = new ExternalJavaProject(classpath);
+ IPackageFragment parent = project.getPackageFragmentRoot(Path.EMPTY).getPackageFragment(IPackageFragment.DEFAULT_PACKAGE_NAME);
+ CompilationUnit result = new CompilationUnit((PackageFragment) parent, name, this);
+ result.becomeWorkingCopy(getProblemRequestor(result), monitor);
+ return result;
}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/compiler/BuildContext.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/compiler/BuildContext.java
new file mode 100755
index 0000000..24fa223
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/compiler/BuildContext.java
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.compiler;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jdt.internal.core.builder.CompilationParticipantResult;
+import org.eclipse.jdt.internal.core.builder.SourceFile;
+
+/**
+ * The context of a build event that is notified to interested compilation
+ * participants when {@link CompilationParticipant#buildStarting(BuildContext[], boolean) a build is starting},
+ * or to annotations processors when {@link CompilationParticipant#processAnnotations(BuildContext[]) a source file has annotations}.
+ * <p>
+ * This class is not intended to be instanciated or subclassed by clients.
+ * </p>
+ * @since 3.2
+ */
+public class BuildContext extends CompilationParticipantResult {
+
+/**
+ * Creates a build context for the given source file.
+ * <p>
+ * This constructor is not intended to be called by clients.
+ * </p>
+ *
+ * @param sourceFile the source file being built
+ */
+public BuildContext(SourceFile sourceFile) {
+ super(sourceFile);
+}
+
+/**
+ * Returns the contents of the compilation unit.
+ *
+ * @return the contents of the compilation unit
+ */
+public char[] getContents() {
+ return this.sourceFile.getContents();
+}
+
+/**
+ * Returns the <code>IFile</code> representing the compilation unit.
+ *
+ * @return the <code>IFile</code> representing the compilation unit
+ */
+public IFile getFile() {
+ return this.sourceFile.resource;
+}
+
+/**
+ * Returns whether the compilation unit contained any annotations when it was compiled.
+ *
+ * NOTE: This is only valid during {@link CompilationParticipant#processAnnotations(BuildContext[])}.
+ *
+ * @return whether the compilation unit contained any annotations when it was compiled
+ */
+public boolean hasAnnotations() {
+ return this.hasAnnotations; // only set during processAnnotations
+}
+
+/**
+ * Record the added/changed generated files that need to be compiled.
+ *
+ * @param addedGeneratedFiles the added/changed files
+ */
+public void recordAddedGeneratedFiles(IFile[] addedGeneratedFiles) {
+ int length2 = addedGeneratedFiles.length;
+ if (length2 == 0) return;
+
+ int length1 = this.addedFiles == null ? 0 : this.addedFiles.length;
+ IFile[] merged = new IFile[length1 + length2];
+ if (length1 > 0) // always make a copy even if currently empty
+ System.arraycopy(this.addedFiles, 0, merged, 0, length1);
+ System.arraycopy(addedGeneratedFiles, 0, merged, length1, length2);
+ this.addedFiles = merged;
+}
+
+/**
+ * Record the generated files that need to be deleted.
+ *
+ * @param deletedGeneratedFiles the files that need to be deleted
+ */
+public void recordDeletedGeneratedFiles(IFile[] deletedGeneratedFiles) {
+ int length2 = deletedGeneratedFiles.length;
+ if (length2 == 0) return;
+
+ int length1 = this.deletedFiles == null ? 0 : this.deletedFiles.length;
+ IFile[] merged = new IFile[length1 + length2];
+ if (length1 > 0) // always make a copy even if currently empty
+ System.arraycopy(this.deletedFiles, 0, merged, 0, length1);
+ System.arraycopy(deletedGeneratedFiles, 0, merged, length1, length2);
+ this.deletedFiles = merged;
+}
+
+/**
+ * Record the fully-qualified type names of any new dependencies, each name is of the form "p1.p2.A.B".
+ *
+ * @param typeNameDependencies the fully-qualified type names of new dependencies
+ */
+public void recordDependencies(String[] typeNameDependencies) {
+ int length2 = typeNameDependencies.length;
+ if (length2 == 0) return;
+
+ int length1 = this.dependencies == null ? 0 : this.dependencies.length;
+ String[] merged = new String[length1 + length2];
+ if (length1 > 0) // always make a copy even if currently empty
+ System.arraycopy(this.dependencies, 0, merged, 0, length1);
+ System.arraycopy(typeNameDependencies, 0, merged, length1, length2);
+ this.dependencies = merged;
+}
+
+/**
+ * Record new problems to report against this compilationUnit.
+ * Markers are persisted for these problems only for the declared managed marker type
+ * (see the 'compilationParticipant' extension point).
+ *
+ * @param newProblems the problems to report
+ */
+public void recordNewProblems(CategorizedProblem[] newProblems) {
+ int length2 = newProblems.length;
+ if (length2 == 0) return;
+
+ int length1 = this.problems == null ? 0 : this.problems.length;
+ CategorizedProblem[] merged = new CategorizedProblem[length1 + length2];
+ if (length1 > 0) // always make a copy even if currently empty
+ System.arraycopy(this.problems, 0, merged, 0, length1);
+ System.arraycopy(newProblems, 0, merged, length1, length2);
+ this.problems = merged;
+}
+
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/compiler/CompilationParticipant.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/compiler/CompilationParticipant.java
new file mode 100755
index 0000000..c27ab15
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/compiler/CompilationParticipant.java
@@ -0,0 +1,134 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * mkaufman@bea.com - initial API as ICompilationParticipant
+ * IBM - changed from interface ICompilationParticipant to abstract class CompilationParticipant
+ * IBM - rewrote spec
+ *
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.compiler;
+
+import org.eclipse.jdt.core.IJavaProject;
+
+/**
+ * A compilation participant is notified of events occuring during the compilation process.
+ * The compilation process not only involves generating .class files (i.e. building), it also involves
+ * cleaning the output directory, reconciling a working copy, etc.
+ * So the notified events are the result of a build action, a clean action, a reconcile operation
+ * (for a working copy), etc.
+ * <p>
+ * Code that participates in the build should in general be implemented with a separate Builder,
+ * rather than a CompilationParticipant. It is only necessary to use a CompilationParticipant if
+ * the build step needs to interact with the Java build, for instance by creating additional
+ * Java source files that must themselves in turn be compiled.
+ * <p>
+ * Clients wishing to participate in the compilation process must suclass this class, and implement
+ * {@link #isActive(IJavaProject)}, {@link #aboutToBuild(IJavaProject)},
+ * {@link #reconcile(ReconcileContext)}, etc.
+* </p><p>
+ * This class is intended to be subclassed by clients.
+ * </p>
+ * @since 3.2
+ */
+public abstract class CompilationParticipant {
+
+public static int READY_FOR_BUILD = 1;
+public static int NEEDS_FULL_BUILD = 2;
+
+/**
+ * Notifies this participant that a build is about to start and provides it the opportunity to
+ * create missing source folders for generated source files. Additional source folders
+ * should be marked as optional so the project can be built when the folders do not exist.
+ * Only sent to participants interested in the project.
+ * <p>
+ * Default is to return <code>READY_FOR_BUILD</code>.
+ * </p>
+ * @param project the project about to build
+ * @return READY_FOR_BUILD or NEEDS_FULL_BUILD
+ */
+public int aboutToBuild(IJavaProject project) {
+ return READY_FOR_BUILD;
+}
+
+/**
+ * Notifies this participant that a compile operation is about to start and provides it the opportunity to
+ * generate source files based on the source files about to be compiled.
+ * When isBatchBuild is true, then files contains all source files in the project.
+ * Only sent to participants interested in the current build project.
+ *
+ * @param files is an array of BuildContext
+ * @param isBatch identifies when the build is a batch build
+ */
+public void buildStarting(BuildContext[] files, boolean isBatch) {
+ // do nothing by default
+}
+
+/**
+ * Notifies this participant that a clean is about to start and provides it the opportunity to
+ * delete generated source files.
+ * Only sent to participants interested in the project.
+ * @param project the project about to be cleaned
+ */
+public void cleanStarting(IJavaProject project) {
+ // do nothing by default
+}
+
+/**
+ * Returns whether this participant is active for a given project.
+ * <p>
+ * Default is to return <code>false</code>.
+ * </p><p>
+ * For efficiency, participants that are not interested in the
+ * given project should return <code>false</code> for that project.
+ * </p>
+ * @param project the project to participate in
+ * @return whether this participant is active for a given project
+ */
+public boolean isActive(IJavaProject project) {
+ return false;
+}
+
+/**
+ * Returns whether this participant is interested in only Annotations.
+ * <p>
+ * Default is to return <code>false</code>.
+ * </p>
+ * @return whether this participant is interested in only Annotations.
+ */
+public boolean isAnnotationProcessor() {
+ return false;
+}
+
+/**
+ * Notifies this participant that a compile operation has found source files using Annotations.
+ * Only sent to participants interested in the current build project that answer true to isAnnotationProcessor().
+ * Each BuildContext was informed whether its source file currently hasAnnotations().
+ *
+ * @param files is an array of BuildContext
+ */
+public void processAnnotations(BuildContext[] files) {
+ // do nothing by default
+}
+
+/**
+ * Notifies this participant that a reconcile operation is happening. The participant can act on this reconcile
+ * operation by using the given context. Other participant can then see the result of this participation
+ * on this context.
+ * <p>
+ * Note that a participant should not modify the buffer of the working copy that is being reconciled.
+ * </p><p>
+ * Default is to do nothing.
+ * </p>
+ * @param context the reconcile context to act on
+ */
+public void reconcile(ReconcileContext context) {
+ // do nothing by default
+}
+
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/compiler/IScanner.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/compiler/IScanner.java
index 2036684..0e1d57b 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/compiler/IScanner.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/compiler/IScanner.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -17,11 +17,14 @@
* Definition of a Java scanner, as returned by the <code>ToolFactory</code>.
* The scanner is responsible for tokenizing a given source, providing information about
* the nature of the token read, its positions and source equivalent.
- *
+ * <p>
* When the scanner has finished tokenizing, it answers an EOF token (<code>
* ITerminalSymbols#TokenNameEOF</code>.
- *
+ * </p><p>
* When encountering lexical errors, an <code>InvalidInputException</code> is thrown.
+ * </p><p>
+ * This interface is not intended to be implemented by clients.
+ * </p>
*
* @see org.eclipse.jdt.core.ToolFactory
* @see ITerminalSymbols
@@ -140,6 +143,7 @@
/**
* Set the scanner source to process. By default, the scanner will consider starting at the beginning of the
* source until it reaches its end.
+ * If the given source is <code>null</code>, this clears the source.
*
* @param source the given source
*/
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/compiler/ITerminalSymbols.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/compiler/ITerminalSymbols.java
index 3cdf047..7e500bf 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/compiler/ITerminalSymbols.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/compiler/ITerminalSymbols.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -14,6 +14,9 @@
/**
* Maps each terminal symbol in the java-grammar into a unique integer.
* This integer is used to represent the terminal when computing a parsing action.
+ * <p>
+ * This interface is not intended to be implemented by clients.
+ * </p>
*
* @see IScanner
* @since 2.0
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/compiler/ReconcileContext.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/compiler/ReconcileContext.java
new file mode 100755
index 0000000..474cd00
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/compiler/ReconcileContext.java
@@ -0,0 +1,194 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * mkaufman@bea.com - initial API and implementation
+ * IBM - renamed from PreReconcileCompilationResult to ReconcileContext
+ * IBM - rewrote spec
+ *
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.compiler;
+
+import java.util.HashMap;
+
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaElementDelta;
+import org.eclipse.jdt.core.IJavaModelMarker;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.ASTParser;
+import org.eclipse.jdt.internal.core.CompilationUnit;
+import org.eclipse.jdt.internal.core.JavaProject;
+import org.eclipse.jdt.internal.core.ReconcileWorkingCopyOperation;
+
+/**
+ * The context of a reconcile event that is notified to interested compilation
+ * participants while a reconcile operation is running.
+ * <p>
+ * A reconcile participant can get the AST for the reconcile-operation using
+ * {@link #getAST3()}. If the participant modifies in any way the AST
+ * (either by modifying the source of the working copy, or modifying another entity
+ * that would result in different bindings for the AST), it is expected to reset the
+ * AST in the context using {@link #resetAST()}.
+ * </p><p>
+ * A reconcile participant can also create and return problems using
+ * {@link #putProblems(String, CategorizedProblem[])}. These problems are then reported
+ * to the problem requestor of the reconcile operation.
+ * </p><p>
+ * This class is not intended to be instanciated or subclassed by clients.
+ * </p>
+ *
+ * @see CompilationParticipant#reconcile(ReconcileContext)
+ * @since 3.2
+ */
+public class ReconcileContext {
+
+ private ReconcileWorkingCopyOperation operation;
+ private CompilationUnit workingCopy;
+
+/**
+ * Creates a reconcile context for the given reconcile operation.
+ * <p>
+ * This constructor is not intended to be called by clients.
+ * </p>
+ *
+ * @param operation the reconcile operation
+ */
+public ReconcileContext(ReconcileWorkingCopyOperation operation, CompilationUnit workingCopy) {
+ this.operation = operation;
+ this.workingCopy = workingCopy;
+}
+
+/**
+ * Returns a resolved AST with {@link AST#JLS3 JLS3} level.
+ * It is created from the current state of the working copy.
+ * Creates one if none exists yet.
+ * Returns <code>null</code> if the current state of the working copy
+ * doesn't allow the AST to be created (e.g. if the working copy's content
+ * cannot be parsed).
+ * <p>
+ * If the AST level requested during reconciling is not {@link AST#JLS3}
+ * or if binding resolutions was not requested, then a different AST is created.
+ * Note that this AST does not become the current AST and it is only valid for
+ * the requestor.
+ * </p>
+ *
+ * @return the AST created from the current state of the working copy,
+ * or <code>null</code> if none could be created
+ * @exception JavaModelException if the contents of the working copy
+ * cannot be accessed. Reasons include:
+ * <ul>
+ * <li> The working copy does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+ * </ul>
+ */
+public org.eclipse.jdt.core.dom.CompilationUnit getAST3() throws JavaModelException {
+ if (this.operation.astLevel != AST.JLS3 || !this.operation.resolveBindings) {
+ // create AST (optionally resolving bindings)
+ ASTParser parser = ASTParser.newParser(AST.JLS3);
+ parser.setCompilerOptions(workingCopy.getJavaProject().getOptions(true));
+ if (JavaProject.hasJavaNature(workingCopy.getJavaProject().getProject()))
+ parser.setResolveBindings(true);
+ parser.setStatementsRecovery((this.operation.reconcileFlags & ICompilationUnit.ENABLE_STATEMENTS_RECOVERY) != 0);
+ parser.setBindingsRecovery((this.operation.reconcileFlags & ICompilationUnit.ENABLE_BINDINGS_RECOVERY) != 0);
+ parser.setSource(workingCopy);
+ return (org.eclipse.jdt.core.dom.CompilationUnit) parser.createAST(this.operation.progressMonitor);
+ }
+ return this.operation.makeConsistent(this.workingCopy);
+}
+
+/**
+ * Returns the AST level requested by the reconcile operation.
+ * It is either {@link ICompilationUnit#NO_AST}, or one of the JLS constants defined on {@link AST}.
+ *
+ * @return the AST level requested by the reconcile operation
+ */
+public int getASTLevel() {
+ return this.operation.astLevel;
+}
+
+/**
+ * Returns whether the reconcile operation is resolving bindings.
+ *
+ * @return whether the reconcile operation is resolving bindings
+ */
+public boolean isResolvingBindings() {
+ return this.operation.resolveBindings;
+}
+
+/**
+ * Returns the delta describing the change to the working copy being reconciled.
+ * Returns <code>null</code> if there is no change.
+ * Note that the delta's AST is not yet positionnned at this stage. Use {@link #getAST3()}
+ * to get the current AST.
+ *
+ * @return the delta describing the change, or <code>null</code> if none
+ */
+public IJavaElementDelta getDelta() {
+ return this.operation.deltaBuilder.delta;
+}
+
+/**
+ * Returns the problems to be reported to the problem requestor of the reconcile operation
+ * for the given marker type.
+ * Returns <code>null</code> if no problems need to be reported for this marker type.
+ *
+ * @param markerType the given marker type
+ * @return problems to be reported to the problem requesto
+ */
+public CategorizedProblem[] getProblems(String markerType) {
+ if (this.operation.problems == null) return null;
+ return (CategorizedProblem[]) this.operation.problems.get(markerType);
+}
+
+/**
+ * Returns the working copy this context refers to.
+ *
+ * @return the working copy this context refers to
+ */
+public ICompilationUnit getWorkingCopy() {
+ return this.workingCopy;
+}
+
+/**
+ * Resets the AST carried by this context.
+ * A compilation participant that modifies the environment that would result in different
+ * bindings for the AST is expected to reset the AST on this context, so that other
+ * participants don't get a stale AST.
+ * <p>
+ * Note that resetting the AST will not restart the reconcile process. Only further
+ * participants will see the new AST. Thus participants running before the one that
+ * resets the AST will have a stale view of the AST and its problems. Use
+ * the compilation participant extension point to order the participants.
+ * </p>
+ */
+public void resetAST() {
+ this.operation.ast = null;
+ putProblems(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, null);
+ putProblems(IJavaModelMarker.TASK_MARKER, null);
+}
+
+/**
+ * Sets the problems to be reported to the problem requestor of the reconcile operation
+ * for the given marker type.
+ * <code>null</code> indicates that no problems need to be reported.
+ * <p>
+ * Using this functionality, a participant that resolves problems for a given marker type
+ * can hide those problems since they don't exist any longer.
+ * </p>
+ *
+ * @param markerType the marker type of the given problems
+ * @param problems the problems to be reported to the problem requestor of the reconcile operation,
+ * or <code>null</code> if none
+ */
+public void putProblems(String markerType, CategorizedProblem[] problems) {
+ if (this.operation.problems == null)
+ this.operation.problems = new HashMap();
+ this.operation.problems.put(markerType, problems);
+}
+
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/eval/ICodeSnippetRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/eval/ICodeSnippetRequestor.java
index 03bba9c..d9be4b1 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/eval/ICodeSnippetRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/eval/ICodeSnippetRequestor.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/eval/IEvaluationContext.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/eval/IEvaluationContext.java
index fe44004..1f44230 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/eval/IEvaluationContext.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/eval/IEvaluationContext.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -342,7 +342,7 @@
throws JavaModelException;
/**
* Evaluates the given global variable. During this operation,
- * this context's package declaration, imports, and <it>all</it> its declared
+ * this context's package declaration, imports, and <i>all</i> its declared
* variables are verified. The given requestor's <code>acceptProblem</code>
* method will be called for each problem that is detected.
* <p>
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/eval/IGlobalVariable.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/eval/IGlobalVariable.java
index 5195648..0a57fa8 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/eval/IGlobalVariable.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/eval/IGlobalVariable.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/DOMException.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/DOMException.java
index f8ba578..5add075 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/DOMException.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/DOMException.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/DOMFactory.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/DOMFactory.java
index c0737f6..775d2dd 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/DOMFactory.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/DOMFactory.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/IDOMCompilationUnit.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/IDOMCompilationUnit.java
index cb2dfc2..ba8da3e 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/IDOMCompilationUnit.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/IDOMCompilationUnit.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -11,7 +11,9 @@
package org.eclipse.jdt.core.jdom;
/**
- * Represents a Java compilation unit (<code>.java</code> source file).
+ * Represents a Java compilation unit (source file with one of the
+ * {@link org.eclipse.jdt.core.JavaCore#getJavaLikeExtensions()
+ * Java-like extensions}).
* The corresponding syntactic unit is CompilationUnit (JLS2 7.3).
* Allowable child types for a compilation unit are <code>IDOMPackage</code>, <code>IDOMImport</code>,
* and <code>IDOMType</code>.
@@ -38,7 +40,9 @@
* method returns the name of this compilation unit.
*
* <p>The name of a compilation unit is the name of the first top-level public type
- * defined in the compilation unit, suffixed with ".java". For example, if the first
+ * defined in the compilation unit, suffixed with one of the
+ * {@link org.eclipse.jdt.core.JavaCore#getJavaLikeExtensions()
+ * Java-like extensions}. For example, if the first
* top-level public type defined in this compilation unit has the name "Hanoi",
* then name of this compilation unit is "Hanoi.java".</p>
*
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/IDOMFactory.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/IDOMFactory.java
index f4eedbf..3b84062 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/IDOMFactory.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/IDOMFactory.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -13,7 +13,9 @@
/**
* A factory used to create document fragment (DF) nodes. An
* <code>IDOMCompilationUnit</code> represents the root of a complete JDOM (that
- * is, a ".java" file). Other node types represent fragments of a compilation
+ * is, a source file with one of the
+ * {@link org.eclipse.jdt.core.JavaCore#getJavaLikeExtensions()
+ * Java-like extensions}). Other node types represent fragments of a compilation
* unit.
* <p>
* The factory can be used to create empty DFs or it can create DFs from source
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/IDOMField.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/IDOMField.java
index 2ec880d..9c37dda 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/IDOMField.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/IDOMField.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/IDOMImport.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/IDOMImport.java
index 913009a..fbb62ca 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/IDOMImport.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/IDOMImport.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/IDOMInitializer.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/IDOMInitializer.java
index bb9b028..7ff9752 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/IDOMInitializer.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/IDOMInitializer.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/IDOMMember.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/IDOMMember.java
index a031200..1f7165d 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/IDOMMember.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/IDOMMember.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/IDOMMethod.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/IDOMMethod.java
index c1f3fc7..18d9bc3 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/IDOMMethod.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/IDOMMethod.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/IDOMNode.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/IDOMNode.java
index 525105d..ce7469b 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/IDOMNode.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/IDOMNode.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -144,7 +144,7 @@
/**
* Returns the current contents of this document fragment as a character array.
* <p>
- * Note: To obtain complete source for the ".java" file, ask a compilation unit
+ * Note: To obtain complete source for the source file, ask a compilation unit
* node for its contents.
* </p>
*
@@ -169,7 +169,7 @@
/**
* Returns the current contents of this document fragment.
* <p>
- * Note: To obtain complete source for the ".java" file, ask a compilation unit
+ * Note: To obtain complete source for the source file, ask a compilation unit
* node for its contents.
* </p>
*
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/IDOMPackage.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/IDOMPackage.java
index 674cb0d..445d5c6 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/IDOMPackage.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/IDOMPackage.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/IDOMType.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/IDOMType.java
index 9e559a7..ed97e90 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/IDOMType.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/IDOMType.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ByteCodeVisitorAdapter.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ByteCodeVisitorAdapter.java
index 7689012..386c049 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ByteCodeVisitorAdapter.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ByteCodeVisitorAdapter.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ClassFileBytesDisassembler.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ClassFileBytesDisassembler.java
index 2453dcd..374361d 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ClassFileBytesDisassembler.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ClassFileBytesDisassembler.java
@@ -43,6 +43,12 @@
public final static int COMPACT = 8;
/**
+ * This mode is used to retrive a pseudo code for working copy purpose.
+ * @since 3.2
+ */
+ public final static int WORKING_COPY = 16;
+
+ /**
* Answers back the disassembled string of the classfile bytes using the default
* mode.
* This is an output quite similar to the javap tool, using DEFAULT mode.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ClassFormatException.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ClassFormatException.java
index a76ac8d..bb7a3c1 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ClassFormatException.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ClassFormatException.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/CompilationUnitSorter.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/CompilationUnitSorter.java
index 2bba98d..0946d9b 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/CompilationUnitSorter.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/CompilationUnitSorter.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Alex Blewitt - alex_blewitt@yahoo.com https://bugs.eclipse.org/bugs/show_bug.cgi?id=171066
*******************************************************************************/
package org.eclipse.jdt.core.util;
@@ -15,9 +16,13 @@
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.internal.core.SortElementsOperation;
+import org.eclipse.text.edits.TextEdit;
+import org.eclipse.text.edits.TextEditGroup;
/**
* Operation for sorting members within a compilation unit.
@@ -37,6 +42,19 @@
// Not instantiable
}
+ /**
+ * @deprecated marking deprecated as it is using deprecated code
+ */
+ private static void checkASTLevel(int level) {
+ switch (level) {
+ case AST.JLS2 :
+ case AST.JLS3 :
+ break;
+ default :
+ throw new IllegalArgumentException();
+ }
+ }
+
/**
* Name of auxillary property whose value can be used to determine the
* original relative order of two body declarations. This allows a
@@ -310,15 +328,129 @@
if (compilationUnit == null || comparator == null) {
throw new IllegalArgumentException();
}
- switch (level) {
- case AST.JLS2 :
- case AST.JLS3 :
- break;
- default :
- throw new IllegalArgumentException();
- }
+ checkASTLevel(level);
ICompilationUnit[] compilationUnits = new ICompilationUnit[] { compilationUnit };
SortElementsOperation operation = new SortElementsOperation(level, compilationUnits, positions, comparator);
operation.runOperation(monitor);
}
+
+ /**
+ * Reorders the declarations in the given compilation unit according to the
+ * specified comparator. The caller is responsible for arranging in advance
+ * that the given compilation unit is a working copy, and for applying the
+ * returned TextEdit afterwards.
+ * <p>
+ * <b>Note:</b> Reordering the members within a type declaration might be
+ * more than a cosmetic change and could have potentially serious
+ * repercussions. Firstly, the order in which the fields of a type are
+ * initialized is significant in the Java language; reordering fields and
+ * initializers may result in compilation errors or change the execution
+ * behavior of the code. Secondly, reordering a class's members may affect
+ * how its instances are serialized. This operation should therefore be used
+ * with caution and due concern for potential negative side effects.
+ * </p>
+ * <p>
+ * The <code>compare</code> method of the given comparator is passed pairs
+ * of body declarations (subclasses of <code>BodyDeclaration</code>)
+ * representing body declarations at the same level.
+ * The comparator is called on body declarations of nested classes,
+ * including anonymous and local classes, but always at the same level.
+ * Clients need to provide a comparator implementation (there is no standard
+ * comparator). The <code>RELATIVE_ORDER</code> property attached to these
+ * AST nodes affords the comparator a way to preserve the original relative
+ * order.
+ * </p>
+ * <p>
+ * The body declarations passed as parameters to the comparator always carry
+ * at least the following minimal signature information: <br>
+ * <table border="1" width="80%" cellpadding="5">
+ * <tr>
+ * <td width="20%"><code>TypeDeclaration</code></td>
+ * <td width="50%"><code>modifiers, isInterface, name, superclass,
+ * superInterfaces, typeParameters<br>
+ * RELATIVE_ORDER property</code></td>
+ * </tr>
+ * <tr>
+ * <td width="20%"><code>FieldDeclaration</code></td>
+ * <td width="50%"><code>modifiers, type, fragments
+ * (VariableDeclarationFragments
+ * with name only)<br>
+ * RELATIVE_ORDER property</code></td>
+ * </tr>
+ * <tr>
+ * <td width="20%"><code>MethodDeclaration</code></td>
+ * <td width="50%"><code>modifiers, isConstructor, returnType, name,
+ * typeParameters, parameters
+ * (SingleVariableDeclarations with name, type, and modifiers only),
+ * thrownExceptions<br>
+ * RELATIVE_ORDER property</code></td>
+ * </tr>
+ * <tr>
+ * <td width="20%"><code>Initializer</code></td>
+ * <td width="50%"><code>modifiers<br>
+ * RELATIVE_ORDER property</code></td>
+ * </tr>
+ * <tr>
+ * <td width="20%"><code>AnnotationTypeDeclaration</code></td>
+ * <td width="50%"><code>modifiers, name<br>
+ * RELATIVE_ORDER property</code></td>
+ * </tr>
+ * <tr>
+ * <td width="20%"><code>AnnotationTypeMemberDeclaration</code></td>
+ * <td width="50%"><code>modifiers, name, type, default<br>
+ * RELATIVE_ORDER property</code></td>
+ * </tr>
+ * <tr>
+ * <td width="20%"><code>EnumDeclaration</code></td>
+ * <td width="50%"><code>modifiers, name, superInterfaces<br>
+ * RELATIVE_ORDER property</code></td>
+ * </tr>
+ * <tr>
+ * <td width="20%"><code>EnumConstantDeclaration</code></td>
+ * <td width="50%"><code>modifiers, name, arguments<br>
+ * RELATIVE_ORDER property</code></td>
+ * </tr>
+ * </table>
+ * </p>
+ *
+ * @param unit
+ * the CompilationUnit to sort
+ * @param comparator
+ * the comparator capable of ordering
+ * <code>BodyDeclaration</code>s; this comparator is passed
+ * AST nodes from an AST of the specified AST level
+ * @param options
+ * bitwise-or of option flags; <code>0</code> for default
+ * behavior (reserved for future growth)
+ * @param group
+ * the text edit group to use when generating text edits, or <code>null</code>
+ * @param monitor
+ * the progress monitor to notify, or <code>null</code> if none
+ * @return a TextEdit describing the required edits to do the sort, or <code>null</code>
+ * if sorting is not required
+ * @exception JavaModelException
+ * if the compilation unit could not be sorted. Reasons
+ * include:
+ * <ul>
+ * <li> The given unit was not created from a ICompilationUnit (INVALID_ELEMENT_TYPES)</li>
+ * </ul>
+ * @exception IllegalArgumentException
+ * if the given compilation unit is null or if the given
+ * comparator is null, or if <code>options</code> is not one
+ * of the supported levels.
+ * @see org.eclipse.jdt.core.dom.BodyDeclaration
+ * @see #RELATIVE_ORDER
+ * @since 3.3
+ */
+ public static TextEdit sort(CompilationUnit unit,
+ Comparator comparator,
+ int options,
+ TextEditGroup group,
+ IProgressMonitor monitor) throws JavaModelException {
+ if (unit == null || comparator == null) {
+ throw new IllegalArgumentException();
+ }
+ SortElementsOperation operation = new SortElementsOperation(AST.JLS3, new IJavaElement[] { unit.getJavaElement() }, null, comparator);
+ return operation.calculateEdit(unit, group);
+ }
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAnnotation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAnnotation.java
index c7fe6f9..7655b47 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAnnotation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAnnotation.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004 IBM Corporation and others.
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAnnotationComponent.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAnnotationComponent.java
index 1e1bd2b..3ddb2e5 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAnnotationComponent.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAnnotationComponent.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAnnotationDefaultAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAnnotationDefaultAttribute.java
index 0093a66..335ddf1 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAnnotationDefaultAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAnnotationDefaultAttribute.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAttributeNamesConstants.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAttributeNamesConstants.java
index 0bdc102..386bf0c 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAttributeNamesConstants.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IAttributeNamesConstants.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -129,4 +129,16 @@
* @since 3.0
*/
char[] ANNOTATION_DEFAULT = "AnnotationDefault".toCharArray(); //$NON-NLS-1$
+
+ /**
+ * "StackMapTable" attribute (added in J2SE 1.6).
+ * @since 3.2
+ */
+ char[] STACK_MAP_TABLE = "StackMapTable".toCharArray(); //$NON-NLS-1$
+
+ /**
+ * "StackMap" attribute (added in cldc1.0).
+ * @since 3.2
+ */
+ char[] STACK_MAP = "StackMap".toCharArray(); //$NON-NLS-1$
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IBytecodeVisitor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IBytecodeVisitor.java
index a2c23ee..b1dbbe3 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IBytecodeVisitor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IBytecodeVisitor.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IClassFileAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IClassFileAttribute.java
index c3b5948..5beeed2 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IClassFileAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IClassFileAttribute.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IClassFileDisassembler.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IClassFileDisassembler.java
index 7805f76..afd1b97 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IClassFileDisassembler.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IClassFileDisassembler.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -15,7 +15,7 @@
* IClassFileReader onto a String using the proper line separator.
*
* @since 2.0
- * @deprecated - should use ClassFileBytesDisassembler instead
+ * @deprecated Use {@link ClassFileBytesDisassembler} instead
*/
public interface IClassFileDisassembler {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IClassFileReader.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IClassFileReader.java
index 69acad3..1d73ec4 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IClassFileReader.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IClassFileReader.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ICodeAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ICodeAttribute.java
index 94d6a7f..28d5bb9 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ICodeAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ICodeAttribute.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPool.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPool.java
index d536a57..b06d30c 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPool.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPool.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPoolConstant.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPoolConstant.java
index e7bd618..7c15431 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPoolConstant.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantPoolConstant.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantValueAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantValueAttribute.java
index 4849dcb..594eb05 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantValueAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IConstantValueAttribute.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IEnclosingMethodAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IEnclosingMethodAttribute.java
index 0088464..b7fe519 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IEnclosingMethodAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IEnclosingMethodAttribute.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004 IBM Corporation and others.
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IExceptionAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IExceptionAttribute.java
index c3d9c20..3a610bb 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IExceptionAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IExceptionAttribute.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IExceptionTableEntry.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IExceptionTableEntry.java
index decb049..7cce15c 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IExceptionTableEntry.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IExceptionTableEntry.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IFieldInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IFieldInfo.java
index ebabb40..71b8fb2 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IFieldInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IFieldInfo.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IInnerClassesAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IInnerClassesAttribute.java
index e89e12e..b370218 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IInnerClassesAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IInnerClassesAttribute.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IInnerClassesAttributeEntry.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IInnerClassesAttributeEntry.java
index dc90439..da8e9b5 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IInnerClassesAttributeEntry.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IInnerClassesAttributeEntry.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ILineNumberAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ILineNumberAttribute.java
index c91f409..8ecc48d 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ILineNumberAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ILineNumberAttribute.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ILocalVariableAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ILocalVariableAttribute.java
index 676d8ff..9e3eec2 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ILocalVariableAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ILocalVariableAttribute.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ILocalVariableTableEntry.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ILocalVariableTableEntry.java
index 8b2fbf0..55fdee4 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ILocalVariableTableEntry.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ILocalVariableTableEntry.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ILocalVariableTypeTableAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ILocalVariableTypeTableAttribute.java
index fdc0eda..0a32839 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ILocalVariableTypeTableAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ILocalVariableTypeTableAttribute.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004 IBM Corporation and others.
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ILocalVariableTypeTableEntry.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ILocalVariableTypeTableEntry.java
index 4c4a3ba..19be343 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ILocalVariableTypeTableEntry.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ILocalVariableTypeTableEntry.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004 IBM Corporation and others.
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IMethodInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IMethodInfo.java
index 4fa8072..7eac9e1 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IMethodInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IMethodInfo.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IModifierConstants.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IModifierConstants.java
index dc59354..3658379 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IModifierConstants.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IModifierConstants.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IOpcodeMnemonics.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IOpcodeMnemonics.java
index 73b0721..bbbbe2a 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IOpcodeMnemonics.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IOpcodeMnemonics.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IParameterAnnotation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IParameterAnnotation.java
index 1016077..0b3303d 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IParameterAnnotation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IParameterAnnotation.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004 IBM Corporation and others.
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IRuntimeInvisibleAnnotationsAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IRuntimeInvisibleAnnotationsAttribute.java
index 6a6fe94..3e78cf2 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IRuntimeInvisibleAnnotationsAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IRuntimeInvisibleAnnotationsAttribute.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004 IBM Corporation and others.
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IRuntimeInvisibleParameterAnnotationsAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IRuntimeInvisibleParameterAnnotationsAttribute.java
index aa5797d..fadb4dd 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IRuntimeInvisibleParameterAnnotationsAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IRuntimeInvisibleParameterAnnotationsAttribute.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004 IBM Corporation and others.
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IRuntimeVisibleAnnotationsAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IRuntimeVisibleAnnotationsAttribute.java
index f70ac57..3f9a0b0 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IRuntimeVisibleAnnotationsAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IRuntimeVisibleAnnotationsAttribute.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004 IBM Corporation and others.
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IRuntimeVisibleParameterAnnotationsAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IRuntimeVisibleParameterAnnotationsAttribute.java
index 433fd41..979ac3b 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IRuntimeVisibleParameterAnnotationsAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IRuntimeVisibleParameterAnnotationsAttribute.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004 IBM Corporation and others.
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ISignatureAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ISignatureAttribute.java
index 46c1779..dd487c3 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ISignatureAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ISignatureAttribute.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004 IBM Corporation and others.
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ISourceAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ISourceAttribute.java
index 2bdd925..73a5f7a 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ISourceAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ISourceAttribute.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IStackMapAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IStackMapAttribute.java
new file mode 100755
index 0000000..ec5060d
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IStackMapAttribute.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.util;
+
+/**
+ * This class represents a stack map attribute.
+ *
+ * This interface may be implemented by clients.
+ *
+ * @since 3.2
+ */
+public interface IStackMapAttribute extends IClassFileAttribute {
+
+ /**
+ * Answer back the number of stack map frames of this atribute as specified in
+ * the JVM specifications.
+ *
+ * @return the number of stack map frames of this atribute as specified in
+ * the JVM specifications
+ */
+ int getNumberOfEntries();
+
+ /**
+ * Answer back the stack map frames for this attribute as specified
+ * in the JVM specifications.
+ *
+ * @return the stack map frames for this attribute as specified
+ * in the JVM specifications
+ */
+ IStackMapFrame[] getStackMapFrame();
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IStackMapFrame.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IStackMapFrame.java
new file mode 100755
index 0000000..52c43a5
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IStackMapFrame.java
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.util;
+
+/**
+ * Description of a stack map frame as specified in the JVM specifications.
+ *
+ * This interface may be implemented by clients.
+ *
+ * @since 3.2
+ */
+public interface IStackMapFrame {
+
+ /**
+ * Answer back the frame type for this entry.
+ * <table>
+ * <tr>
+ * <th align="left">Type</th>
+ * <th align="left">Range</th>
+ * </tr>
+ * <tr>
+ * <td>SAME</td>
+ * <td>0-63</td>
+ * </tr>
+ * <tr>
+ * <td>SAME_LOCALS_1_STACK_ITEM</td>
+ * <td>64-127</td>
+ * </tr>
+ * <tr>
+ * <td>SAME_LOCALS_1_STACK_ITEM_EXTENDED</td>
+ * <td>247</td>
+ * </tr>
+ * <tr>
+ * <td>CHOP</td>
+ * <td>248-250</td>
+ * </tr>
+ * <tr>
+ * <td>SAME_FRAME_EXTENDED</td>
+ * <td>251</td>
+ * </tr>
+ * <tr>
+ * <td>APPEND</td>
+ * <td>252-254</td>
+ * </tr>
+ * <tr>
+ * <td>FULL_FRAME</td>
+ * <td>255</td>
+ * </tr>
+ * </table>
+ *
+ * @return the frame type for this entry
+ */
+ int getFrameType();
+
+ /**
+ * Answer back the offset delta.
+ * <p>This is not defined only for the frame types SAME and SAME_LOCALS_1_STACK_ITEM.</p>
+ *
+ * @return the offset delta
+ */
+ int getOffsetDelta();
+
+ /**
+ * Answer back the number of locals.
+ * <p>This is defined only for the frame type FULL_FRAME.</p>
+ *
+ * @return the number of locals
+ */
+ int getNumberOfLocals();
+
+ /**
+ * Answer back verification infos for the defined locals.
+ * <p>This is defined only for frame types APPEND and FULL_FRAME.
+ *
+ * @return verification infos for the defined locals
+ */
+ IVerificationTypeInfo[] getLocals();
+
+ /**
+ * Answer back the number of stack items
+ * <p>This is defined only for the frame types SAME_LOCALS_1_STACK_ITEM, SAME_LOCALS_1_STACK_ITEM_EXTENDED and FULL_FRAME.
+ * For SAME_LOCALS_1_STACK_ITEM and SAME_LOCALS_1_STACK_ITEM_EXTENDED, the answer is implicitely 1.</p>
+ *
+ * @return the number of stack items
+ */
+ int getNumberOfStackItems();
+
+ /**
+ * Answer back the verification infos for the stack items.
+ *
+ * @return the verification infos for the stack items
+ */
+ IVerificationTypeInfo[] getStackItems();
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IStackMapTableAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IStackMapTableAttribute.java
new file mode 100755
index 0000000..067cd86
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IStackMapTableAttribute.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.util;
+
+/**
+ * This class represents a stack map table attribute.
+ *
+ * This interface may be implemented by clients.
+ *
+ * @since 3.2
+ */
+public interface IStackMapTableAttribute extends IClassFileAttribute {
+
+ /**
+ * Answer back the number of stack map frames of this atribute as specified in
+ * the JVM specifications.
+ *
+ * @return the number of stack map frames of this atribute as specified in
+ * the JVM specifications
+ */
+ int getNumberOfEntries();
+
+ /**
+ * Answer back the stack map frames for this attribute as specified
+ * in the JVM specifications.
+ *
+ * @return the stack map frames for this attribute as specified
+ * in the JVM specifications
+ */
+ IStackMapFrame[] getStackMapFrame();
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IVerificationTypeInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IVerificationTypeInfo.java
index e78fcbb..8300d47 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IVerificationTypeInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/IVerificationTypeInfo.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -19,6 +19,52 @@
*/
public interface IVerificationTypeInfo {
/**
+ * The tag value representing top variable info
+ * @since 3.2
+ */
+ public static final int ITEM_TOP = 0;
+ /**
+ * The tag value representing integer variable info
+ * @since 3.2
+ */
+ public static final int ITEM_INTEGER = 1;
+ /**
+ * The tag value representing float variable info
+ * @since 3.2
+ */
+ public static final int ITEM_FLOAT = 2;
+ /**
+ * The tag value representing double variable info
+ * @since 3.2
+ */
+ public static final int ITEM_DOUBLE = 3;
+ /**
+ * The tag value representing long variable info
+ * @since 3.2
+ */
+ public static final int ITEM_LONG = 4;
+ /**
+ * The tag value representing null variable info
+ * @since 3.2
+ */
+ public static final int ITEM_NULL = 5;
+ /**
+ * The tag value representing uninitialized this variable info
+ * @since 3.2
+ */
+ public static final int ITEM_UNINITIALIZED_THIS = 6;
+ /**
+ * The tag value representing object variable info
+ * @since 3.2
+ */
+ public static final int ITEM_OBJECT = 7;
+ /**
+ * The tag value representing uninitialized variable info
+ * @since 3.2
+ */
+ public static final int ITEM_UNINITIALIZED = 8;
+
+ /**
* Answer back the tag of this verification type info as described in the JVM specifications.
* <ul>
* <li>0 for the top type</li>
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/OpcodeStringValues.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/OpcodeStringValues.java
index b1fa9d1..dc60807 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/OpcodeStringValues.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/OpcodeStringValues.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/DocumentElementParser.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/DocumentElementParser.java
index a7a3cce..d732132 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/DocumentElementParser.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/DocumentElementParser.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,21 +10,7 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler;
-/*
- * A document element parser extracts structural information
- * from a piece of source, providing detailed source positions info.
- *
- * also see @IDocumentElementRequestor
- *
- * The structural investigation includes:
- * - the package statement
- * - import statements
- * - top-level types: package member, member types (member types of member types...)
- * - fields
- * - methods
- *
- * Any (parsing) problem encountered is also provided.
- */
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.env.*;
import org.eclipse.jdt.internal.compiler.impl.*;
@@ -48,8 +34,6 @@
int[][] intArrayStack;
int intArrayPtr;
- CompilerOptions options;
-
public DocumentElementParser(
final IDocumentElementRequestor requestor,
IProblemFactory problemFactory,
@@ -63,6 +47,9 @@
intArrayStack = new int[30][];
this.options = options;
this.javadocParser.checkDocComment = false;
+
+ this.setMethodsFullRecovery(false);
+ this.setStatementsRecovery(false);
}
/*
* Will clear the comment stack when looking
@@ -95,7 +82,7 @@
break nextComment;
}
if (deprecated) {
- checkAndSetModifiers(AccDeprecated);
+ checkAndSetModifiers(ClassFileConstants.AccDeprecated);
}
// modify the modifier source start to point at the first comment
if (commentPtr >= 0) {
@@ -210,11 +197,11 @@
TypeDeclaration typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
if (nestedMethod[nestedType] == 0) {
if (nestedType != 0) {
- typeDecl.bits |= ASTNode.IsMemberTypeMASK;
+ typeDecl.bits |= ASTNode.IsMemberType;
}
} else {
// Record that the block has a declaration for local types
- typeDecl.bits |= ASTNode.IsLocalTypeMASK;
+ typeDecl.bits |= ASTNode.IsLocalType;
markEnclosingMemberWithLocalType();
blockReal();
}
@@ -474,6 +461,11 @@
declaration.declarationSourceStart = previousVariable.declarationSourceStart;
declaration.modifiers = previousVariable.modifiers;
declaration.modifiersSourceStart = previousVariable.modifiersSourceStart;
+ final Annotation[] annotations = previousVariable.annotations;
+ if (annotations != null) {
+ final int annotationsLength = annotations.length;
+ System.arraycopy(annotations, 0, declaration.annotations = new Annotation[annotationsLength], 0, annotationsLength);
+ }
}
localIntPtr = intPtr;
@@ -663,11 +655,11 @@
TypeDeclaration typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
if (nestedMethod[nestedType] == 0) {
if (nestedType != 0) {
- typeDecl.bits |= ASTNode.IsMemberTypeMASK;
+ typeDecl.bits |= ASTNode.IsMemberType;
}
} else {
// Record that the block has a declaration for local types
- typeDecl.bits |= ASTNode.IsLocalTypeMASK;
+ typeDecl.bits |= ASTNode.IsLocalType;
markEnclosingMemberWithLocalType();
blockReal();
}
@@ -685,7 +677,7 @@
intPtr--;
int declSourceStart = intStack[intPtr--];
typeDecl.modifiersSourceStart = intStack[intPtr--];
- typeDecl.modifiers = this.intStack[this.intPtr--] | AccInterface;
+ typeDecl.modifiers = this.intStack[this.intPtr--] | ClassFileConstants.AccInterface;
if (typeDecl.declarationSourceStart > declSourceStart) {
typeDecl.declarationSourceStart = declSourceStart;
}
@@ -975,7 +967,7 @@
CharOperation.concatWith(importReference.getImportName(), '.'),
importReference.sourceStart,
false,
- AccStatic);
+ ClassFileConstants.AccStatic);
}
/*
*
@@ -996,7 +988,7 @@
CharOperation.concatWith(importReference.getImportName(), '.'),
importReference.sourceStart,
false,
- AccDefault);
+ ClassFileConstants.AccDefault);
}
protected void consumeStaticImportOnDemandDeclarationName() {
// SingleTypeImportDeclarationName ::= 'import' 'static' Name '.' '*'
@@ -1013,7 +1005,7 @@
CharOperation.concatWith(importReference.getImportName(), '.'),
importReference.sourceStart,
true,
- AccStatic);
+ ClassFileConstants.AccStatic);
}
/*
*
@@ -1029,7 +1021,7 @@
initializer.declarationSourceStart,
initializer.declarationSourceEnd,
intArrayStack[intArrayPtr--],
- AccStatic,
+ ClassFileConstants.AccStatic,
intStack[intPtr--],
initializer.block.sourceStart,
initializer.declarationSourceEnd);
@@ -1064,7 +1056,7 @@
CharOperation.concatWith(importReference.getImportName(), '.'),
importReference.sourceStart,
true,
- AccDefault);
+ ClassFileConstants.AccDefault);
}
/*
* Flush javadocs defined prior to a given positions.
@@ -1089,7 +1081,12 @@
}
return super.endParse(act);
}
-
+public void initialize(boolean initializeNLS) {
+ //positionning the parser for a new compilation unit
+ //avoiding stack reallocation and all that....
+ super.initialize(initializeNLS);
+ intArrayPtr = -1;
+}
public void initialize() {
//positionning the parser for a new compilation unit
//avoiding stack reallocation and all that....
@@ -1120,15 +1117,14 @@
public void parseCompilationUnit(ICompilationUnit unit) {
char[] regionSource = unit.getContents();
try {
- initialize();
+ initialize(true);
goForCompilationUnit();
referenceContext =
compilationUnit =
- compilationUnit =
- new CompilationUnitDeclaration(
- problemReporter(),
- new CompilationResult(unit, 0, 0, this.options.maxProblemsPerUnit),
- regionSource.length);
+ new CompilationUnitDeclaration(
+ problemReporter(),
+ new CompilationResult(unit, 0, 0, this.options.maxProblemsPerUnit),
+ regionSource.length);
scanner.resetTo(0, regionSource.length);
scanner.setSource(regionSource);
parse();
@@ -1145,11 +1141,10 @@
goForClassBodyDeclarations();
referenceContext =
compilationUnit =
- compilationUnit =
- new CompilationUnitDeclaration(
- problemReporter(),
- new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit),
- regionSource.length);
+ new CompilationUnitDeclaration(
+ problemReporter(),
+ new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit),
+ regionSource.length);
scanner.resetTo(0, regionSource.length);
scanner.setSource(regionSource);
parse();
@@ -1166,11 +1161,10 @@
goForFieldDeclaration();
referenceContext =
compilationUnit =
- compilationUnit =
- new CompilationUnitDeclaration(
- problemReporter(),
- new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit),
- regionSource.length);
+ new CompilationUnitDeclaration(
+ problemReporter(),
+ new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit),
+ regionSource.length);
scanner.resetTo(0, regionSource.length);
scanner.setSource(regionSource);
parse();
@@ -1188,11 +1182,10 @@
goForImportDeclaration();
referenceContext =
compilationUnit =
- compilationUnit =
- new CompilationUnitDeclaration(
- problemReporter(),
- new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit),
- regionSource.length);
+ new CompilationUnitDeclaration(
+ problemReporter(),
+ new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit),
+ regionSource.length);
scanner.resetTo(0, regionSource.length);
scanner.setSource(regionSource);
parse();
@@ -1213,11 +1206,10 @@
goForInitializer();
referenceContext =
compilationUnit =
- compilationUnit =
- new CompilationUnitDeclaration(
- problemReporter(),
- new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit),
- regionSource.length);
+ new CompilationUnitDeclaration(
+ problemReporter(),
+ new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit),
+ regionSource.length);
scanner.resetTo(0, regionSource.length);
scanner.setSource(regionSource);
parse();
@@ -1235,18 +1227,16 @@
goForGenericMethodDeclaration();
referenceContext =
compilationUnit =
- compilationUnit =
- new CompilationUnitDeclaration(
- problemReporter(),
- new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit),
- regionSource.length);
+ new CompilationUnitDeclaration(
+ problemReporter(),
+ new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit),
+ regionSource.length);
scanner.resetTo(0, regionSource.length);
scanner.setSource(regionSource);
parse();
} catch (AbortCompilation ex) {
// ignore this exception
}
-
}
/*
* Investigate one package statement declaration.
@@ -1257,11 +1247,10 @@
goForPackageDeclaration();
referenceContext =
compilationUnit =
- compilationUnit =
- new CompilationUnitDeclaration(
- problemReporter(),
- new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit),
- regionSource.length);
+ new CompilationUnitDeclaration(
+ problemReporter(),
+ new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit),
+ regionSource.length);
scanner.resetTo(0, regionSource.length);
scanner.setSource(regionSource);
parse();
@@ -1279,11 +1268,10 @@
goForTypeDeclaration();
referenceContext =
compilationUnit =
- compilationUnit =
- new CompilationUnitDeclaration(
- problemReporter(),
- new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit),
- regionSource.length);
+ new CompilationUnitDeclaration(
+ problemReporter(),
+ new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit),
+ regionSource.length);
scanner.resetTo(0, regionSource.length);
scanner.setSource(regionSource);
parse();
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/IDocumentElementRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/IDocumentElementRequestor.java
index de28a29..cb16a7d 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/IDocumentElementRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/IDocumentElementRequestor.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,7 +10,7 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler;
-import org.eclipse.jdt.core.compiler.IProblem;
+import org.eclipse.jdt.core.compiler.CategorizedProblem;
/**
* Part of the source element parser responsible for building the output.
@@ -121,7 +121,7 @@
/**
* @param problem - Used to report a problem while running the JDOM
*/
-void acceptProblem(IProblem problem);
+void acceptProblem(CategorizedProblem problem);
/**
* @param declarationStart - a source position corresponding to the start
* of this class.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/ISourceElementRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/ISourceElementRequestor.java
index 253a680..21ecce6 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/ISourceElementRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/ISourceElementRequestor.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,7 +10,7 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler;
-import org.eclipse.jdt.core.compiler.IProblem;
+import org.eclipse.jdt.core.compiler.CategorizedProblem;
/*
* Part of the source element parser responsible for building the output. It
@@ -39,7 +39,6 @@
public interface ISourceElementRequestor {
public static class TypeInfo {
- public int kind;
public int declarationStart;
public int modifiers;
public char[] name;
@@ -49,6 +48,9 @@
public char[][] superinterfaces;
public TypeParameterInfo[] typeParameters;
public long[] annotationPositions;
+ public char[][] categories;
+ public boolean secondary;
+ public boolean anonymousMember;
}
public static class TypeParameterInfo {
@@ -75,6 +77,7 @@
public char[][] exceptionTypes;
public TypeParameterInfo[] typeParameters;
public long[] annotationPositions;
+ public char[][] categories;
}
public static class FieldInfo {
@@ -85,6 +88,7 @@
public int nameSourceStart;
public int nameSourceEnd;
public long[] annotationPositions;
+ public char[][] categories;
}
void acceptConstructorReference(char[] typeName, int argCount, int sourcePosition);
@@ -97,16 +101,15 @@
* @param declarationEnd
* This is the position of the ';' ending the import statement or
* the end of the comment following the import.
- * @param name
- * This is the name of the import like specified in the source
- * including the dots. The '.*' is never included in the name.
+ * @param tokens
+ * This are the tokens of the import like specified in the source.
* @param onDemand
* set to true if the import is an import on demand (e.g. import
* java.io.*). False otherwise.
* @param modifiers
* can be set to static from 1.5 on.
*/
- void acceptImport(int declarationStart, int declarationEnd, char[] name, boolean onDemand, int modifiers);
+ void acceptImport(int declarationStart, int declarationEnd, char[][] tokens, boolean onDemand, int modifiers);
/*
* Table of line separator position. This table is passed once at the end of
@@ -121,7 +124,7 @@
void acceptPackage(int declarationStart, int declarationEnd, char[] name);
- void acceptProblem(IProblem problem);
+ void acceptProblem(CategorizedProblem problem);
void acceptTypeReference(char[][] typeName, int sourceStart, int sourceEnd);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementParser.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementParser.java
index 79b2023..b8ee845 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementParser.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementParser.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -11,7 +11,9 @@
package org.eclipse.jdt.internal.compiler;
import java.util.ArrayList;
+import java.util.HashMap;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.env.*;
import org.eclipse.jdt.internal.compiler.impl.*;
import org.eclipse.jdt.core.compiler.*;
@@ -42,18 +44,17 @@
*/
public class SourceElementParser extends CommentRecorderParser {
- ISourceElementRequestor requestor;
- int fieldCount;
+ public ISourceElementRequestor requestor;
ISourceType sourceType;
boolean reportReferenceInfo;
char[][] typeNames;
char[][] superTypeNames;
int nestedTypeIndex;
- NameReference[] unknownRefs;
- int unknownRefsCounter;
LocalDeclarationVisitor localDeclarationVisitor = null;
CompilerOptions options;
HashtableOfObjectToInt sourceEnds = new HashtableOfObjectToInt();
+ HashMap nodesToCategories = new HashMap(); // a map from ASTNode to char[][]
+ boolean useSourceJavadocParser = true;
/**
* An ast visitor that visits local type declarations.
@@ -91,18 +92,35 @@
CompilerOptions options,
boolean reportLocalDeclarations,
boolean optimizeStringLiterals) {
+ this(requestor, problemFactory, options, reportLocalDeclarations, optimizeStringLiterals, true/* use SourceJavadocParser */);
+}
+
+public SourceElementParser(
+ ISourceElementRequestor requestor,
+ IProblemFactory problemFactory,
+ CompilerOptions options,
+ boolean reportLocalDeclarations,
+ boolean optimizeStringLiterals,
+ boolean useSourceJavadocParser) {
+
+ super(
+ new ProblemReporter(
+ DefaultErrorHandlingPolicies.exitAfterAllProblems(),
+ options,
+ problemFactory),
+ optimizeStringLiterals);
+
// we want to notify all syntax error with the acceptProblem API
// To do so, we define the record method of the ProblemReporter
- super(new ProblemReporter(
+ this.problemReporter = new ProblemReporter(
DefaultErrorHandlingPolicies.exitAfterAllProblems(),
options,
problemFactory) {
- public void record(IProblem problem, CompilationResult unitResult, ReferenceContext context) {
+ public void record(CategorizedProblem problem, CompilationResult unitResult, ReferenceContext context) {
unitResult.record(problem, context); // TODO (jerome) clients are trapping problems either through factory or requestor... is result storing needed?
- requestor.acceptProblem(problem);
+ SourceElementParser.this.requestor.acceptProblem(problem);
}
- },
- optimizeStringLiterals);
+ };
this.requestor = requestor;
typeNames = new char[4][];
superTypeNames = new char[4][];
@@ -111,8 +129,35 @@
if (reportLocalDeclarations) {
this.localDeclarationVisitor = new LocalDeclarationVisitor();
}
+ // set specific javadoc parser
+ this.useSourceJavadocParser = useSourceJavadocParser;
+ if (useSourceJavadocParser) {
+ this.javadocParser = new SourceJavadocParser(this);
+ }
}
-
+private void acceptJavadocTypeReference(Expression expression) {
+ if (expression instanceof JavadocSingleTypeReference) {
+ JavadocSingleTypeReference singleRef = (JavadocSingleTypeReference) expression;
+ this.requestor.acceptTypeReference(singleRef.token, singleRef.sourceStart);
+ } else if (expression instanceof JavadocQualifiedTypeReference) {
+ JavadocQualifiedTypeReference qualifiedRef = (JavadocQualifiedTypeReference) expression;
+ this.requestor.acceptTypeReference(qualifiedRef.tokens, qualifiedRef.sourceStart, qualifiedRef.sourceEnd);
+ }
+}
+public void addUnknownRef(NameReference nameRef) {
+ // Note that:
+ // - the only requestor interested in references is the SourceIndexerRequestor
+ // - a name reference can become a type reference only during the cast case, it is then tagged later with the Binding.TYPE bit
+ // However since the indexer doesn't make the distinction between name reference and type reference, there is no need
+ // to report a type reference in the SourceElementParser.
+ // This gained 3.7% in the indexing performance test.
+ if (nameRef instanceof SingleNameReference) {
+ requestor.acceptUnknownReference(((SingleNameReference) nameRef).token, nameRef.sourceStart);
+ } else {
+ //QualifiedNameReference
+ requestor.acceptUnknownReference(((QualifiedNameReference) nameRef).tokens, nameRef.sourceStart, nameRef.sourceEnd);
+ }
+}
public void checkComment() {
// discard obsolete comments while inside methods or fields initializer (see bug 74369)
if (!(this.diet && this.dietInt==0) && this.scanner.commentPtr >= 0) {
@@ -136,7 +181,7 @@
// do not report problem before last parsed comment while recovering code...
this.javadocParser.reportProblems = this.currentElement == null || commentEnd > this.lastJavadocEnd;
if (this.javadocParser.checkDeprecation(lastComment)) {
- checkAndSetModifiers(AccDeprecated);
+ checkAndSetModifiers(ClassFileConstants.AccDeprecated);
}
this.javadoc = this.javadocParser.docComment; // null if check javadoc is not activated
if (currentElement == null) this.lastJavadocEnd = commentEnd;
@@ -146,61 +191,54 @@
if (this.reportReferenceInfo && this.javadocParser.checkDocComment && this.javadoc != null) {
// Report reference info in javadoc comment @throws/@exception tags
TypeReference[] thrownExceptions = this.javadoc.exceptionReferences;
- int throwsTagsNbre = thrownExceptions == null ? 0 : thrownExceptions.length;
- for (int i = 0; i < throwsTagsNbre; i++) {
- TypeReference typeRef = thrownExceptions[i];
- if (typeRef instanceof JavadocSingleTypeReference) {
- JavadocSingleTypeReference singleRef = (JavadocSingleTypeReference) typeRef;
- this.requestor.acceptTypeReference(singleRef.token, singleRef.sourceStart);
- } else if (typeRef instanceof JavadocQualifiedTypeReference) {
- JavadocQualifiedTypeReference qualifiedRef = (JavadocQualifiedTypeReference) typeRef;
- this.requestor.acceptTypeReference(qualifiedRef.tokens, qualifiedRef.sourceStart, qualifiedRef.sourceEnd);
+ if (thrownExceptions != null) {
+ for (int i = 0, max=thrownExceptions.length; i < max; i++) {
+ TypeReference typeRef = thrownExceptions[i];
+ if (typeRef instanceof JavadocSingleTypeReference) {
+ JavadocSingleTypeReference singleRef = (JavadocSingleTypeReference) typeRef;
+ this.requestor.acceptTypeReference(singleRef.token, singleRef.sourceStart);
+ } else if (typeRef instanceof JavadocQualifiedTypeReference) {
+ JavadocQualifiedTypeReference qualifiedRef = (JavadocQualifiedTypeReference) typeRef;
+ this.requestor.acceptTypeReference(qualifiedRef.tokens, qualifiedRef.sourceStart, qualifiedRef.sourceEnd);
+ }
}
}
// Report reference info in javadoc comment @see tags
Expression[] references = this.javadoc.seeReferences;
- int seeTagsNbre = references == null ? 0 : references.length;
- for (int i = 0; i < seeTagsNbre; i++) {
- Expression reference = references[i];
- acceptJavadocTypeReference(reference);
- if (reference instanceof JavadocFieldReference) {
- JavadocFieldReference fieldRef = (JavadocFieldReference) reference;
- this.requestor.acceptFieldReference(fieldRef.token, fieldRef.sourceStart);
- if (fieldRef.receiver != null && !fieldRef.receiver.isThis()) {
- acceptJavadocTypeReference(fieldRef.receiver);
- }
- } else if (reference instanceof JavadocMessageSend) {
- JavadocMessageSend messageSend = (JavadocMessageSend) reference;
- int argCount = messageSend.arguments == null ? 0 : messageSend.arguments.length;
- this.requestor.acceptMethodReference(messageSend.selector, argCount, messageSend.sourceStart);
- this.requestor.acceptConstructorReference(messageSend.selector, argCount, messageSend.sourceStart);
- if (messageSend.receiver != null && !messageSend.receiver.isThis()) {
- acceptJavadocTypeReference(messageSend.receiver);
- }
- } else if (reference instanceof JavadocAllocationExpression) {
- JavadocAllocationExpression constructor = (JavadocAllocationExpression) reference;
- int argCount = constructor.arguments == null ? 0 : constructor.arguments.length;
- if (constructor.type != null) {
- char[][] compoundName = constructor.type.getParameterizedTypeName();
- this.requestor.acceptConstructorReference(compoundName[compoundName.length-1], argCount, constructor.sourceStart);
- if (!constructor.type.isThis()) {
- acceptJavadocTypeReference(constructor.type);
+ if (references != null) {
+ for (int i = 0, max=references.length; i < max; i++) {
+ Expression reference = references[i];
+ acceptJavadocTypeReference(reference);
+ if (reference instanceof JavadocFieldReference) {
+ JavadocFieldReference fieldRef = (JavadocFieldReference) reference;
+ this.requestor.acceptFieldReference(fieldRef.token, fieldRef.sourceStart);
+ if (fieldRef.receiver != null && !fieldRef.receiver.isThis()) {
+ acceptJavadocTypeReference(fieldRef.receiver);
+ }
+ } else if (reference instanceof JavadocMessageSend) {
+ JavadocMessageSend messageSend = (JavadocMessageSend) reference;
+ int argCount = messageSend.arguments == null ? 0 : messageSend.arguments.length;
+ this.requestor.acceptMethodReference(messageSend.selector, argCount, messageSend.sourceStart);
+ this.requestor.acceptConstructorReference(messageSend.selector, argCount, messageSend.sourceStart);
+ if (messageSend.receiver != null && !messageSend.receiver.isThis()) {
+ acceptJavadocTypeReference(messageSend.receiver);
+ }
+ } else if (reference instanceof JavadocAllocationExpression) {
+ JavadocAllocationExpression constructor = (JavadocAllocationExpression) reference;
+ int argCount = constructor.arguments == null ? 0 : constructor.arguments.length;
+ if (constructor.type != null) {
+ char[][] compoundName = constructor.type.getParameterizedTypeName();
+ this.requestor.acceptConstructorReference(compoundName[compoundName.length-1], argCount, constructor.sourceStart);
+ if (!constructor.type.isThis()) {
+ acceptJavadocTypeReference(constructor.type);
+ }
}
}
}
}
}
}
-private void acceptJavadocTypeReference(Expression expression) {
- if (expression instanceof JavadocSingleTypeReference) {
- JavadocSingleTypeReference singleRef = (JavadocSingleTypeReference) expression;
- this.requestor.acceptTypeReference(singleRef.token, singleRef.sourceStart);
- } else if (expression instanceof JavadocQualifiedTypeReference) {
- JavadocQualifiedTypeReference qualifiedRef = (JavadocQualifiedTypeReference) expression;
- this.requestor.acceptTypeReference(qualifiedRef.tokens, qualifiedRef.sourceStart, qualifiedRef.sourceEnd);
- }
-}
protected void classInstanceCreation(boolean alwaysQualified) {
boolean previousFlag = reportReferenceInfo;
@@ -251,6 +289,18 @@
alloc.sourceStart);
}
}
+protected void consumeAnnotationTypeDeclarationHeaderName() {
+ int currentAstPtr = this.astPtr;
+ super.consumeAnnotationTypeDeclarationHeaderName();
+ if (this.astPtr > currentAstPtr) // if ast node was pushed on the ast stack
+ rememberCategories();
+}
+protected void consumeClassHeaderName1() {
+ int currentAstPtr = this.astPtr;
+ super.consumeClassHeaderName1();
+ if (this.astPtr > currentAstPtr) // if ast node was pushed on the ast stack
+ rememberCategories();
+}
protected void consumeClassInstanceCreationExpressionWithTypeArguments() {
boolean previousFlag = reportReferenceInfo;
reportReferenceInfo = false; // not to see the type reference reported in super call to getTypeReference(...)
@@ -272,22 +322,27 @@
int selectorSourceEnd = (int) selectorSourcePositions;
int currentAstPtr = this.astPtr;
super.consumeConstructorHeaderName();
- if (this.astPtr > currentAstPtr) // if ast node was pushed on the ast stack
+ if (this.astPtr > currentAstPtr) { // if ast node was pushed on the ast stack
this.sourceEnds.put(this.astStack[this.astPtr], selectorSourceEnd);
+ rememberCategories();
+ }
}
protected void consumeConstructorHeaderNameWithTypeParameters() {
long selectorSourcePositions = this.identifierPositionStack[this.identifierPtr];
int selectorSourceEnd = (int) selectorSourcePositions;
int currentAstPtr = this.astPtr;
super.consumeConstructorHeaderNameWithTypeParameters();
- if (this.astPtr > currentAstPtr) // if ast node was pushed on the ast stack
+ if (this.astPtr > currentAstPtr) { // if ast node was pushed on the ast stack
this.sourceEnds.put(this.astStack[this.astPtr], selectorSourceEnd);
+ rememberCategories();
+ }
}
protected void consumeEnumConstantWithClassBody() {
super.consumeEnumConstantWithClassBody();
if ((currentToken == TokenNameCOMMA || currentToken == TokenNameSEMICOLON)
&& astStack[astPtr] instanceof FieldDeclaration) {
this.sourceEnds.put(this.astStack[this.astPtr], this.scanner.currentPosition - 1);
+ rememberCategories();
}
}
protected void consumeEnumConstantNoClassBody() {
@@ -295,8 +350,15 @@
if ((currentToken == TokenNameCOMMA || currentToken == TokenNameSEMICOLON)
&& this.astStack[this.astPtr] instanceof FieldDeclaration) {
this.sourceEnds.put(this.astStack[this.astPtr], this.scanner.currentPosition - 1);
+ rememberCategories();
}
}
+protected void consumeEnumHeaderName() {
+ int currentAstPtr = this.astPtr;
+ super.consumeEnumHeaderName();
+ if (this.astPtr > currentAstPtr) // if ast node was pushed on the ast stack
+ rememberCategories();
+}
protected void consumeExitVariableWithInitialization() {
// ExitVariableWithInitialization ::= $empty
// the scanner is located after the comma or the semi-colon.
@@ -305,6 +367,7 @@
if ((currentToken == TokenNameCOMMA || currentToken == TokenNameSEMICOLON)
&& this.astStack[this.astPtr] instanceof FieldDeclaration) {
this.sourceEnds.put(this.astStack[this.astPtr], this.scanner.currentPosition - 1);
+ rememberCategories();
}
}
protected void consumeExitVariableWithoutInitialization() {
@@ -314,6 +377,7 @@
if ((currentToken == TokenNameCOMMA || currentToken == TokenNameSEMICOLON)
&& astStack[astPtr] instanceof FieldDeclaration) {
this.sourceEnds.put(this.astStack[this.astPtr], this.scanner.currentPosition - 1);
+ rememberCategories();
}
}
/*
@@ -329,6 +393,21 @@
requestor.acceptFieldReference(fr.token, fr.sourceStart);
}
}
+protected void consumeFormalParameter(boolean isVarArgs) {
+ super.consumeFormalParameter(isVarArgs);
+
+ // Flush comments prior to this formal parameter so the declarationSourceStart of the following parameter
+ // is correctly set (see bug 80904)
+ // Note that this could be done in the Parser itself, but this would slow down all parsers, when they don't need
+ // the declarationSourceStart to be set
+ flushCommentsDefinedPriorTo(this.scanner.currentPosition);
+}
+protected void consumeInterfaceHeaderName1() {
+ int currentAstPtr = this.astPtr;
+ super.consumeInterfaceHeaderName1();
+ if (this.astPtr > currentAstPtr) // if ast node was pushed on the ast stack
+ rememberCategories();
+}
protected void consumeMemberValuePair() {
super.consumeMemberValuePair();
MemberValuePair memberValuepair = (MemberValuePair) this.astStack[this.astPtr];
@@ -348,9 +427,12 @@
int selectorSourceEnd = (int) selectorSourcePositions;
int currentAstPtr = this.astPtr;
super.consumeMethodHeaderName(isAnnotationMethod);
- if (this.astPtr > currentAstPtr) // if ast node was pushed on the ast stack
+ if (this.astPtr > currentAstPtr) { // if ast node was pushed on the ast stack
this.sourceEnds.put(this.astStack[this.astPtr], selectorSourceEnd);
+ rememberCategories();
+ }
}
+
protected void consumeMethodHeaderNameWithTypeParameters(boolean isAnnotationMethod) {
long selectorSourcePositions = this.identifierPositionStack[this.identifierPtr];
int selectorSourceEnd = (int) selectorSourcePositions;
@@ -358,6 +440,7 @@
super.consumeMethodHeaderNameWithTypeParameters(isAnnotationMethod);
if (this.astPtr > currentAstPtr) // if ast node was pushed on the ast stack
this.sourceEnds.put(this.astStack[this.astPtr], selectorSourceEnd);
+ rememberCategories();
}
/*
*
@@ -465,35 +548,92 @@
}
protected void consumeSingleStaticImportDeclarationName() {
// SingleTypeImportDeclarationName ::= 'import' 'static' Name
- super.consumeSingleStaticImportDeclarationName();
- ImportReference impt = (ImportReference)astStack[astPtr];
+ ImportReference impt;
+ int length;
+ char[][] tokens = new char[length = this.identifierLengthStack[this.identifierLengthPtr--]][];
+ this.identifierPtr -= length;
+ long[] positions = new long[length];
+ System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
+ System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, 0, length);
+ pushOnAstStack(impt = newImportReference(tokens, positions, false, ClassFileConstants.AccStatic));
+
+ this.modifiers = ClassFileConstants.AccDefault;
+ this.modifiersSourceStart = -1; // <-- see comment into modifiersFlag(int)
+
+ if (this.currentToken == TokenNameSEMICOLON){
+ impt.declarationSourceEnd = this.scanner.currentPosition - 1;
+ } else {
+ impt.declarationSourceEnd = impt.sourceEnd;
+ }
+ impt.declarationEnd = impt.declarationSourceEnd;
+ //this.endPosition is just before the ;
+ impt.declarationSourceStart = this.intStack[this.intPtr--];
+
+ if(!this.statementRecoveryActivated &&
+ this.options.sourceLevel < ClassFileConstants.JDK1_5 &&
+ this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
+ impt.modifiers = ClassFileConstants.AccDefault; // convert the static import reference to a non-static importe reference
+ this.problemReporter().invalidUsageOfStaticImports(impt);
+ }
+
+ // recovery
+ if (this.currentElement != null){
+ this.lastCheckPoint = impt.declarationSourceEnd+1;
+ this.currentElement = this.currentElement.add(impt, 0);
+ this.lastIgnoredToken = -1;
+ this.restartRecovery = true; // used to avoid branching back into the regular automaton
+ }
if (reportReferenceInfo) {
// Name for static import is TypeName '.' Identifier
// => accept unknown ref on identifier
- int length = impt.tokens.length-1;
- int start = (int) (impt.sourcePositions[length] >>> 32);
- char[] last = impt.tokens[length];
+ int tokensLength = impt.tokens.length-1;
+ int start = (int) (impt.sourcePositions[tokensLength] >>> 32);
+ char[] last = impt.tokens[tokensLength];
// accept all possible kind for last name, index users will have to select the right one...
// see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=86901
requestor.acceptFieldReference(last, start);
requestor.acceptMethodReference(last, 0,start);
requestor.acceptTypeReference(last, start);
// accept type name
- if (length > 0) {
- char[][] compoundName = new char[length][];
- System.arraycopy(impt.tokens, 0, compoundName, 0, length);
- int end = (int) impt.sourcePositions[length-1];
+ if (tokensLength > 0) {
+ char[][] compoundName = new char[tokensLength][];
+ System.arraycopy(impt.tokens, 0, compoundName, 0, tokensLength);
+ int end = (int) impt.sourcePositions[tokensLength-1];
requestor.acceptTypeReference(compoundName, impt.sourceStart, end);
}
}
}
+
protected void consumeSingleTypeImportDeclarationName() {
// SingleTypeImportDeclarationName ::= 'import' Name
/* push an ImportRef build from the last name
stored in the identifier stack. */
- super.consumeSingleTypeImportDeclarationName();
- ImportReference impt = (ImportReference)astStack[astPtr];
+ ImportReference impt;
+ int length;
+ char[][] tokens = new char[length = this.identifierLengthStack[this.identifierLengthPtr--]][];
+ this.identifierPtr -= length;
+ long[] positions = new long[length];
+ System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
+ System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, 0, length);
+ pushOnAstStack(impt = newImportReference(tokens, positions, false, ClassFileConstants.AccDefault));
+
+ if (this.currentToken == TokenNameSEMICOLON){
+ impt.declarationSourceEnd = this.scanner.currentPosition - 1;
+ } else {
+ impt.declarationSourceEnd = impt.sourceEnd;
+ }
+ impt.declarationEnd = impt.declarationSourceEnd;
+ //this.endPosition is just before the ;
+ impt.declarationSourceStart = this.intStack[this.intPtr--];
+
+ // recovery
+ if (this.currentElement != null){
+ this.lastCheckPoint = impt.declarationSourceEnd+1;
+ this.currentElement = this.currentElement.add(impt, 0);
+ this.lastIgnoredToken = -1;
+ this.restartRecovery = true; // used to avoid branching back into the regular automaton
+ }
if (reportReferenceInfo) {
requestor.acceptTypeReference(impt.tokens, impt.sourceStart, impt.sourceEnd);
}
@@ -503,8 +643,41 @@
/* push an ImportRef build from the last name
stored in the identifier stack. */
- super.consumeStaticImportOnDemandDeclarationName();
- ImportReference impt = (ImportReference)astStack[astPtr];
+ ImportReference impt;
+ int length;
+ char[][] tokens = new char[length = this.identifierLengthStack[this.identifierLengthPtr--]][];
+ this.identifierPtr -= length;
+ long[] positions = new long[length];
+ System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
+ System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, 0, length);
+ pushOnAstStack(impt = new ImportReference(tokens, positions, true, ClassFileConstants.AccStatic));
+
+ this.modifiers = ClassFileConstants.AccDefault;
+ this.modifiersSourceStart = -1; // <-- see comment into modifiersFlag(int)
+
+ if (this.currentToken == TokenNameSEMICOLON){
+ impt.declarationSourceEnd = this.scanner.currentPosition - 1;
+ } else {
+ impt.declarationSourceEnd = impt.sourceEnd;
+ }
+ impt.declarationEnd = impt.declarationSourceEnd;
+ //this.endPosition is just before the ;
+ impt.declarationSourceStart = this.intStack[this.intPtr--];
+
+ if(!this.statementRecoveryActivated &&
+ options.sourceLevel < ClassFileConstants.JDK1_5 &&
+ this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
+ impt.modifiers = ClassFileConstants.AccDefault; // convert the static import reference to a non-static importe reference
+ this.problemReporter().invalidUsageOfStaticImports(impt);
+ }
+
+ // recovery
+ if (this.currentElement != null){
+ this.lastCheckPoint = impt.declarationSourceEnd+1;
+ this.currentElement = this.currentElement.add(impt, 0);
+ this.lastIgnoredToken = -1;
+ this.restartRecovery = true; // used to avoid branching back into the regular automaton
+ }
if (reportReferenceInfo) {
requestor.acceptTypeReference(impt.tokens, impt.sourceStart, impt.sourceEnd);
}
@@ -514,8 +687,31 @@
/* push an ImportRef build from the last name
stored in the identifier stack. */
- super.consumeTypeImportOnDemandDeclarationName();
- ImportReference impt = (ImportReference)astStack[astPtr];
+ ImportReference impt;
+ int length;
+ char[][] tokens = new char[length = this.identifierLengthStack[this.identifierLengthPtr--]][];
+ this.identifierPtr -= length;
+ long[] positions = new long[length];
+ System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
+ System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, 0, length);
+ pushOnAstStack(impt = new ImportReference(tokens, positions, true, ClassFileConstants.AccDefault));
+
+ if (this.currentToken == TokenNameSEMICOLON){
+ impt.declarationSourceEnd = this.scanner.currentPosition - 1;
+ } else {
+ impt.declarationSourceEnd = impt.sourceEnd;
+ }
+ impt.declarationEnd = impt.declarationSourceEnd;
+ //this.endPosition is just before the ;
+ impt.declarationSourceStart = this.intStack[this.intPtr--];
+
+ // recovery
+ if (this.currentElement != null){
+ this.lastCheckPoint = impt.declarationSourceEnd+1;
+ this.currentElement = this.currentElement.add(impt, 0);
+ this.lastIgnoredToken = -1;
+ this.restartRecovery = true; // used to avoid branching back into the regular automaton
+ }
if (reportReferenceInfo) {
requestor.acceptUnknownReference(impt.tokens, impt.sourceStart, impt.sourceEnd);
}
@@ -525,21 +721,25 @@
int selectorSourceEnd = this.sourceEnds.removeKey(c);
if (selectorSourceEnd != -1)
this.sourceEnds.put(methodDeclaration, selectorSourceEnd);
+ char[][] categories = (char[][]) this.nodesToCategories.remove(c);
+ if (categories != null)
+ this.nodesToCategories.put(methodDeclaration, categories);
+
return methodDeclaration;
}
protected CompilationUnitDeclaration endParse(int act) {
if (sourceType != null) {
- switch (sourceType.getKind()) {
- case IGenericType.CLASS_DECL :
+ switch (TypeDeclaration.kind(sourceType.getModifiers())) {
+ case TypeDeclaration.CLASS_DECL :
consumeClassDeclaration();
break;
- case IGenericType.INTERFACE_DECL :
+ case TypeDeclaration.INTERFACE_DECL :
consumeInterfaceDeclaration();
break;
- case IGenericType.ENUM_DECL :
+ case TypeDeclaration.ENUM_DECL :
consumeEnumDeclaration();
break;
- case IGenericType.ANNOTATION_TYPE_DECL :
+ case TypeDeclaration.ANNOTATION_TYPE_DECL :
consumeAnnotationTypeDeclaration();
break;
}
@@ -551,6 +751,42 @@
return null;
}
}
+private ISourceElementRequestor.TypeParameterInfo[] getTypeParameterInfos(TypeParameter[] typeParameters) {
+ if (typeParameters == null) return null;
+ int typeParametersLength = typeParameters.length;
+ ISourceElementRequestor.TypeParameterInfo[] result = new ISourceElementRequestor.TypeParameterInfo[typeParametersLength];
+ for (int i = 0; i < typeParametersLength; i++) {
+ TypeParameter typeParameter = typeParameters[i];
+ TypeReference firstBound = typeParameter.type;
+ TypeReference[] otherBounds = typeParameter.bounds;
+ char[][] typeParameterBounds = null;
+ if (firstBound != null) {
+ if (otherBounds != null) {
+ int otherBoundsLength = otherBounds.length;
+ char[][] boundNames = new char[otherBoundsLength+1][];
+ boundNames[0] = CharOperation.concatWith(firstBound.getParameterizedTypeName(), '.');
+ for (int j = 0; j < otherBoundsLength; j++) {
+ boundNames[j+1] =
+ CharOperation.concatWith(otherBounds[j].getParameterizedTypeName(), '.');
+ }
+ typeParameterBounds = boundNames;
+ } else {
+ typeParameterBounds = new char[][] { CharOperation.concatWith(firstBound.getParameterizedTypeName(), '.')};
+ }
+ } else {
+ typeParameterBounds = CharOperation.NO_CHAR_CHAR;
+ }
+ ISourceElementRequestor.TypeParameterInfo typeParameterInfo = new ISourceElementRequestor.TypeParameterInfo();
+ typeParameterInfo.declarationStart = typeParameter.declarationSourceStart;
+ typeParameterInfo.declarationEnd = typeParameter.declarationSourceEnd;
+ typeParameterInfo.name = typeParameter.name;
+ typeParameterInfo.nameSourceStart = typeParameter.sourceStart;
+ typeParameterInfo.nameSourceEnd = typeParameter.sourceEnd;
+ typeParameterInfo.bounds = typeParameterBounds;
+ result[i] = typeParameterInfo;
+ }
+ return result;
+}
public TypeReference getTypeReference(int dim) {
/* build a Reference on a variable that may be qualified or not
* This variable is a type reference and dim will be its dimensions
@@ -645,7 +881,7 @@
if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
// single variable reference
SingleNameReference ref =
- new SingleNameReference(
+ newSingleNameReference(
identifierStack[identifierPtr],
identifierPositionStack[identifierPtr--]);
if (reportReferenceInfo) {
@@ -660,7 +896,7 @@
long[] positions = new long[length];
System.arraycopy(identifierPositionStack, identifierPtr + 1, positions, 0, length);
QualifiedNameReference ref =
- new QualifiedNameReference(
+ newQualifiedNameReference(
tokens,
positions,
(int) (identifierPositionStack[identifierPtr + 1] >> 32), // sourceStart
@@ -683,7 +919,7 @@
if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
// single variable reference
SingleNameReference ref =
- new SingleNameReference(
+ newSingleNameReference(
identifierStack[identifierPtr],
identifierPositionStack[identifierPtr--]);
ref.bits &= ~ASTNode.RestrictiveFlagMASK;
@@ -706,7 +942,7 @@
long[] positions = new long[length];
System.arraycopy(identifierPositionStack, identifierPtr + 1, positions, 0, length);
QualifiedNameReference ref =
- new QualifiedNameReference(
+ newQualifiedNameReference(
tokens,
positions,
(int) (identifierPositionStack[identifierPtr + 1] >> 32),
@@ -719,6 +955,32 @@
}
return ref;
}
+
+/*
+ * Checks whether one of the annotations is the @Deprecated annotation
+ * (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=89807)
+ */
+private boolean hasDeprecatedAnnotation(Annotation[] annotations) {
+ if (annotations != null) {
+ for (int i = 0, length = annotations.length; i < length; i++) {
+ Annotation annotation = annotations[i];
+ if (CharOperation.equals(annotation.type.getLastToken(), TypeConstants.JAVA_LANG_DEPRECATED[2])) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+protected ImportReference newImportReference(char[][] tokens, long[] positions, boolean onDemand, int mod) {
+ return new ImportReference(tokens, positions, onDemand, mod);
+}
+protected QualifiedNameReference newQualifiedNameReference(char[][] tokens, long[] positions, int sourceStart, int sourceEnd) {
+ return new QualifiedNameReference(tokens, positions, sourceStart, sourceEnd);
+}
+protected SingleNameReference newSingleNameReference(char[] source, long positions) {
+ return new SingleNameReference(source, positions);
+}
/*
* Update the bodyStart of the corresponding parse node
*/
@@ -737,9 +999,6 @@
scanner.initialPosition <= parsedUnit.sourceStart
&& scanner.eofPosition >= parsedUnit.sourceEnd;
- if (reportReferenceInfo) {
- notifyAllUnknownReferences();
- }
// collect the top level ast nodes
int length = 0;
ASTNode[] nodes = null;
@@ -805,44 +1064,6 @@
}
}
-private void notifyAllUnknownReferences() {
- for (int i = 0, max = this.unknownRefsCounter; i < max; i++) {
- NameReference nameRef = this.unknownRefs[i];
- if ((nameRef.bits & Binding.VARIABLE) != 0) {
- if ((nameRef.bits & Binding.TYPE) == 0) {
- // variable but not type
- if (nameRef instanceof SingleNameReference) {
- // local var or field
- requestor.acceptUnknownReference(((SingleNameReference) nameRef).token, nameRef.sourceStart);
- } else {
- // QualifiedNameReference
- // The last token is a field reference and the previous tokens are a type/variable references
- char[][] tokens = ((QualifiedNameReference) nameRef).tokens;
- int tokensLength = tokens.length;
- requestor.acceptFieldReference(tokens[tokensLength - 1], nameRef.sourceEnd - tokens[tokensLength - 1].length + 1);
- char[][] typeRef = new char[tokensLength - 1][];
- System.arraycopy(tokens, 0, typeRef, 0, tokensLength - 1);
- requestor.acceptUnknownReference(typeRef, nameRef.sourceStart, nameRef.sourceEnd - tokens[tokensLength - 1].length);
- }
- } else {
- // variable or type
- if (nameRef instanceof SingleNameReference) {
- requestor.acceptUnknownReference(((SingleNameReference) nameRef).token, nameRef.sourceStart);
- } else {
- //QualifiedNameReference
- requestor.acceptUnknownReference(((QualifiedNameReference) nameRef).tokens, nameRef.sourceStart, nameRef.sourceEnd);
- }
- }
- } else if ((nameRef.bits & Binding.TYPE) != 0) {
- if (nameRef instanceof SingleNameReference) {
- requestor.acceptTypeReference(((SingleNameReference) nameRef).token, nameRef.sourceStart);
- } else {
- // it is a QualifiedNameReference
- requestor.acceptTypeReference(((QualifiedNameReference) nameRef).tokens, nameRef.sourceStart, nameRef.sourceEnd);
- }
- }
- }
-}
/*
* Update the bodyStart of the corresponding parse node
*/
@@ -913,12 +1134,15 @@
if (isInRange){
int currentModifiers = methodDeclaration.modifiers;
if (isVarArgs)
- currentModifiers |= AccVarargs;
- boolean deprecated = (currentModifiers & AccDeprecated) != 0; // remember deprecation so as to not lose it below
+ currentModifiers |= ClassFileConstants.AccVarargs;
+
+ // remember deprecation so as to not lose it below
+ boolean deprecated = (currentModifiers & ClassFileConstants.AccDeprecated) != 0 || hasDeprecatedAnnotation(methodDeclaration.annotations);
+
ISourceElementRequestor.MethodInfo methodInfo = new ISourceElementRequestor.MethodInfo();
methodInfo.isConstructor = true;
methodInfo.declarationStart = methodDeclaration.declarationSourceStart;
- methodInfo.modifiers = deprecated ? (currentModifiers & AccJustFlag) | AccDeprecated : currentModifiers & AccJustFlag;
+ methodInfo.modifiers = deprecated ? (currentModifiers & ExtraCompilerModifiers.AccJustFlag) | ClassFileConstants.AccDeprecated : currentModifiers & ExtraCompilerModifiers.AccJustFlag;
methodInfo.name = methodDeclaration.selector;
methodInfo.nameSourceStart = methodDeclaration.sourceStart;
methodInfo.nameSourceEnd = selectorSourceEnd;
@@ -927,6 +1151,7 @@
methodInfo.exceptionTypes = thrownExceptionTypes;
methodInfo.typeParameters = getTypeParameterInfos(methodDeclaration.typeParameters());
methodInfo.annotationPositions = collectAnnotationPositions(methodDeclaration.annotations);
+ methodInfo.categories = (char[][]) this.nodesToCategories.get(methodDeclaration);
requestor.enterConstructor(methodInfo);
}
if (reportReferenceInfo) {
@@ -960,15 +1185,18 @@
if (isInRange) {
int currentModifiers = methodDeclaration.modifiers;
if (isVarArgs)
- currentModifiers |= AccVarargs;
- boolean deprecated = (currentModifiers & AccDeprecated) != 0; // remember deprecation so as to not lose it below
+ currentModifiers |= ClassFileConstants.AccVarargs;
+
+ // remember deprecation so as to not lose it below
+ boolean deprecated = (currentModifiers & ClassFileConstants.AccDeprecated) != 0 || hasDeprecatedAnnotation(methodDeclaration.annotations);
+
TypeReference returnType = methodDeclaration instanceof MethodDeclaration
? ((MethodDeclaration) methodDeclaration).returnType
: null;
ISourceElementRequestor.MethodInfo methodInfo = new ISourceElementRequestor.MethodInfo();
methodInfo.isAnnotation = methodDeclaration instanceof AnnotationMethodDeclaration;
methodInfo.declarationStart = methodDeclaration.declarationSourceStart;
- methodInfo.modifiers = deprecated ? (currentModifiers & AccJustFlag) | AccDeprecated : currentModifiers & AccJustFlag;
+ methodInfo.modifiers = deprecated ? (currentModifiers & ExtraCompilerModifiers.AccJustFlag) | ClassFileConstants.AccDeprecated : currentModifiers & ExtraCompilerModifiers.AccJustFlag;
methodInfo.returnType = returnType == null ? null : CharOperation.concatWith(returnType.getParameterizedTypeName(), '.');
methodInfo.name = methodDeclaration.selector;
methodInfo.nameSourceStart = methodDeclaration.sourceStart;
@@ -978,6 +1206,7 @@
methodInfo.exceptionTypes = thrownExceptionTypes;
methodInfo.typeParameters = getTypeParameterInfos(methodDeclaration.typeParameters());
methodInfo.annotationPositions = collectAnnotationPositions(methodDeclaration.annotations);
+ methodInfo.categories = (char[][]) this.nodesToCategories.get(methodDeclaration);
requestor.enterMethod(methodInfo);
}
@@ -995,42 +1224,6 @@
requestor.exitMethod(methodDeclaration.declarationSourceEnd, -1, -1);
}
}
-private ISourceElementRequestor.TypeParameterInfo[] getTypeParameterInfos(TypeParameter[] typeParameters) {
- if (typeParameters == null) return null;
- int typeParametersLength = typeParameters.length;
- ISourceElementRequestor.TypeParameterInfo[] result = new ISourceElementRequestor.TypeParameterInfo[typeParametersLength];
- for (int i = 0; i < typeParametersLength; i++) {
- TypeParameter typeParameter = typeParameters[i];
- TypeReference firstBound = typeParameter.type;
- TypeReference[] otherBounds = typeParameter.bounds;
- char[][] typeParameterBounds = null;
- if (firstBound != null) {
- if (otherBounds != null) {
- int otherBoundsLength = otherBounds.length;
- char[][] boundNames = new char[otherBoundsLength+1][];
- boundNames[0] = CharOperation.concatWith(firstBound.getParameterizedTypeName(), '.');
- for (int j = 0; j < otherBoundsLength; j++) {
- boundNames[j+1] =
- CharOperation.concatWith(otherBounds[j].getParameterizedTypeName(), '.');
- }
- typeParameterBounds = boundNames;
- } else {
- typeParameterBounds = new char[][] { CharOperation.concatWith(firstBound.getParameterizedTypeName(), '.')};
- }
- } else {
- typeParameterBounds = CharOperation.NO_CHAR_CHAR;
- }
- ISourceElementRequestor.TypeParameterInfo typeParameterInfo = new ISourceElementRequestor.TypeParameterInfo();
- typeParameterInfo.declarationStart = typeParameter.declarationSourceStart;
- typeParameterInfo.declarationEnd = typeParameter.declarationSourceEnd;
- typeParameterInfo.name = typeParameter.name;
- typeParameterInfo.nameSourceStart = typeParameter.sourceStart;
- typeParameterInfo.nameSourceEnd = typeParameter.sourceEnd;
- typeParameterInfo.bounds = typeParameterBounds;
- result[i] = typeParameterInfo;
- }
- return result;
-}
/*
* Update the bodyStart of the corresponding parse node
@@ -1061,12 +1254,15 @@
}
if (isInRange) {
int currentModifiers = fieldDeclaration.modifiers;
- boolean deprecated = (currentModifiers & AccDeprecated) != 0; // remember deprecation so as to not lose it below
+
+ // remember deprecation so as to not lose it below
+ boolean deprecated = (currentModifiers & ClassFileConstants.AccDeprecated) != 0 || hasDeprecatedAnnotation(fieldDeclaration.annotations);
+
char[] typeName = null;
if (fieldDeclaration.type == null) {
// enum constant
typeName = declaringType.name;
- currentModifiers |= AccEnum;
+ currentModifiers |= ClassFileConstants.AccEnum;
} else {
// regular field
typeName = CharOperation.concatWith(fieldDeclaration.type.getParameterizedTypeName(), '.');
@@ -1074,11 +1270,12 @@
ISourceElementRequestor.FieldInfo fieldInfo = new ISourceElementRequestor.FieldInfo();
fieldInfo.declarationStart = fieldDeclaration.declarationSourceStart;
fieldInfo.name = fieldDeclaration.name;
- fieldInfo.modifiers = deprecated ? (currentModifiers & AccJustFlag) | AccDeprecated : currentModifiers & AccJustFlag;
+ fieldInfo.modifiers = deprecated ? (currentModifiers & ExtraCompilerModifiers.AccJustFlag) | ClassFileConstants.AccDeprecated : currentModifiers & ExtraCompilerModifiers.AccJustFlag;
fieldInfo.type = typeName;
fieldInfo.nameSourceStart = fieldDeclaration.sourceStart;
fieldInfo.nameSourceEnd = fieldDeclaration.sourceEnd;
fieldInfo.annotationPositions = collectAnnotationPositions(fieldDeclaration.annotations);
+ fieldInfo.categories = (char[][]) this.nodesToCategories.get(fieldDeclaration);
requestor.enterField(fieldInfo);
}
this.visitIfNeeded(fieldDeclaration, declaringType);
@@ -1125,15 +1322,15 @@
requestor.acceptImport(
importReference.declarationSourceStart,
importReference.declarationSourceEnd,
- CharOperation.concatWith(importReference.getImportName(), '.'),
- importReference.onDemand,
+ importReference.tokens,
+ (importReference.bits & ASTNode.OnDemand) != 0,
importReference.modifiers);
}
}
public void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boolean notifyTypePresence, TypeDeclaration declaringType) {
if (CharOperation.equals(TypeConstants.PACKAGE_INFO_NAME, typeDeclaration.name)) return;
-
+
// range check
boolean isInRange =
scanner.initialPosition <= typeDeclaration.declarationSourceStart
@@ -1157,7 +1354,7 @@
superInterfacesLength = superInterfaces.length;
interfaceNames = new char[superInterfacesLength][];
} else {
- if ((typeDeclaration.bits & ASTNode.IsAnonymousTypeMASK) != 0) {
+ if ((typeDeclaration.bits & ASTNode.IsAnonymousType) != 0) {
// see PR 3442
QualifiedAllocationExpression alloc = typeDeclaration.allocation;
if (alloc != null && alloc.type != null) {
@@ -1173,24 +1370,26 @@
CharOperation.concatWith(superInterfaces[i].getParameterizedTypeName(), '.');
}
}
- int kind = typeDeclaration.kind();
+ int kind = TypeDeclaration.kind(typeDeclaration.modifiers);
char[] implicitSuperclassName = TypeConstants.CharArray_JAVA_LANG_OBJECT;
if (isInRange) {
int currentModifiers = typeDeclaration.modifiers;
- boolean deprecated = (currentModifiers & AccDeprecated) != 0; // remember deprecation so as to not lose it below
+
+ // remember deprecation so as to not lose it below
+ boolean deprecated = (currentModifiers & ClassFileConstants.AccDeprecated) != 0 || hasDeprecatedAnnotation(typeDeclaration.annotations);
+
boolean isEnumInit = typeDeclaration.allocation != null && typeDeclaration.allocation.enumConstant != null;
char[] superclassName;
if (isEnumInit) {
- currentModifiers |= AccEnum;
+ currentModifiers |= ClassFileConstants.AccEnum;
superclassName = declaringType.name;
} else {
TypeReference superclass = typeDeclaration.superclass;
superclassName = superclass != null ? CharOperation.concatWith(superclass.getParameterizedTypeName(), '.') : null;
}
ISourceElementRequestor.TypeInfo typeInfo = new ISourceElementRequestor.TypeInfo();
- typeInfo.kind = kind;
typeInfo.declarationStart = typeDeclaration.declarationSourceStart;
- typeInfo.modifiers = deprecated ? (currentModifiers & AccJustFlag) | AccDeprecated : currentModifiers & AccJustFlag;
+ typeInfo.modifiers = deprecated ? (currentModifiers & ExtraCompilerModifiers.AccJustFlag) | ClassFileConstants.AccDeprecated : currentModifiers & ExtraCompilerModifiers.AccJustFlag;
typeInfo.name = typeDeclaration.name;
typeInfo.nameSourceStart = typeDeclaration.sourceStart;
typeInfo.nameSourceEnd = sourceEnd(typeDeclaration);
@@ -1198,19 +1397,22 @@
typeInfo.superinterfaces = interfaceNames;
typeInfo.typeParameters = getTypeParameterInfos(typeDeclaration.typeParameters);
typeInfo.annotationPositions = collectAnnotationPositions(typeDeclaration.annotations);
+ typeInfo.categories = (char[][]) this.nodesToCategories.get(typeDeclaration);
+ typeInfo.secondary = typeDeclaration.isSecondary();
+ typeInfo.anonymousMember = typeDeclaration.allocation != null && typeDeclaration.allocation.enclosingInstance != null;
requestor.enterType(typeInfo);
switch (kind) {
- case IGenericType.CLASS_DECL :
+ case TypeDeclaration.CLASS_DECL :
if (superclassName != null)
implicitSuperclassName = superclassName;
break;
- case IGenericType.INTERFACE_DECL :
+ case TypeDeclaration.INTERFACE_DECL :
implicitSuperclassName = TypeConstants.CharArray_JAVA_LANG_OBJECT;
break;
- case IGenericType.ENUM_DECL :
+ case TypeDeclaration.ENUM_DECL :
implicitSuperclassName = TypeConstants.CharArray_JAVA_LANG_ENUM;
break;
- case IGenericType.ANNOTATION_TYPE_DECL :
+ case TypeDeclaration.ANNOTATION_TYPE_DECL :
implicitSuperclassName = TypeConstants.CharArray_JAVA_LANG_ANNOTATION_ANNOTATION;
break;
}
@@ -1274,16 +1476,6 @@
nestedTypeIndex--;
}
}
-private int sourceEnd(TypeDeclaration typeDeclaration) {
- if ((typeDeclaration.bits & ASTNode.IsAnonymousTypeMASK) != 0) {
- QualifiedAllocationExpression allocation = typeDeclaration.allocation;
- if (allocation.type == null) // case of enum constant body
- return typeDeclaration.sourceEnd;
- return allocation.type.sourceEnd;
- } else {
- return typeDeclaration.sourceEnd;
- }
-}
public void parseCompilationUnit(
ICompilationUnit unit,
int start,
@@ -1292,17 +1484,13 @@
this.reportReferenceInfo = fullParse;
boolean old = diet;
- if (fullParse) {
- unknownRefs = new NameReference[10];
- unknownRefsCounter = 0;
- }
try {
diet = true;
CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, this.options.maxProblemsPerUnit);
CompilationUnitDeclaration parsedUnit = parse(unit, compilationUnitResult, start, end);
if (scanner.recordLineSeparator) {
- requestor.acceptLineSeparatorPositions(compilationUnitResult.lineSeparatorPositions);
+ requestor.acceptLineSeparatorPositions(compilationUnitResult.getLineSeparatorPositions());
}
if (this.localDeclarationVisitor != null || fullParse){
diet = false;
@@ -1314,6 +1502,7 @@
// ignore this exception
} finally {
diet = old;
+ reset();
}
}
public CompilationUnitDeclaration parseCompilationUnit(
@@ -1321,10 +1510,6 @@
boolean fullParse) {
boolean old = diet;
- if (fullParse) {
- unknownRefs = new NameReference[10];
- unknownRefsCounter = 0;
- }
try {
diet = true;
@@ -1332,7 +1517,7 @@
CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, this.options.maxProblemsPerUnit);
CompilationUnitDeclaration parsedUnit = parse(unit, compilationUnitResult);
if (scanner.recordLineSeparator) {
- requestor.acceptLineSeparatorPositions(compilationUnitResult.lineSeparatorPositions);
+ requestor.acceptLineSeparatorPositions(compilationUnitResult.getLineSeparatorPositions());
}
int initialStart = this.scanner.initialPosition;
int initialEnd = this.scanner.eofPosition;
@@ -1347,6 +1532,7 @@
// ignore this exception
} finally {
diet = old;
+ reset();
}
return null;
}
@@ -1357,10 +1543,6 @@
int end,
boolean needReferenceInfo) {
boolean old = diet;
- if (needReferenceInfo) {
- unknownRefs = new NameReference[10];
- unknownRefsCounter = 0;
- }
CompilationResult compilationUnitResult =
new CompilationResult(sourceUnit, 0, 0, this.options.maxProblemsPerUnit);
@@ -1402,9 +1584,10 @@
// ignore this exception
} finally {
if (scanner.recordLineSeparator) {
- requestor.acceptLineSeparatorPositions(compilationUnitResult.lineSeparatorPositions);
+ requestor.acceptLineSeparatorPositions(compilationUnitResult.getLineSeparatorPositions());
}
diet = old;
+ reset();
}
}
@@ -1440,6 +1623,7 @@
// ignore this exception
} finally {
diet = old;
+ reset();
}
}
/*
@@ -1448,7 +1632,7 @@
private static void quickSort(ASTNode[] sortedCollection, int left, int right) {
int original_left = left;
int original_right = right;
- ASTNode mid = sortedCollection[ (left + right) / 2];
+ ASTNode mid = sortedCollection[left + (right - left) / 2];
do {
while (sortedCollection[left].sourceStart < mid.sourceStart) {
left++;
@@ -1471,22 +1655,36 @@
quickSort(sortedCollection, left, original_right);
}
}
-public void addUnknownRef(NameReference nameRef) {
- if (this.unknownRefs.length == this.unknownRefsCounter) {
- // resize
- System.arraycopy(
- this.unknownRefs,
- 0,
- (this.unknownRefs = new NameReference[this.unknownRefsCounter * 2]),
- 0,
- this.unknownRefsCounter);
+private void rememberCategories() {
+ if (this.useSourceJavadocParser) {
+ SourceJavadocParser sourceJavadocParser = (SourceJavadocParser) this.javadocParser;
+ char[][] categories = sourceJavadocParser.categories;
+ if (categories.length > 0) {
+ this.nodesToCategories.put(this.astStack[this.astPtr], categories);
+ sourceJavadocParser.categories = CharOperation.NO_CHAR_CHAR;
+ }
}
- this.unknownRefs[this.unknownRefsCounter++] = nameRef;
}
-
+private void reset() {
+ this.sourceEnds = new HashtableOfObjectToInt();
+ this.nodesToCategories = new HashMap();
+ typeNames = new char[4][];
+ superTypeNames = new char[4][];
+ nestedTypeIndex = 0;
+}
+private int sourceEnd(TypeDeclaration typeDeclaration) {
+ if ((typeDeclaration.bits & ASTNode.IsAnonymousType) != 0) {
+ QualifiedAllocationExpression allocation = typeDeclaration.allocation;
+ if (allocation.type == null) // case of enum constant body
+ return typeDeclaration.sourceEnd;
+ return allocation.type.sourceEnd;
+ } else {
+ return typeDeclaration.sourceEnd;
+ }
+}
private void visitIfNeeded(AbstractMethodDeclaration method) {
if (this.localDeclarationVisitor != null
- && (method.bits & ASTNode.HasLocalTypeMASK) != 0) {
+ && (method.bits & ASTNode.HasLocalType) != 0) {
if (method instanceof ConstructorDeclaration) {
ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) method;
if (constructorDeclaration.constructorCall != null) {
@@ -1503,7 +1701,7 @@
private void visitIfNeeded(FieldDeclaration field, TypeDeclaration declaringType) {
if (this.localDeclarationVisitor != null
- && (field.bits & ASTNode.HasLocalTypeMASK) != 0) {
+ && (field.bits & ASTNode.HasLocalType) != 0) {
if (field.initialization != null) {
try {
this.localDeclarationVisitor.pushDeclaringType(declaringType);
@@ -1517,7 +1715,7 @@
private void visitIfNeeded(Initializer initializer) {
if (this.localDeclarationVisitor != null
- && (initializer.bits & ASTNode.HasLocalTypeMASK) != 0) {
+ && (initializer.bits & ASTNode.HasLocalType) != 0) {
if (initializer.block != null) {
initializer.block.traverse(this.localDeclarationVisitor, null);
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementRequestorAdapter.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementRequestorAdapter.java
index b0ba625..7f31e8b 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementRequestorAdapter.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementRequestorAdapter.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,7 +10,7 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler;
-import org.eclipse.jdt.core.compiler.IProblem;
+import org.eclipse.jdt.core.compiler.CategorizedProblem;
public class SourceElementRequestorAdapter implements ISourceElementRequestor {
@@ -32,12 +32,12 @@
}
/**
- * @see ISourceElementRequestor#acceptImport(int, int, char[], boolean, int)
+ * @see ISourceElementRequestor#acceptImport(int, int, char[][], boolean, int)
*/
public void acceptImport(
int declarationStart,
int declarationEnd,
- char[] name,
+ char[][] tokens,
boolean onDemand,
int modifiers) {
// default implementation: do nothing
@@ -71,9 +71,9 @@
}
/**
- * @see ISourceElementRequestor#acceptProblem(IProblem)
+ * @see ISourceElementRequestor#acceptProblem(CategorizedProblem)
*/
- public void acceptProblem(IProblem problem) {
+ public void acceptProblem(CategorizedProblem problem) {
// default implementation: do nothing
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceJavadocParser.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceJavadocParser.java
new file mode 100755
index 0000000..c9bd2d0
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceJavadocParser.java
@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.parser.JavadocParser;
+import org.eclipse.jdt.internal.compiler.parser.Parser;
+import org.eclipse.jdt.internal.compiler.parser.ScannerHelper;
+import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
+
+public class SourceJavadocParser extends JavadocParser {
+
+ // Store categories identifiers parsed in javadoc
+ int categoriesPtr = -1;
+ char[][] categories = CharOperation.NO_CHAR_CHAR;
+
+public SourceJavadocParser(Parser sourceParser) {
+ super(sourceParser);
+ this.kind = SOURCE_PARSER | TEXT_VERIF;
+}
+
+public boolean checkDeprecation(int commentPtr) {
+ this.categoriesPtr = -1;
+ boolean result = super.checkDeprecation(commentPtr);
+ if (this.categoriesPtr > -1) {
+ System.arraycopy(this.categories, 0, this.categories = new char[this.categoriesPtr+1][], 0, this.categoriesPtr+1);
+ } else {
+ this.categories = CharOperation.NO_CHAR_CHAR;
+ }
+ return result;
+}
+
+/* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#parseIdentifierTag()
+ */
+protected boolean parseIdentifierTag(boolean report) {
+ int end = this.lineEnd+1;
+ if (super.parseIdentifierTag(report) && this.index <= end) {
+ if (this.tagValue == TAG_CATEGORY_VALUE) {
+ // Store first category id
+ int length = this.categories.length;
+ if (++this.categoriesPtr >= length) {
+ System.arraycopy(this.categories, 0, this.categories = new char[length+5][], 0, length);
+ length += 5;
+ }
+ this.categories[this.categoriesPtr] = this.identifierStack[this.identifierPtr--];
+ // Store optional additional category identifiers
+ consumeToken();
+ while (this.index < end) {
+ if (readTokenSafely() == TerminalTokens.TokenNameIdentifier && (this.scanner.currentCharacter == ' ' || ScannerHelper.isWhitespace(this.scanner.currentCharacter))) {
+ if (this.index > (this.lineEnd+1)) break;
+ // valid additional identifier
+ if (++this.categoriesPtr >= length) {
+ System.arraycopy(this.categories, 0, this.categories = new char[length+5][], 0, length);
+ length += 5;
+ }
+ this.categories[this.categoriesPtr] = this.scanner.getCurrentIdentifierSource();
+ consumeToken();
+ } else {
+ // TODO (frederic) raise warning for invalid syntax when javadoc spec will be finalized...
+ break;
+ }
+ }
+ // Reset position to end of line
+ this.index = end;
+ this.scanner.currentPosition = end;
+ consumeToken();
+ }
+ return true;
+ }
+ return false;
+}
+
+/* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.compiler.parser.JavadocParser#parseSimpleTag()
+ */
+protected void parseSimpleTag() {
+
+ // Read first char
+ // readChar() code is inlined to balance additional method call in checkDeprectation(int)
+ char first = this.source[this.index++];
+ if (first == '\\' && this.source[this.index] == 'u') {
+ int c1, c2, c3, c4;
+ int pos = this.index;
+ this.index++;
+ while (this.source[this.index] == 'u')
+ this.index++;
+ if (!(((c1 = ScannerHelper.getNumericValue(this.source[this.index++])) > 15 || c1 < 0)
+ || ((c2 = ScannerHelper.getNumericValue(this.source[this.index++])) > 15 || c2 < 0)
+ || ((c3 = ScannerHelper.getNumericValue(this.source[this.index++])) > 15 || c3 < 0)
+ || ((c4 = ScannerHelper.getNumericValue(this.source[this.index++])) > 15 || c4 < 0))) {
+ first = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+ } else {
+ this.index = pos;
+ }
+ }
+
+ // switch on first tag char
+ switch (first) {
+ case 'd': // perhaps @deprecated tag?
+ if ((readChar() == 'e') &&
+ (readChar() == 'p') && (readChar() == 'r') &&
+ (readChar() == 'e') && (readChar() == 'c') &&
+ (readChar() == 'a') && (readChar() == 't') &&
+ (readChar() == 'e') && (readChar() == 'd')) {
+ // ensure the tag is properly ended: either followed by a space, a tab, line end or asterisk.
+ char c = readChar();
+ if (ScannerHelper.isWhitespace(c) || c == '*') {
+ this.tagValue = TAG_DEPRECATED_VALUE;
+ this.deprecated = true;
+ }
+ }
+ break;
+ case 'c': // perhaps @category tag?
+ if ((readChar() == 'a') &&
+ (readChar() == 't') && (readChar() == 'e') &&
+ (readChar() == 'g') && (readChar() == 'o') &&
+ (readChar() == 'r') && (readChar() == 'y')) {
+ // ensure the tag is properly ended: either followed by a space, a tab, line end or asterisk.
+ char c = readChar();
+ if (ScannerHelper.isWhitespace(c) || c == '*') {
+ this.tagValue = TAG_CATEGORY_VALUE;
+ if (this.scanner.source == null) {
+ this.scanner.setSource(this.source);
+ }
+ this.scanner.resetTo(this.index, this.scanner.eofPosition);
+ parseIdentifierTag(false); // Do not report missing identifier
+ }
+ }
+ break;
+ }
+}
+
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceTypeConverter.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceTypeConverter.java
index 1c5015b..88bdeb2 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceTypeConverter.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceTypeConverter.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -26,7 +26,6 @@
import java.util.ArrayList;
import java.util.HashMap;
-import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.IImportDeclaration;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.JavaModelException;
@@ -38,13 +37,24 @@
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.env.*;
-import org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers;
+import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
import org.eclipse.jdt.internal.core.*;
+import org.eclipse.jdt.internal.core.util.Util;
-public class SourceTypeConverter implements CompilerModifiers {
+public class SourceTypeConverter {
+ /*
+ * Exception thrown while converting an anonymous type of a member type
+ * in this case, we must parse the source as the enclosing instance cannot be recreated
+ * from the model
+ */
+ static class AnonymousMemberFound extends RuntimeException {
+ private static final long serialVersionUID = 1L;
+ }
+
public static final int FIELD = 0x01;
public static final int CONSTRUCTOR = 0x02;
public static final int METHOD = 0x04;
@@ -119,38 +129,52 @@
int end = topLevelTypeInfo.getNameSourceEnd();
/* convert package and imports */
- char[] packageName = cuHandle.getParent().getElementName().toCharArray();
+ String[] packageName = ((PackageFragment) cuHandle.getParent()).names;
if (packageName.length > 0)
// if its null then it is defined in the default package
this.unit.currentPackage =
- createImportReference(packageName, start, end, false, AccDefault);
+ createImportReference(packageName, start, end, false, ClassFileConstants.AccDefault);
IImportDeclaration[] importDeclarations = topLevelTypeInfo.getHandle().getCompilationUnit().getImports();
int importCount = importDeclarations.length;
this.unit.imports = new ImportReference[importCount];
for (int i = 0; i < importCount; i++) {
ImportDeclaration importDeclaration = (ImportDeclaration) importDeclarations[i];
ISourceImport sourceImport = (ISourceImport) importDeclaration.getElementInfo();
+ String nameWithoutStar = importDeclaration.getNameWithoutStar();
this.unit.imports[i] = createImportReference(
- importDeclaration.getNameWithoutStar().toCharArray(),
+ Util.splitOn('.', nameWithoutStar, 0, nameWithoutStar.length()),
sourceImport.getDeclarationSourceStart(),
sourceImport.getDeclarationSourceEnd(),
importDeclaration.isOnDemand(),
sourceImport.getModifiers());
}
/* convert type(s) */
- int typeCount = sourceTypes.length;
- final TypeDeclaration[] types = new TypeDeclaration[typeCount];
- /*
- * We used a temporary types collection to prevent this.unit.types from being null during a call to
- * convert(...) when the source is syntactically incorrect and the parser is flushing the unit's types.
- * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=97466
- */
- for (int i = 0; i < typeCount; i++) {
- SourceTypeElementInfo typeInfo = (SourceTypeElementInfo) sourceTypes[i];
- types[i] = convert((SourceType) typeInfo.getHandle(), compilationResult);
+ try {
+ int typeCount = sourceTypes.length;
+ final TypeDeclaration[] types = new TypeDeclaration[typeCount];
+ /*
+ * We used a temporary types collection to prevent this.unit.types from being null during a call to
+ * convert(...) when the source is syntactically incorrect and the parser is flushing the unit's types.
+ * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=97466
+ */
+ for (int i = 0; i < typeCount; i++) {
+ SourceTypeElementInfo typeInfo = (SourceTypeElementInfo) sourceTypes[i];
+ types[i] = convert((SourceType) typeInfo.getHandle(), compilationResult);
+ }
+ this.unit.types = types;
+ return this.unit;
+ } catch (AnonymousMemberFound e) {
+ return new Parser(this.problemReporter, true).parse(this.cu, compilationResult);
}
- this.unit.types = types;
- return this.unit;
+ }
+
+ private void addIdentifiers(String typeSignature, int start, int endExclusive, int identCount, ArrayList fragments) {
+ if (identCount == 1) {
+ char[] identifier;
+ typeSignature.getChars(start, endExclusive, identifier = new char[endExclusive-start], 0);
+ fragments.add(identifier);
+ } else
+ fragments.add(extractIdentifiers(typeSignature, start, endExclusive-1, identCount));
}
/*
@@ -159,7 +183,7 @@
private Initializer convert(InitializerElementInfo initializerInfo, CompilationResult compilationResult) throws JavaModelException {
Block block = new Block(0);
- Initializer initializer = new Initializer(block, IConstants.AccDefault);
+ Initializer initializer = new Initializer(block, ClassFileConstants.AccDefault);
int start = initializerInfo.getDeclarationSourceStart();
int end = initializerInfo.getDeclarationSourceEnd();
@@ -176,7 +200,7 @@
for (int i = 0; i < typesLength; i++) {
SourceType type = (SourceType) children[i];
TypeDeclaration localType = convert(type, compilationResult);
- if ((localType.bits & ASTNode.IsAnonymousTypeMASK) != 0) {
+ if ((localType.bits & ASTNode.IsAnonymousType) != 0) {
QualifiedAllocationExpression expression = new QualifiedAllocationExpression(localType);
expression.type = localType.superclass;
localType.superclass = null;
@@ -210,9 +234,9 @@
field.declarationSourceStart = fieldInfo.getDeclarationSourceStart();
field.declarationSourceEnd = fieldInfo.getDeclarationSourceEnd();
int modifiers = fieldInfo.getModifiers();
- boolean isEnumConstant = (modifiers & AccEnum) != 0;
+ boolean isEnumConstant = (modifiers & ClassFileConstants.AccEnum) != 0;
if (isEnumConstant) {
- field.modifiers = modifiers & ~Flags.AccEnum; // clear AccEnum bit onto AST (binding will add it)
+ field.modifiers = modifiers & ~ClassFileConstants.AccEnum; // clear AccEnum bit onto AST (binding will add it)
} else {
field.modifiers = modifiers;
field.type = createTypeReference(fieldInfo.getTypeName(), start, end);
@@ -239,33 +263,40 @@
if ((this.flags & LOCAL_TYPE) != 0) {
IJavaElement[] children = fieldInfo.getChildren();
int childrenLength = children.length;
- if (childrenLength > 0) {
+ if (childrenLength == 1) {
+ field.initialization = convert(children[0], isEnumConstant ? field : null, compilationResult);
+ } else if (childrenLength > 1) {
ArrayInitializer initializer = new ArrayInitializer();
field.initialization = initializer;
Expression[] expressions = new Expression[childrenLength];
initializer.expressions = expressions;
for (int i = 0; i < childrenLength; i++) {
- IJavaElement localType = children[i];
- TypeDeclaration anonymousLocalTypeDeclaration = convert((SourceType) localType, compilationResult);
- QualifiedAllocationExpression expression = new QualifiedAllocationExpression(anonymousLocalTypeDeclaration);
- expression.type = anonymousLocalTypeDeclaration.superclass;
- anonymousLocalTypeDeclaration.superclass = null;
- anonymousLocalTypeDeclaration.superInterfaces = null;
- anonymousLocalTypeDeclaration.allocation = expression;
- anonymousLocalTypeDeclaration.modifiers &= ~AccEnum; // remove tag in case this is the init of an enum constant
- expressions[i] = expression;
+ expressions[i] = convert(children[i], isEnumConstant ? field : null, compilationResult);
}
}
}
return field;
}
+ private QualifiedAllocationExpression convert(IJavaElement localType, FieldDeclaration enumConstant, CompilationResult compilationResult) throws JavaModelException {
+ TypeDeclaration anonymousLocalTypeDeclaration = convert((SourceType) localType, compilationResult);
+ QualifiedAllocationExpression expression = new QualifiedAllocationExpression(anonymousLocalTypeDeclaration);
+ expression.type = anonymousLocalTypeDeclaration.superclass;
+ anonymousLocalTypeDeclaration.superclass = null;
+ anonymousLocalTypeDeclaration.superInterfaces = null;
+ anonymousLocalTypeDeclaration.allocation = expression;
+ if (enumConstant != null) {
+ anonymousLocalTypeDeclaration.modifiers &= ~ClassFileConstants.AccEnum;
+ expression.enumConstant = enumConstant;
+ expression.type = null;
+ }
+ return expression;
+ }
+
/*
* Convert a method source element into a parsed method/constructor declaration
*/
- private AbstractMethodDeclaration convert(SourceMethod methodHandle, CompilationResult compilationResult) throws JavaModelException {
-
- SourceMethodElementInfo methodInfo = (SourceMethodElementInfo) methodHandle.getElementInfo();
+ private AbstractMethodDeclaration convert(SourceMethod methodHandle, SourceMethodElementInfo methodInfo, CompilationResult compilationResult) throws JavaModelException {
AbstractMethodDeclaration method;
/* only source positions available */
@@ -292,7 +323,7 @@
int modifiers = methodInfo.getModifiers();
if (methodInfo.isConstructor()) {
ConstructorDeclaration decl = new ConstructorDeclaration(compilationResult);
- decl.isDefaultConstructor = false;
+ decl.bits &= ~ASTNode.IsDefaultConstructor;
method = decl;
decl.typeParameters = typeParams;
} else {
@@ -301,16 +332,24 @@
AnnotationMethodDeclaration annotationMethodDeclaration = new AnnotationMethodDeclaration(compilationResult);
/* conversion of default value */
+ SourceAnnotationMethodInfo annotationMethodInfo = (SourceAnnotationMethodInfo) methodInfo;
+ boolean hasDefaultValue = annotationMethodInfo.defaultValueStart != -1 || annotationMethodInfo.defaultValueEnd != -1;
if ((this.flags & FIELD_INITIALIZATION) != 0) {
- char[] defaultValueSource = ((SourceAnnotationMethodInfo) methodInfo).getDefaultValueSource(getSource());
- if (defaultValueSource != null) {
- Expression expression = parseMemberValue(defaultValueSource);
- if (expression != null) {
- annotationMethodDeclaration.defaultValue = expression;
- modifiers |= AccAnnotationDefault;
+ if (hasDefaultValue) {
+ char[] defaultValueSource = CharOperation.subarray(getSource(), annotationMethodInfo.defaultValueStart, annotationMethodInfo.defaultValueEnd+1);
+ if (defaultValueSource != null) {
+ Expression expression = parseMemberValue(defaultValueSource);
+ if (expression != null) {
+ annotationMethodDeclaration.defaultValue = expression;
+ }
+ } else {
+ // could not retrieve the default value
+ hasDefaultValue = false;
}
}
}
+ if (hasDefaultValue)
+ modifiers |= ClassFileConstants.AccAnnotationDefault;
decl = annotationMethodDeclaration;
} else {
decl = new MethodDeclaration(compilationResult);
@@ -325,8 +364,8 @@
method = decl;
}
method.selector = methodHandle.getElementName().toCharArray();
- boolean isVarargs = (modifiers & AccVarargs) != 0;
- method.modifiers = modifiers & ~AccVarargs;
+ boolean isVarargs = (modifiers & ClassFileConstants.AccVarargs) != 0;
+ method.modifiers = modifiers & ~ClassFileConstants.AccVarargs;
method.sourceStart = start;
method.sourceEnd = end;
method.declarationSourceStart = methodInfo.getDeclarationSourceStart();
@@ -342,30 +381,33 @@
String[] argumentTypeSignatures = methodHandle.getParameterTypes();
char[][] argumentNames = methodInfo.getArgumentNames();
int argumentCount = argumentTypeSignatures == null ? 0 : argumentTypeSignatures.length;
- long position = ((long) start << 32) + end;
- method.arguments = new Argument[argumentCount];
- for (int i = 0; i < argumentCount; i++) {
- char[] typeName = Signature.toCharArray(argumentTypeSignatures[i].toCharArray());
- TypeReference typeReference = createTypeReference(typeName, start, end);
- if (isVarargs && i == argumentCount-1) {
- typeReference.bits |= ASTNode.IsVarArgs;
+ if (argumentCount > 0) {
+ long position = ((long) start << 32) + end;
+ method.arguments = new Argument[argumentCount];
+ for (int i = 0; i < argumentCount; i++) {
+ TypeReference typeReference = createTypeReference(argumentTypeSignatures[i], start, end);
+ if (isVarargs && i == argumentCount-1) {
+ typeReference.bits |= ASTNode.IsVarArgs;
+ }
+ method.arguments[i] =
+ new Argument(
+ argumentNames[i],
+ position,
+ typeReference,
+ ClassFileConstants.AccDefault);
+ // do not care whether was final or not
}
- method.arguments[i] =
- new Argument(
- argumentNames[i],
- position,
- typeReference,
- AccDefault);
- // do not care whether was final or not
}
/* convert thrown exceptions */
char[][] exceptionTypeNames = methodInfo.getExceptionTypeNames();
int exceptionCount = exceptionTypeNames == null ? 0 : exceptionTypeNames.length;
- method.thrownExceptions = new TypeReference[exceptionCount];
- for (int i = 0; i < exceptionCount; i++) {
- method.thrownExceptions[i] =
- createTypeReference(exceptionTypeNames[i], start, end);
+ if (exceptionCount > 0) {
+ method.thrownExceptions = new TypeReference[exceptionCount];
+ for (int i = 0; i < exceptionCount; i++) {
+ method.thrownExceptions[i] =
+ createTypeReference(exceptionTypeNames[i], start, end);
+ }
}
/* convert local and anonymous types */
@@ -377,7 +419,7 @@
for (int i = 0; i < typesLength; i++) {
SourceType type = (SourceType) children[i];
TypeDeclaration localType = convert(type, compilationResult);
- if ((localType.bits & ASTNode.IsAnonymousTypeMASK) != 0) {
+ if ((localType.bits & ASTNode.IsAnonymousType) != 0) {
QualifiedAllocationExpression expression = new QualifiedAllocationExpression(localType);
expression.type = localType.superclass;
localType.superclass = null;
@@ -400,21 +442,23 @@
*/
private TypeDeclaration convert(SourceType typeHandle, CompilationResult compilationResult) throws JavaModelException {
SourceTypeElementInfo typeInfo = (SourceTypeElementInfo) typeHandle.getElementInfo();
+ if (typeInfo.isAnonymousMember())
+ throw new AnonymousMemberFound();
/* create type declaration - can be member type */
TypeDeclaration type = new TypeDeclaration(compilationResult);
if (typeInfo.getEnclosingType() == null) {
if (typeHandle.isAnonymous()) {
- type.name = TypeDeclaration.ANONYMOUS_EMPTY_NAME;
- type.bits |= ASTNode.AnonymousAndLocalMask;
+ type.name = CharOperation.NO_CHAR;
+ type.bits |= (ASTNode.IsAnonymousType|ASTNode.IsLocalType);
} else {
if (typeHandle.isLocal()) {
- type.bits |= ASTNode.IsLocalTypeMASK;
+ type.bits |= ASTNode.IsLocalType;
}
}
} else {
- type.bits |= ASTNode.IsMemberTypeMASK;
+ type.bits |= ASTNode.IsMemberType;
}
- if ((type.bits & ASTNode.IsAnonymousTypeMASK) == 0) {
+ if ((type.bits & ASTNode.IsAnonymousType) == 0) {
type.name = typeInfo.getName();
}
type.name = typeInfo.getName();
@@ -504,8 +548,8 @@
/* by default, we assume that one is needed. */
int extraConstructor = 0;
int methodCount = 0;
- int kind = type.kind();
- boolean isAbstract = kind == IGenericType.INTERFACE_DECL || kind == IGenericType.ANNOTATION_TYPE_DECL;
+ int kind = TypeDeclaration.kind(type.modifiers);
+ boolean isAbstract = kind == TypeDeclaration.INTERFACE_DECL || kind == TypeDeclaration.ANNOTATION_TYPE_DECL;
if (!isAbstract) {
extraConstructor = needConstructor ? 1 : 0;
for (int i = 0; i < sourceMethodCount; i++) {
@@ -529,14 +573,15 @@
boolean hasAbstractMethods = false;
for (int i = 0; i < sourceMethodCount; i++) {
SourceMethod sourceMethod = sourceMethods[i];
- boolean isConstructor = sourceMethod.isConstructor();
- if ((sourceMethod.getFlags() & Flags.AccAbstract) != 0) {
+ SourceMethodElementInfo methodInfo = (SourceMethodElementInfo)sourceMethod.getElementInfo();
+ boolean isConstructor = methodInfo.isConstructor();
+ if ((methodInfo.getModifiers() & ClassFileConstants.AccAbstract) != 0) {
hasAbstractMethods = true;
}
if ((isConstructor && needConstructor) || (!isConstructor && needMethod)) {
- AbstractMethodDeclaration method = convert(sourceMethod, compilationResult);
+ AbstractMethodDeclaration method = convert(sourceMethod, methodInfo, compilationResult);
if (isAbstract || method.isAbstract()) { // fix-up flag
- method.modifiers |= AccSemicolonBody;
+ method.modifiers |= ExtraCompilerModifiers.AccSemicolonBody;
}
type.methods[extraConstructor + index++] = method;
}
@@ -560,15 +605,17 @@
int start = (int) (position >>> 32);
int end = (int) position;
char[] annotationSource = CharOperation.subarray(cuSource, start, end+1);
- Expression expression = parseMemberValue(annotationSource);
- /*
- * expression can be null or not an annotation if the source has changed between
- * the moment where the annotation source positions have been retrieved and the moment were
- * this parsing occured.
- * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=90916
- */
- if (expression instanceof Annotation) {
- annotations[recordedAnnotations++] = (Annotation) expression;
+ if (annotationSource != null) {
+ Expression expression = parseMemberValue(annotationSource);
+ /*
+ * expression can be null or not an annotation if the source has changed between
+ * the moment where the annotation source positions have been retrieved and the moment were
+ * this parsing occured.
+ * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=90916
+ */
+ if (expression instanceof Annotation) {
+ annotations[recordedAnnotations++] = (Annotation) expression;
+ }
}
}
if (length != recordedAnnotations) {
@@ -582,16 +629,18 @@
* Build an import reference from an import name, e.g. java.lang.*
*/
private ImportReference createImportReference(
- char[] importName,
+ String[] importName,
int start,
int end,
boolean onDemand,
int modifiers) {
- char[][] qImportName = CharOperation.splitOn('.', importName);
- long[] positions = new long[qImportName.length];
+ int length = importName.length;
+ long[] positions = new long[length];
long position = ((long) start << 32) + end;
- for (int i = 0; i < qImportName.length; i++) {
+ char[][] qImportName = new char[length][];
+ for (int i = 0; i < length; i++) {
+ qImportName[i] = importName[i].toCharArray();
positions[i] = position; // dummy positions
}
return new ImportReference(
@@ -634,9 +683,242 @@
int length = typeName.length;
this.namePos = 0;
- TypeReference type = decodeType(typeName, length, start, end);
- return type;
+ return decodeType(typeName, length, start, end);
}
+
+ /*
+ * Build a type reference from a type signature, e.g. Ljava.lang.Object;
+ */
+ private TypeReference createTypeReference(
+ String typeSignature,
+ int start,
+ int end) {
+
+ int length = typeSignature.length();
+ this.namePos = 0;
+ return decodeType(typeSignature, length, start, end);
+ }
+
+ private TypeReference decodeType(String typeSignature, int length, int start, int end) {
+ int identCount = 1;
+ int dim = 0;
+ int nameFragmentStart = this.namePos, nameFragmentEnd = -1;
+ boolean nameStarted = false;
+ ArrayList fragments = null;
+ typeLoop: while (this.namePos < length) {
+ char currentChar = typeSignature.charAt(this.namePos);
+ switch (currentChar) {
+ case Signature.C_BOOLEAN :
+ if (!nameStarted) {
+ this.namePos++;
+ if (dim == 0)
+ return new SingleTypeReference(TypeBinding.BOOLEAN.simpleName, ((long) start << 32) + end);
+ else
+ return new ArrayTypeReference(TypeBinding.BOOLEAN.simpleName, dim, ((long) start << 32) + end);
+ }
+ break;
+ case Signature.C_BYTE :
+ if (!nameStarted) {
+ this.namePos++;
+ if (dim == 0)
+ return new SingleTypeReference(TypeBinding.BYTE.simpleName, ((long) start << 32) + end);
+ else
+ return new ArrayTypeReference(TypeBinding.BYTE.simpleName, dim, ((long) start << 32) + end);
+ }
+ break;
+ case Signature.C_CHAR :
+ if (!nameStarted) {
+ this.namePos++;
+ if (dim == 0)
+ return new SingleTypeReference(TypeBinding.CHAR.simpleName, ((long) start << 32) + end);
+ else
+ return new ArrayTypeReference(TypeBinding.CHAR.simpleName, dim, ((long) start << 32) + end);
+ }
+ break;
+ case Signature.C_DOUBLE :
+ if (!nameStarted) {
+ this.namePos++;
+ if (dim == 0)
+ return new SingleTypeReference(TypeBinding.DOUBLE.simpleName, ((long) start << 32) + end);
+ else
+ return new ArrayTypeReference(TypeBinding.DOUBLE.simpleName, dim, ((long) start << 32) + end);
+ }
+ break;
+ case Signature.C_FLOAT :
+ if (!nameStarted) {
+ this.namePos++;
+ if (dim == 0)
+ return new SingleTypeReference(TypeBinding.FLOAT.simpleName, ((long) start << 32) + end);
+ else
+ return new ArrayTypeReference(TypeBinding.FLOAT.simpleName, dim, ((long) start << 32) + end);
+ }
+ break;
+ case Signature.C_INT :
+ if (!nameStarted) {
+ this.namePos++;
+ if (dim == 0)
+ return new SingleTypeReference(TypeBinding.INT.simpleName, ((long) start << 32) + end);
+ else
+ return new ArrayTypeReference(TypeBinding.INT.simpleName, dim, ((long) start << 32) + end);
+ }
+ break;
+ case Signature.C_LONG :
+ if (!nameStarted) {
+ this.namePos++;
+ if (dim == 0)
+ return new SingleTypeReference(TypeBinding.LONG.simpleName, ((long) start << 32) + end);
+ else
+ return new ArrayTypeReference(TypeBinding.LONG.simpleName, dim, ((long) start << 32) + end);
+ }
+ break;
+ case Signature.C_SHORT :
+ if (!nameStarted) {
+ this.namePos++;
+ if (dim == 0)
+ return new SingleTypeReference(TypeBinding.SHORT.simpleName, ((long) start << 32) + end);
+ else
+ return new ArrayTypeReference(TypeBinding.SHORT.simpleName, dim, ((long) start << 32) + end);
+ }
+ break;
+ case Signature.C_VOID :
+ if (!nameStarted) {
+ this.namePos++;
+ new SingleTypeReference(TypeBinding.VOID.simpleName, ((long) start << 32) + end);
+ }
+ break;
+ case Signature.C_RESOLVED :
+ case Signature.C_UNRESOLVED :
+ if (!nameStarted) {
+ nameFragmentStart = this.namePos+1;
+ nameStarted = true;
+ }
+ break;
+ case Signature.C_STAR:
+ this.namePos++;
+ Wildcard result = new Wildcard(Wildcard.UNBOUND);
+ result.sourceStart = start;
+ result.sourceEnd = end;
+ return result;
+ case Signature.C_EXTENDS:
+ this.namePos++;
+ result = new Wildcard(Wildcard.EXTENDS);
+ result.bound = decodeType(typeSignature, length, start, end);
+ result.sourceStart = start;
+ result.sourceEnd = end;
+ return result;
+ case Signature.C_SUPER:
+ this.namePos++;
+ result = new Wildcard(Wildcard.SUPER);
+ result.bound = decodeType(typeSignature, length, start, end);
+ result.sourceStart = start;
+ result.sourceEnd = end;
+ return result;
+ case Signature.C_ARRAY :
+ dim++;
+ break;
+ case Signature.C_GENERIC_END :
+ case Signature.C_SEMICOLON :
+ nameFragmentEnd = this.namePos-1;
+ this.namePos++;
+ break typeLoop;
+ case Signature.C_DOT :
+ case Signature.C_DOLLAR:
+ if (!nameStarted) {
+ nameFragmentStart = this.namePos+1;
+ nameStarted = true;
+ } else if (this.namePos > nameFragmentStart) // handle name starting with a $ (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=91709)
+ identCount ++;
+ break;
+ case Signature.C_GENERIC_START :
+ nameFragmentEnd = this.namePos-1;
+ // convert 1.5 specific constructs only if compliance is 1.5 or above
+ if (!this.has1_5Compliance)
+ break typeLoop;
+ if (fragments == null) fragments = new ArrayList(2);
+ addIdentifiers(typeSignature, nameFragmentStart, nameFragmentEnd + 1, identCount, fragments);
+ this.namePos++; // skip '<'
+ TypeReference[] arguments = decodeTypeArguments(typeSignature, length, start, end); // positionned on '>' at end
+ fragments.add(arguments);
+ identCount = 1;
+ nameStarted = false;
+ // next increment will skip '>'
+ break;
+ }
+ this.namePos++;
+ }
+ if (fragments == null) { // non parameterized
+ /* rebuild identifiers and dimensions */
+ if (identCount == 1) { // simple type reference
+ if (dim == 0) {
+ char[] nameFragment = new char[nameFragmentEnd - nameFragmentStart + 1];
+ typeSignature.getChars(nameFragmentStart, nameFragmentEnd +1, nameFragment, 0);
+ return new SingleTypeReference(nameFragment, ((long) start << 32) + end);
+ } else {
+ char[] nameFragment = new char[nameFragmentEnd - nameFragmentStart + 1];
+ typeSignature.getChars(nameFragmentStart, nameFragmentEnd +1, nameFragment, 0);
+ return new ArrayTypeReference(nameFragment, dim, ((long) start << 32) + end);
+ }
+ } else { // qualified type reference
+ long[] positions = new long[identCount];
+ long pos = ((long) start << 32) + end;
+ for (int i = 0; i < identCount; i++) {
+ positions[i] = pos;
+ }
+ char[][] identifiers = extractIdentifiers(typeSignature, nameFragmentStart, nameFragmentEnd, identCount);
+ if (dim == 0) {
+ return new QualifiedTypeReference(identifiers, positions);
+ } else {
+ return new ArrayQualifiedTypeReference(identifiers, dim, positions);
+ }
+ }
+ } else { // parameterized
+ // rebuild type reference from available fragments: char[][], arguments, char[][], arguments...
+ // check trailing qualified name
+ if (nameStarted) {
+ addIdentifiers(typeSignature, nameFragmentStart, nameFragmentEnd + 1, identCount, fragments);
+ }
+ int fragmentLength = fragments.size();
+ if (fragmentLength == 2) {
+ Object firstFragment = fragments.get(0);
+ if (firstFragment instanceof char[]) {
+ // parameterized single type
+ return new ParameterizedSingleTypeReference((char[]) firstFragment, (TypeReference[]) fragments.get(1), dim, ((long) start << 32) + end);
+ }
+ }
+ // parameterized qualified type
+ identCount = 0;
+ for (int i = 0; i < fragmentLength; i ++) {
+ Object element = fragments.get(i);
+ if (element instanceof char[][]) {
+ identCount += ((char[][])element).length;
+ } else if (element instanceof char[])
+ identCount++;
+ }
+ char[][] tokens = new char[identCount][];
+ TypeReference[][] arguments = new TypeReference[identCount][];
+ int index = 0;
+ for (int i = 0; i < fragmentLength; i ++) {
+ Object element = fragments.get(i);
+ if (element instanceof char[][]) {
+ char[][] fragmentTokens = (char[][]) element;
+ int fragmentTokenLength = fragmentTokens.length;
+ System.arraycopy(fragmentTokens, 0, tokens, index, fragmentTokenLength);
+ index += fragmentTokenLength;
+ } else if (element instanceof char[]) {
+ tokens[index++] = (char[]) element;
+ } else {
+ arguments[index-1] = (TypeReference[]) element;
+ }
+ }
+ long[] positions = new long[identCount];
+ long pos = ((long) start << 32) + end;
+ for (int i = 0; i < identCount; i++) {
+ positions[i] = pos;
+ }
+ return new ParameterizedQualifiedTypeReference(tokens, arguments, dim, positions);
+ }
+ }
+
private TypeReference decodeType(char[] typeName, int length, int start, int end) {
int identCount = 1;
int dim = 0;
@@ -814,6 +1096,38 @@
return typeArguments;
}
+ private TypeReference[] decodeTypeArguments(String typeSignature, int length, int start, int end) {
+ ArrayList argumentList = new ArrayList(1);
+ int count = 0;
+ argumentsLoop: while (this.namePos < length) {
+ TypeReference argument = decodeType(typeSignature, length, start, end);
+ count++;
+ argumentList.add(argument);
+ if (this.namePos >= length) break argumentsLoop;
+ if (typeSignature.charAt(this.namePos) == '>') {
+ break argumentsLoop;
+ }
+ }
+ TypeReference[] typeArguments = new TypeReference[count];
+ argumentList.toArray(typeArguments);
+ return typeArguments;
+ }
+
+ private char[][] extractIdentifiers(String typeSignature, int start, int endInclusive, int identCount) {
+ char[][] result = new char[identCount][];
+ int charIndex = start;
+ int i = 0;
+ while (charIndex < endInclusive) {
+ if (typeSignature.charAt(charIndex) == '.') {
+ typeSignature.getChars(start, charIndex, result[i++] = new char[charIndex - start], 0);
+ start = ++charIndex;
+ } else
+ charIndex++;
+ }
+ typeSignature.getChars(start, charIndex + 1, result[i++] = new char[charIndex - start + 1], 0);
+ return result;
+ }
+
private char[] getSource() {
if (this.source == null)
this.source = this.cu.getContents();
@@ -821,6 +1135,7 @@
}
private Expression parseMemberValue(char[] memberValue) {
+ // memberValue must not be null
if (this.parser == null) {
this.parser = new Parser(this.problemReporter, true);
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ASTHolderCUInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ASTHolderCUInfo.java
index 6990e7a..ec91dc1 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ASTHolderCUInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ASTHolderCUInfo.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,9 +10,14 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core;
+import java.util.HashMap;
+
import org.eclipse.jdt.core.dom.CompilationUnit;
public class ASTHolderCUInfo extends CompilationUnitElementInfo {
int astLevel;
+ boolean resolveBindings;
+ int reconcileFlags;
+ HashMap problems = null;
CompilationUnit ast;
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Assert.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Assert.java
deleted file mode 100644
index 627e3a4..0000000
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Assert.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.jdt.internal.core;
-
-/* This class is not intended to be instantiated. */
-public final class Assert {
-
-private Assert() {
- // cannot be instantiated
-}
-/** Asserts that an argument is legal. If the given boolean is
- * not <code>true</code>, an <code>IllegalArgumentException</code>
- * is thrown.
- *
- * @param expression the outcode of the check
- * @return <code>true</code> if the check passes (does not return
- * if the check fails)
- * @exception IllegalArgumentException if the legality test failed
- */
-public static boolean isLegal(boolean expression) {
- return isLegal(expression, ""); //$NON-NLS-1$
-}
-/** Asserts that an argument is legal. If the given boolean is
- * not <code>true</code>, an <code>IllegalArgumentException</code>
- * is thrown.
- * The given message is included in that exception, to aid debugging.
- *
- * @param expression the outcode of the check
- * @param message the message to include in the exception
- * @return <code>true</code> if the check passes (does not return
- * if the check fails)
- * @exception IllegalArgumentException if the legality test failed
- */
-public static boolean isLegal(boolean expression, String message) {
- if (!expression)
- throw new IllegalArgumentException(message);
- return expression;
-}
-/** Asserts that the given object is not <code>null</code>. If this
- * is not the case, some kind of unchecked exception is thrown.
- *
- * @param object the value to test
- * @exception IllegalArgumentException if the object is <code>null</code>
- */
-public static void isNotNull(Object object) {
- isNotNull(object, ""); //$NON-NLS-1$
-}
-/** Asserts that the given object is not <code>null</code>. If this
- * is not the case, some kind of unchecked exception is thrown.
- * The given message is included in that exception, to aid debugging.
- *
- * @param object the value to test
- * @param message the message to include in the exception
- * @exception IllegalArgumentException if the object is <code>null</code>
- */
-public static void isNotNull(Object object, String message) {
- if (object == null)
- throw new AssertionFailedException("null argument; " + message); //$NON-NLS-1$
-}
-/** Asserts that the given boolean is <code>true</code>. If this
- * is not the case, some kind of unchecked exception is thrown.
- *
- * @param expression the outcode of the check
- * @return <code>true</code> if the check passes (does not return
- * if the check fails)
- */
-public static boolean isTrue(boolean expression) {
- return isTrue(expression, ""); //$NON-NLS-1$
-}
-/** Asserts that the given boolean is <code>true</code>. If this
- * is not the case, some kind of unchecked exception is thrown.
- * The given message is included in that exception, to aid debugging.
- *
- * @param expression the outcode of the check
- * @param message the message to include in the exception
- * @return <code>true</code> if the check passes (does not return
- * if the check fails)
- */
-public static boolean isTrue(boolean expression, String message) {
- if (!expression)
- throw new AssertionFailedException("Assertion failed; " + message); //$NON-NLS-1$
- return expression;
-}
-
- public static class AssertionFailedException extends RuntimeException {
- private static final long serialVersionUID = -3179320974982211564L; // backward compatible
- public AssertionFailedException(String detail) {
- super(detail);
- }
- }
-}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BasicCompilationUnit.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BasicCompilationUnit.java
index 9d31c94..62845b2 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BasicCompilationUnit.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BasicCompilationUnit.java
@@ -29,7 +29,13 @@
*/
public class BasicCompilationUnit implements ICompilationUnit {
protected char[] contents;
- protected char[] fileName;
+
+ // Note that if this compiler ICompilationUnit's content is known in advance, the fileName is not used to retrieve this content.
+ // Instead it is used to keep enough information to recreate the IJavaElement corresponding to this compiler ICompilationUnit.
+ // Thus the fileName can be a path to a .class file, or even a path in a .jar to a .class file.
+ // (e.g. /P/lib/mylib.jar|org/eclipse/test/X.class)
+ protected char[] fileName;
+
protected char[][] packageName;
protected char[] mainTypeName;
protected String encoding;
@@ -113,7 +119,7 @@
start = separator;
int end = CharOperation.lastIndexOf('$', this.fileName);
- if (end == -1) {
+ if (end == -1 || !Util.isClassFileName(this.fileName)) {
end = CharOperation.lastIndexOf('.', this.fileName);
if (end == -1)
end = this.fileName.length;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BatchOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BatchOperation.java
index 9d55df6..142c2d5 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BatchOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BatchOperation.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BecomeWorkingCopyOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BecomeWorkingCopyOperation.java
index 932a72f..7fa514b 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BecomeWorkingCopyOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BecomeWorkingCopyOperation.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -39,13 +39,13 @@
if (!workingCopy.isPrimary()) {
// report added java delta for a non-primary working copy
- JavaElementDelta delta = new JavaElementDelta(this.getJavaModel());
+ JavaElementDelta delta = new JavaElementDelta(getJavaModel());
delta.added(workingCopy);
addDelta(delta);
} else {
if (workingCopy.getResource().isAccessible()) {
// report a F_PRIMARY_WORKING_COPY change delta for a primary working copy
- JavaElementDelta delta = new JavaElementDelta(this.getJavaModel());
+ JavaElementDelta delta = new JavaElementDelta(getJavaModel());
delta.changed(workingCopy, IJavaElementDelta.F_PRIMARY_WORKING_COPY);
addDelta(delta);
} else {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryField.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryField.java
index 6e5066c..9934a55 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryField.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryField.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,8 +10,10 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core;
+import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.IField;
+import org.eclipse.jdt.core.IJavaModelStatusConstants;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.internal.compiler.env.IBinaryField;
@@ -105,4 +107,24 @@
}
}
}
+public String getAttachedJavadoc(IProgressMonitor monitor) throws JavaModelException {
+ String contents = ((BinaryType) this.getDeclaringType()).getJavadocContents(monitor);
+ if (contents == null) return null;
+ int indexAnchor = contents.indexOf(
+ JavadocConstants.ANCHOR_PREFIX_START + this.getElementName() + JavadocConstants.ANCHOR_PREFIX_END);
+ if (indexAnchor == -1) throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.UNKNOWN_JAVADOC_FORMAT, this));
+ int indexOfEndLink = contents.indexOf(JavadocConstants.ANCHOR_SUFFIX, indexAnchor);
+ if (indexOfEndLink == -1) throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.UNKNOWN_JAVADOC_FORMAT, this));
+ int indexOfNextField = contents.indexOf(JavadocConstants.ANCHOR_PREFIX_START, indexOfEndLink);
+ int indexOfBottom = contents.indexOf(JavadocConstants.CONSTRUCTOR_DETAIL, indexOfEndLink);
+ if (indexOfBottom == -1) {
+ indexOfBottom = contents.indexOf(JavadocConstants.METHOD_DETAIL, indexOfEndLink);
+ if (indexOfBottom == -1) {
+ indexOfBottom = contents.indexOf(JavadocConstants.END_OF_CLASS_DATA, indexOfEndLink);
+ }
+ }
+ indexOfNextField= Math.min(indexOfNextField, indexOfBottom);
+ if (indexOfNextField == -1) throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.UNKNOWN_JAVADOC_FORMAT, this));
+ return contents.substring(indexOfEndLink + JavadocConstants.ANCHOR_SUFFIX_LENGTH, indexOfNextField);
+}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryMember.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryMember.java
index 79e894a..9ea6723 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryMember.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryMember.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -17,6 +17,7 @@
import org.eclipse.jdt.core.IJavaModelStatusConstants;
import org.eclipse.jdt.core.ISourceRange;
import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.compiler.CharOperation;
/**
* Common functionality for Binary member handles.
@@ -38,16 +39,24 @@
* @see JavaElement#generateInfos
*/
protected void generateInfos(Object info, HashMap newElements, IProgressMonitor pm) throws JavaModelException {
- Openable openableParent = (Openable)getOpenableParent();
- if (openableParent == null) return;
-
- ClassFileInfo openableParentInfo = (ClassFileInfo) JavaModelManager.getJavaModelManager().getInfo(openableParent);
- if (openableParentInfo == null) {
+ Openable openableParent = (Openable) getOpenableParent();
+ if (JavaModelManager.getJavaModelManager().getInfo(openableParent) == null) {
openableParent.generateInfos(openableParent.createElementInfo(), newElements, pm);
- openableParentInfo = (ClassFileInfo)newElements.get(openableParent);
}
- if (openableParentInfo == null) return;
- openableParentInfo.getBinaryChildren(newElements); // forces the initialization
+}
+public String[] getCategories() throws JavaModelException {
+ SourceMapper mapper= getSourceMapper();
+ if (mapper != null) {
+ // ensure the class file's buffer is open so that categories are computed
+ ((ClassFile)getClassFile()).getBuffer();
+
+ if (mapper.categories != null) {
+ String[] categories = (String[]) mapper.categories.get(this);
+ if (categories != null)
+ return categories;
+ }
+ }
+ return CharOperation.NO_STRINGS;
}
public String getKey() {
try {
@@ -72,7 +81,7 @@
return mapper.getNameRange(this);
} else {
- return SourceMapper.fgUnknownRange;
+ return SourceMapper.UNKNOWN_RANGE;
}
}
/*
@@ -86,7 +95,7 @@
return mapper.getSourceRange(this);
} else {
- return SourceMapper.fgUnknownRange;
+ return SourceMapper.UNKNOWN_RANGE;
}
}
/*
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryMethod.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryMethod.java
index 1cedf39..09a7531 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryMethod.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryMethod.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,16 +10,14 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core;
+import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.*;
-import org.eclipse.jdt.core.Flags;
-import org.eclipse.jdt.core.IMethod;
-import org.eclipse.jdt.core.IType;
-import org.eclipse.jdt.core.JavaModelException;
-import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.compiler.SourceElementRequestorAdapter;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.env.IBinaryMethod;
+import org.eclipse.jdt.internal.compiler.env.IBinaryType;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
+import org.eclipse.jdt.internal.core.JavaModelManager.PerProjectInfo;
import org.eclipse.jdt.internal.core.util.Util;
/**
@@ -27,35 +25,6 @@
*/
/* package */ class BinaryMethod extends BinaryMember implements IMethod {
-
- class DecodeParametersNames extends SourceElementRequestorAdapter {
- String[] parametersNames;
-
- public void enterMethod(MethodInfo methodInfo) {
- if (methodInfo.parameterNames != null) {
- int length = methodInfo.parameterNames.length;
- this.parametersNames = new String[length];
- for (int i = 0; i < length; i++) {
- this.parametersNames[i] = new String(methodInfo.parameterNames[i]);
- }
- }
- }
-
- public void enterConstructor(MethodInfo methodInfo) {
- if (methodInfo.parameterNames != null) {
- int length = methodInfo.parameterNames.length;
- this.parametersNames = new String[length];
- for (int i = 0; i < length; i++) {
- this.parametersNames[i] = new String(methodInfo.parameterNames[i]);
- }
- }
- }
-
- public String[] getParametersNames() {
- return this.parametersNames;
- }
- }
-
/**
* The parameter type signatures of the method - stored locally
* to perform equality test. <code>null</code> indicates no
@@ -67,17 +36,15 @@
*/
protected String[] parameterNames;
- /**
- * An empty list of Strings
- */
- protected static final String[] NO_TYPES= new String[] {};
protected String[] exceptionTypes;
protected String returnType;
+
protected BinaryMethod(JavaElement parent, String name, String[] paramTypes) {
super(parent, name);
- Assert.isTrue(name.indexOf('.') == -1);
+ // Assertion disabled since bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=179011
+ // Assert.isTrue(name.indexOf('.') == -1);
if (paramTypes == null) {
- this.parameterTypes= NO_TYPES;
+ this.parameterTypes= CharOperation.NO_STRINGS;
} else {
this.parameterTypes= paramTypes;
}
@@ -100,7 +67,7 @@
if (this.exceptionTypes == null || this.exceptionTypes.length == 0) {
char[][] eTypeNames = info.getExceptionTypeNames();
if (eTypeNames == null || eTypeNames.length == 0) {
- this.exceptionTypes = NO_TYPES;
+ this.exceptionTypes = CharOperation.NO_STRINGS;
} else {
eTypeNames = ClassFile.translatedNames(eTypeNames);
this.exceptionTypes = new String[eTypeNames.length];
@@ -168,42 +135,219 @@
* Look for source attachment information to retrieve the actual parameter names as stated in source.
*/
public String[] getParameterNames() throws JavaModelException {
- if (this.parameterNames == null) {
+ if (this.parameterNames != null)
+ return this.parameterNames;
- // force source mapping if not already done
- IType type = (IType) getParent();
- SourceMapper mapper = getSourceMapper();
- if (mapper != null) {
- char[][] paramNames = mapper.getMethodParameterNames(this);
-
- // map source and try to find parameter names
- if(paramNames == null) {
- char[] source = mapper.findSource(type);
- if (source != null){
- mapper.mapSource(type, source);
- }
- paramNames = mapper.getMethodParameterNames(this);
+ // force source mapping if not already done
+ IType type = (IType) getParent();
+ SourceMapper mapper = getSourceMapper();
+ if (mapper != null) {
+ char[][] paramNames = mapper.getMethodParameterNames(this);
+
+ // map source and try to find parameter names
+ if(paramNames == null) {
+ IBinaryType info = (IBinaryType) ((BinaryType) getDeclaringType()).getElementInfo();
+ char[] source = mapper.findSource(type, info);
+ if (source != null){
+ mapper.mapSource(type, source, info);
}
-
- // if parameter names exist, convert parameter names to String array
- if(paramNames != null) {
- this.parameterNames = new String[paramNames.length];
- for (int i = 0; i < paramNames.length; i++) {
- this.parameterNames[i] = new String(paramNames[i]);
- }
- }
+ paramNames = mapper.getMethodParameterNames(this);
}
- // if still no parameter names, produce fake ones
- if (this.parameterNames == null) {
- IBinaryMethod info = (IBinaryMethod) getElementInfo();
- int paramCount = Signature.getParameterCount(new String(info.getMethodDescriptor()));
- this.parameterNames = new String[paramCount];
- for (int i = 0; i < paramCount; i++) {
- this.parameterNames[i] = "arg" + i; //$NON-NLS-1$
+
+ // if parameter names exist, convert parameter names to String array
+ if(paramNames != null) {
+ this.parameterNames = new String[paramNames.length];
+ for (int i = 0; i < paramNames.length; i++) {
+ this.parameterNames[i] = new String(paramNames[i]);
}
+ return this.parameterNames;
}
}
- return this.parameterNames;
+
+ // try to see if we can retrieve the names from the attached javadoc
+ IBinaryMethod info = (IBinaryMethod) getElementInfo();
+ final int paramCount = Signature.getParameterCount(new String(info.getMethodDescriptor()));
+ if (paramCount != 0) {
+ // don't try to look for javadoc for synthetic methods
+ int modifiers = this.getFlags();
+ if ((modifiers & ClassFileConstants.AccSynthetic) != 0) {
+ return this.parameterNames = getRawParameterNames(paramCount);
+ }
+ String javadocContents = null;
+ IType declaringType = this.getDeclaringType();
+ PerProjectInfo projectInfo = JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(this.getJavaProject().getProject());
+ synchronized (projectInfo.javadocCache) {
+ javadocContents = (String) projectInfo.javadocCache.get(declaringType);
+ if (javadocContents == null) {
+ projectInfo.javadocCache.put(declaringType, BinaryType.EMPTY_JAVADOC);
+ }
+ }
+ if (javadocContents == null) {
+ long timeOut = 50; // default value
+ try {
+ String option = this.getJavaProject().getOption(JavaCore.TIMEOUT_FOR_PARAMETER_NAME_FROM_ATTACHED_JAVADOC, true);
+ if (option != null) {
+ timeOut = Long.parseLong(option);
+ }
+ } catch(NumberFormatException e) {
+ // ignore
+ }
+ if (timeOut == 0) {
+ // don't try to fetch the values
+ return this.parameterNames = getRawParameterNames(paramCount);
+ }
+ final class ParametersNameCollector {
+ String javadoc;
+ public void setJavadoc(String s) {
+ this.javadoc = s;
+ }
+ public String getJavadoc() {
+ return this.javadoc;
+ }
+ }
+ /*
+ * The declaring type is not in the cache yet. The thread wil retrieve the javadoc contents
+ */
+ final ParametersNameCollector nameCollector = new ParametersNameCollector();
+ Thread collect = new Thread() {
+ public void run() {
+ try {
+ // this call has a side-effect on the per project info cache
+ nameCollector.setJavadoc(BinaryMethod.this.getAttachedJavadoc(null));
+ } catch (JavaModelException e) {
+ // ignore
+ }
+ synchronized(nameCollector) {
+ nameCollector.notify();
+ }
+ }
+ };
+ collect.start();
+ synchronized(nameCollector) {
+ try {
+ nameCollector.wait(timeOut);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ }
+ javadocContents = nameCollector.getJavadoc();
+ } else if (javadocContents != BinaryType.EMPTY_JAVADOC){
+ // need to extract the part relative to the binary method since javadoc contains the javadoc for the declaring type
+ try {
+ javadocContents = extractJavadoc(declaringType, javadocContents);
+ } catch(JavaModelException e) {
+ // ignore
+ }
+ } else {
+ // let's see if we can retrieve them from the debug infos
+ char[][] argumentNames = info.getArgumentNames();
+ if (argumentNames != null && argumentNames.length == paramCount) {
+ String[] names = new String[paramCount];
+ for (int i = 0; i < paramCount; i++) {
+ names[i] = new String(argumentNames[i]);
+ }
+ return this.parameterNames = names;
+ }
+ return getRawParameterNames(paramCount);
+ }
+ if (javadocContents != null && javadocContents != BinaryType.EMPTY_JAVADOC) {
+ final int indexOfOpenParen = javadocContents.indexOf('(');
+ if (indexOfOpenParen != -1) {
+ final int indexOfClosingParen = javadocContents.indexOf(')', indexOfOpenParen);
+ if (indexOfClosingParen != -1) {
+ final char[] paramsSource =
+ CharOperation.replace(
+ javadocContents.substring(indexOfOpenParen + 1, indexOfClosingParen).toCharArray(),
+ " ".toCharArray(), //$NON-NLS-1$
+ new char[] {' '});
+ final char[][] params = splitParameters(paramsSource, paramCount);
+ final int paramsLength = params.length;
+ this.parameterNames = new String[paramsLength];
+ for (int i = 0; i < paramsLength; i++) {
+ final char[] param = params[i];
+ int indexOfSpace = CharOperation.lastIndexOf(' ', param);
+ if (indexOfSpace != -1) {
+ this.parameterNames[i] = String.valueOf(param, indexOfSpace + 1, param.length - indexOfSpace -1);
+ } else {
+ this.parameterNames[i] = "arg" + i; //$NON-NLS-1$
+ }
+ }
+ return this.parameterNames;
+ }
+ }
+ }
+ // let's see if we can retrieve them from the debug infos
+ char[][] argumentNames = info.getArgumentNames();
+ if (argumentNames != null && argumentNames.length == paramCount) {
+ String[] names = new String[paramCount];
+ for (int i = 0; i < paramCount; i++) {
+ names[i] = new String(argumentNames[i]);
+ }
+ return this.parameterNames = names;
+ }
+ }
+ // if still no parameter names, produce fake ones
+ return this.parameterNames = getRawParameterNames(paramCount);
+}
+private char[][] splitParameters(char[] parametersSource, int paramCount) {
+ // we have generic types as one of the parameter types
+ char[][] params = new char[paramCount][];
+ int paramIndex = 0;
+ int index = 0;
+ int balance = 0;
+ int length = parametersSource.length;
+ int start = 0;
+ while(index < length) {
+ switch (parametersSource[index]) {
+ case '<':
+ balance++;
+ index++;
+ while(index < length && parametersSource[index] != '>') {
+ index++;
+ }
+ break;
+ case '>' :
+ balance--;
+ index++;
+ break;
+ case ',' :
+ if (balance == 0 && paramIndex < paramCount) {
+ params[paramIndex++] = CharOperation.subarray(parametersSource, start, index);
+ start = index + 1;
+ }
+ index++;
+ break;
+ case '&' :
+ if ((index + 4) < length) {
+ if (parametersSource[index + 1] == 'l'
+ && parametersSource[index + 2] == 't'
+ && parametersSource[index + 3] == ';') {
+ balance++;
+ index += 4;
+ } else if (parametersSource[index + 1] == 'g'
+ && parametersSource[index + 2] == 't'
+ && parametersSource[index + 3] == ';') {
+ balance--;
+ index += 4;
+ } else {
+ index++;
+ }
+ } else {
+ index++;
+ }
+ break;
+ default:
+ index++;
+ }
+ }
+ if (paramIndex < paramCount) {
+ params[paramIndex++] = CharOperation.subarray(parametersSource, start, index);
+ }
+ if (paramIndex != paramCount) {
+ // happens only for constructors with synthetic enclosing type in the signature
+ System.arraycopy(params, 0, (params = new char[paramIndex][]), 0, paramIndex);
+ }
+ return params;
}
/*
* @see IMethod
@@ -243,6 +387,19 @@
return CharOperation.toStrings(typeParams);
}
+public String[] getRawParameterNames() throws JavaModelException {
+ IBinaryMethod info = (IBinaryMethod) getElementInfo();
+ int paramCount = Signature.getParameterCount(new String(info.getMethodDescriptor()));
+ return getRawParameterNames(paramCount);
+}
+private String[] getRawParameterNames(int paramCount) {
+ String[] result = new String[paramCount];
+ for (int i = 0; i < paramCount; i++) {
+ result[i] = "arg" + i; //$NON-NLS-1$
+ }
+ return result;
+}
+
/*
* @see IMethod
*/
@@ -281,6 +438,10 @@
* @see IMethod
*/
public boolean isConstructor() throws JavaModelException {
+ if (!this.getElementName().equals(this.parent.getElementName())) {
+ // faster than reaching the info
+ return false;
+ }
IBinaryMethod info = (IBinaryMethod) getElementInfo();
return info.isConstructor();
}
@@ -387,4 +548,96 @@
buffer.append(this.occurrenceCount);
}
}
+public String getAttachedJavadoc(IProgressMonitor monitor) throws JavaModelException {
+ IType declaringType = this.getDeclaringType();
+
+ String contents = ((BinaryType) declaringType).getJavadocContents(monitor);
+ return extractJavadoc(declaringType, contents);
+}
+private String extractJavadoc(IType declaringType, String contents) throws JavaModelException {
+ if (contents == null) return null;
+
+ String typeQualifiedName = null;
+ final boolean declaringTypeIsMember = declaringType.isMember();
+ if (declaringTypeIsMember) {
+ IType currentType = declaringType;
+ StringBuffer buffer = new StringBuffer();
+ while (currentType != null) {
+ buffer.insert(0, currentType.getElementName());
+ currentType = currentType.getDeclaringType();
+ if (currentType != null) {
+ buffer.insert(0, '.');
+ }
+ }
+ typeQualifiedName = new String(buffer.toString());
+ } else {
+ typeQualifiedName = declaringType.getElementName();
+ }
+ String methodName = this.getElementName();
+ if (this.isConstructor()) {
+ methodName = typeQualifiedName;
+ }
+ IBinaryMethod info = (IBinaryMethod) getElementInfo();
+ char[] genericSignature = info.getGenericSignature();
+ String anchor = null;
+ if (genericSignature != null) {
+ genericSignature = CharOperation.replaceOnCopy(genericSignature, '/', '.');
+ anchor = Util.toAnchor(genericSignature, methodName, Flags.isVarargs(this.getFlags()));
+ if (anchor == null) throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.UNKNOWN_JAVADOC_FORMAT, this));
+ } else {
+ anchor = Signature.toString(this.getSignature().replace('/', '.'), methodName, null, true, false, Flags.isVarargs(this.getFlags()));
+ }
+ if (declaringTypeIsMember) {
+ int depth = 0;
+ final String packageFragmentName = declaringType.getPackageFragment().getElementName();
+ // might need to remove a part of the signature corresponding to the synthetic argument
+ final IJavaProject javaProject = declaringType.getJavaProject();
+ char[][] typeNames = CharOperation.splitOn('.', typeQualifiedName.toCharArray());
+ if (!Flags.isStatic(declaringType.getFlags())) depth++;
+ StringBuffer typeName = new StringBuffer();
+ for (int i = 0, max = typeNames.length; i < max; i++) {
+ if (typeName.length() == 0) {
+ typeName.append(typeNames[i]);
+ } else {
+ typeName.append('.').append(typeNames[i]);
+ }
+ IType resolvedType = javaProject.findType(packageFragmentName, String.valueOf(typeName));
+ if (resolvedType != null && resolvedType.isMember() && !Flags.isStatic(resolvedType.getFlags())) depth++;
+ }
+ if (depth != 0) {
+ int indexOfOpeningParen = anchor.indexOf('(');
+ if (indexOfOpeningParen == -1) return null;
+ int index = indexOfOpeningParen;
+ indexOfOpeningParen++;
+ for (int i = 0; i < depth; i++) {
+ int indexOfComma = anchor.indexOf(',', index);
+ if (indexOfComma != -1) {
+ index = indexOfComma + 2;
+ }
+ }
+ anchor = anchor.substring(0, indexOfOpeningParen) + anchor.substring(index);
+ }
+ }
+ int indexAnchor = contents.indexOf(JavadocConstants.ANCHOR_PREFIX_START + anchor + JavadocConstants.ANCHOR_PREFIX_END);
+ if (indexAnchor == -1) {
+ return null; // method without javadoc
+ }
+ int indexOfEndLink = contents.indexOf(JavadocConstants.ANCHOR_SUFFIX, indexAnchor);
+ if (indexOfEndLink == -1) throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.UNKNOWN_JAVADOC_FORMAT, this));
+ int indexOfNextMethod = contents.indexOf(JavadocConstants.ANCHOR_PREFIX_START, indexOfEndLink);
+ // find bottom
+ int indexOfBottom = -1;
+ if (this.isConstructor()) {
+ indexOfBottom = contents.indexOf(JavadocConstants.METHOD_DETAIL, indexOfEndLink);
+ if (indexOfBottom == -1) {
+ indexOfBottom = contents.indexOf(JavadocConstants.END_OF_CLASS_DATA, indexOfEndLink);
+ }
+ } else {
+ indexOfBottom = contents.indexOf(JavadocConstants.END_OF_CLASS_DATA, indexOfEndLink);
+ }
+ if (indexOfBottom == -1) throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.UNKNOWN_JAVADOC_FORMAT, this));
+ indexOfNextMethod = Math.min(indexOfNextMethod, indexOfBottom);
+ if (indexOfNextMethod == -1) throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.UNKNOWN_JAVADOC_FORMAT, this));
+ return contents.substring(indexOfEndLink + JavadocConstants.ANCHOR_SUFFIX_LENGTH, indexOfNextMethod);
+}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryType.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryType.java
index 8a49849..3287cfc 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryType.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryType.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -11,18 +11,22 @@
package org.eclipse.jdt.internal.core;
import java.io.InputStream;
+import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
+import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.jdt.core.*;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.internal.codeassist.CompletionEngine;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.env.IBinaryType;
-import org.eclipse.jdt.internal.compiler.env.IGenericType;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
+import org.eclipse.jdt.internal.core.JavaModelManager.PerProjectInfo;
import org.eclipse.jdt.internal.core.hierarchy.TypeHierarchy;
import org.eclipse.jdt.internal.core.util.MementoTokenizer;
import org.eclipse.jdt.internal.core.util.Messages;
@@ -40,11 +44,10 @@
private static final IMethod[] NO_METHODS = new IMethod[0];
private static final IType[] NO_TYPES = new IType[0];
private static final IInitializer[] NO_INITIALIZERS = new IInitializer[0];
- private static final String[] NO_STRINGS = new String[0];
+ public static final String EMPTY_JAVADOC = org.eclipse.jdt.internal.compiler.util.Util.EMPTY_STRING;
protected BinaryType(JavaElement parent, String name) {
super(parent, name);
- Assert.isTrue(name.indexOf('.') == -1);
}
/*
* Remove my cached children from the Java Model
@@ -158,30 +161,40 @@
* @see IParent#getChildren()
*/
public IJavaElement[] getChildren() throws JavaModelException {
- // ensure present
- // fix for 1FWWVYT
- if (!exists()) {
- throw newNotPresentException();
- }
- // get children
ClassFileInfo cfi = getClassFileInfo();
- if (cfi.binaryChildren == null) {
- JavaModelManager manager = JavaModelManager.getJavaModelManager();
- boolean hadTemporaryCache = manager.hasTemporaryCache();
- try {
- Object info = manager.getInfo(this);
- HashMap newElements = manager.getTemporaryCache();
- cfi.readBinaryChildren(newElements, (IBinaryType)info);
- if (!hadTemporaryCache) {
- manager.putInfos(this, newElements);
- }
- } finally {
- if (!hadTemporaryCache) {
- manager.resetTemporaryCache();
+ return cfi.binaryChildren;
+}
+public IJavaElement[] getChildrenForCategory(String category) throws JavaModelException {
+ IJavaElement[] children = getChildren();
+ int length = children.length;
+ if (length == 0) return children;
+ SourceMapper mapper= getSourceMapper();
+ if (mapper != null) {
+ // ensure the class file's buffer is open so that categories are computed
+ ((ClassFile)getClassFile()).getBuffer();
+
+ HashMap categories = mapper.categories;
+ IJavaElement[] result = new IJavaElement[length];
+ int index = 0;
+ if (categories != null) {
+ for (int i = 0; i < length; i++) {
+ IJavaElement child = children[i];
+ String[] cats = (String[]) categories.get(child);
+ if (cats != null) {
+ for (int j = 0, length2 = cats.length; j < length2; j++) {
+ if (cats[j].equals(category)) {
+ result[index++] = child;
+ break;
+ }
+ }
+ }
}
}
+ if (index < length)
+ System.arraycopy(result, 0, result = new IJavaElement[index], 0, index);
+ return result;
}
- return cfi.binaryChildren;
+ return NO_ELEMENTS;
}
protected ClassFileInfo getClassFileInfo() throws JavaModelException {
ClassFile cf = (ClassFile)this.parent;
@@ -238,6 +251,12 @@
}
}
}
+public Object getElementInfo(IProgressMonitor monitor) throws JavaModelException {
+ JavaModelManager manager = JavaModelManager.getJavaModelManager();
+ Object info = manager.getInfo(this);
+ if (info != null && info != JavaModelCache.NON_EXISTING_JAR_TYPE_INFO) return info;
+ return openWhenClosed(createElementInfo(), monitor);
+}
/*
* @see IJavaElement
*/
@@ -341,17 +360,13 @@
String[] parameters = new String[params.size()];
params.toArray(parameters);
JavaElement method = (JavaElement)getMethod(selector, parameters);
- if (token != null) {
- switch (token.charAt(0)) {
- case JEM_TYPE:
- case JEM_TYPE_PARAMETER:
- case JEM_LOCALVARIABLE:
- return method.getHandleFromMemento(token, memento, workingCopyOwner);
- default:
- return method;
- }
- } else {
- return method;
+ switch (token.charAt(0)) {
+ case JEM_TYPE:
+ case JEM_TYPE_PARAMETER:
+ case JEM_LOCALVARIABLE:
+ return method.getHandleFromMemento(token, memento, workingCopyOwner);
+ default:
+ return method;
}
case JEM_TYPE:
String typeName;
@@ -472,6 +487,24 @@
}
}
+public String getSourceFileName(IBinaryType info) {
+ if (info == null) {
+ try {
+ info = (IBinaryType) getElementInfo();
+ } catch (JavaModelException e) {
+ // default to using the outer most declaring type name
+ IType type = this;
+ IType enclosingType = getDeclaringType();
+ while (enclosingType != null) {
+ type = enclosingType;
+ enclosingType = type.getDeclaringType();
+ }
+ return type.getElementName() + Util.defaultJavaExtension();
+ }
+ }
+ return sourceFileName(info);
+}
+
/*
* @see IType#getSuperclassName()
*/
@@ -491,7 +524,7 @@
char[][] names= info.getInterfaceNames();
int length;
if (names == null || (length = names.length) == 0) {
- return NO_STRINGS;
+ return CharOperation.NO_STRINGS;
}
names= ClassFile.translatedNames(names);
String[] strings= new String[length];
@@ -543,7 +576,7 @@
char[][] names= info.getInterfaceNames();
int length;
if (names == null || (length = names.length) == 0) {
- return NO_STRINGS;
+ return CharOperation.NO_STRINGS;
}
names= ClassFile.translatedNames(names);
String[] strings= new String[length];
@@ -635,7 +668,7 @@
*/
public boolean isClass() throws JavaModelException {
IBinaryType info = (IBinaryType) getElementInfo();
- return info.getKind() == IGenericType.CLASS_DECL;
+ return TypeDeclaration.kind(info.getModifiers()) == TypeDeclaration.CLASS_DECL;
}
@@ -645,7 +678,7 @@
*/
public boolean isEnum() throws JavaModelException {
IBinaryType info = (IBinaryType) getElementInfo();
- return info.getKind() == IGenericType.ENUM_DECL;
+ return TypeDeclaration.kind(info.getModifiers()) == TypeDeclaration.ENUM_DECL;
}
/*
@@ -653,9 +686,9 @@
*/
public boolean isInterface() throws JavaModelException {
IBinaryType info = (IBinaryType) getElementInfo();
- switch (info.getKind()) {
- case IGenericType.INTERFACE_DECL:
- case IGenericType.ANNOTATION_TYPE_DECL: // annotation is interface too
+ switch (TypeDeclaration.kind(info.getModifiers())) {
+ case TypeDeclaration.INTERFACE_DECL:
+ case TypeDeclaration.ANNOTATION_TYPE_DECL: // annotation is interface too
return true;
}
return false;
@@ -666,7 +699,7 @@
*/
public boolean isAnnotation() throws JavaModelException {
IBinaryType info = (IBinaryType) getElementInfo();
- return info.getKind() == IGenericType.ANNOTATION_TYPE_DECL;
+ return TypeDeclaration.kind(info.getModifiers()) == TypeDeclaration.ANNOTATION_TYPE_DECL;
}
/*
@@ -898,7 +931,8 @@
return getElementName() + Util.defaultJavaExtension();
}
} else {
- return new String(sourceFileName);
+ int index = CharOperation.lastIndexOf('/', sourceFileName);
+ return new String(sourceFileName, index + 1, sourceFileName.length - index - 1);
}
}
/*
@@ -934,4 +968,99 @@
else
buffer.append("<anonymous>"); //$NON-NLS-1$
}
+public String getAttachedJavadoc(IProgressMonitor monitor) throws JavaModelException {
+ final String contents = getJavadocContents(monitor);
+ if (contents == null) return null;
+ final int indexOfStartOfClassData = contents.indexOf(JavadocConstants.START_OF_CLASS_DATA);
+ if (indexOfStartOfClassData == -1) throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.UNKNOWN_JAVADOC_FORMAT, this));
+ int indexOfNextSummary = contents.indexOf(JavadocConstants.NESTED_CLASS_SUMMARY);
+ if (this.isEnum() && indexOfNextSummary == -1) {
+ // try to find enum constant summary start
+ indexOfNextSummary = contents.indexOf(JavadocConstants.ENUM_CONSTANT_SUMMARY);
+ }
+ if (this.isAnnotation() && indexOfNextSummary == -1) {
+ // try to find required enum constant summary start
+ indexOfNextSummary = contents.indexOf(JavadocConstants.ANNOTATION_TYPE_REQUIRED_MEMBER_SUMMARY);
+ if (indexOfNextSummary == -1) {
+ // try to find optional enum constant summary start
+ indexOfNextSummary = contents.indexOf(JavadocConstants.ANNOTATION_TYPE_OPTIONAL_MEMBER_SUMMARY);
+ }
+ }
+ if (indexOfNextSummary == -1) {
+ // try to find field summary start
+ indexOfNextSummary = contents.indexOf(JavadocConstants.FIELD_SUMMARY);
+ }
+ if (indexOfNextSummary == -1) {
+ // try to find constructor summary start
+ indexOfNextSummary = contents.indexOf(JavadocConstants.CONSTRUCTOR_SUMMARY);
+ }
+ if (indexOfNextSummary == -1) {
+ // try to find method summary start
+ indexOfNextSummary = contents.indexOf(JavadocConstants.METHOD_SUMMARY);
+ }
+ if (indexOfNextSummary == -1) {
+ // we take the end of class data
+ indexOfNextSummary = contents.indexOf(JavadocConstants.END_OF_CLASS_DATA);
+ }
+ if (indexOfNextSummary == -1) {
+ throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.UNKNOWN_JAVADOC_FORMAT, this));
+ }
+ /*
+ * Check out to cut off the hierarchy see 119844
+ * We remove what the contents between the start of class data and the first <P>
+ */
+ int start = indexOfStartOfClassData + JavadocConstants.START_OF_CLASS_DATA_LENGTH;
+ int indexOfFirstParagraph = contents.indexOf("<P>", start); //$NON-NLS-1$
+ if (indexOfFirstParagraph == -1) {
+ indexOfFirstParagraph = contents.indexOf("<p>", start); //$NON-NLS-1$
+ }
+ if (indexOfFirstParagraph != -1 && indexOfFirstParagraph < indexOfNextSummary) {
+ start = indexOfFirstParagraph;
+ }
+ return contents.substring(start, indexOfNextSummary);
+}
+public String getJavadocContents(IProgressMonitor monitor) throws JavaModelException {
+ PerProjectInfo projectInfo = JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(this.getJavaProject().getProject());
+ String cachedJavadoc = null;
+ synchronized (projectInfo.javadocCache) {
+ cachedJavadoc = (String) projectInfo.javadocCache.get(this);
+ }
+ if (cachedJavadoc != null && cachedJavadoc != EMPTY_JAVADOC) {
+ return cachedJavadoc;
+ }
+ URL baseLocation= getJavadocBaseLocation();
+ if (baseLocation == null) {
+ return null;
+ }
+ StringBuffer pathBuffer = new StringBuffer(baseLocation.toExternalForm());
+
+ if (!(pathBuffer.charAt(pathBuffer.length() - 1) == '/')) {
+ pathBuffer.append('/');
+ }
+ IPackageFragment pack= this.getPackageFragment();
+ String typeQualifiedName = null;
+ if (this.isMember()) {
+ IType currentType = this;
+ StringBuffer typeName = new StringBuffer();
+ while (currentType != null) {
+ typeName.insert(0, currentType.getElementName());
+ currentType = currentType.getDeclaringType();
+ if (currentType != null) {
+ typeName.insert(0, '.');
+ }
+ }
+ typeQualifiedName = new String(typeName.toString());
+ } else {
+ typeQualifiedName = this.getElementName();
+ }
+
+ pathBuffer.append(pack.getElementName().replace('.', '/')).append('/').append(typeQualifiedName).append(JavadocConstants.HTML_EXTENSION);
+
+ if (monitor != null && monitor.isCanceled()) throw new OperationCanceledException();
+ final String contents = getURLContents(String.valueOf(pathBuffer));
+ synchronized (projectInfo.javadocCache) {
+ projectInfo.javadocCache.put(this, contents);
+ }
+ return contents;
+}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryTypeConverter.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryTypeConverter.java
index 5182406..0e33b88 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryTypeConverter.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryTypeConverter.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -33,7 +33,8 @@
import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
-import org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
import org.eclipse.jdt.internal.core.util.Util;
/**
@@ -49,7 +50,7 @@
char[][] packageName = Util.toCharArrays(pkg.names);
if (packageName.length > 0) {
- compilationUnit.currentPackage = new ImportReference(packageName, new long[]{0}, false, CompilerModifiers.AccDefault);
+ compilationUnit.currentPackage = new ImportReference(packageName, new long[]{0}, false, ClassFileConstants.AccDefault);
}
/* convert type */
@@ -88,7 +89,7 @@
if (method.isConstructor()) {
ConstructorDeclaration decl = new ConstructorDeclaration(compilationResult);
- decl.isDefaultConstructor = false;
+ decl.bits &= ~ASTNode.IsDefaultConstructor;
methodDeclaration = decl;
} else {
MethodDeclaration decl = type.isAnnotation() ? new AnnotationMethodDeclaration(compilationResult) : new MethodDeclaration(compilationResult);
@@ -116,7 +117,7 @@
argumentNames[i].toCharArray(),
0,
typeReference,
- CompilerModifiers.AccDefault);
+ ClassFileConstants.AccDefault);
// do not care whether was final or not
}
@@ -138,7 +139,7 @@
TypeDeclaration typeDeclaration = new TypeDeclaration(compilationResult);
if (type.getDeclaringType() != null) {
- typeDeclaration.bits |= ASTNode.IsMemberTypeMASK;
+ typeDeclaration.bits |= ASTNode.IsMemberType;
}
typeDeclaration.name = type.getElementName().toCharArray();
typeDeclaration.modifiers = type.getFlags();
@@ -202,7 +203,7 @@
AbstractMethodDeclaration method =convert(methods[i], type, compilationResult);
boolean isAbstract;
if ((isAbstract = method.isAbstract()) || isInterface) { // fix-up flag
- method.modifiers |= CompilerModifiers.AccSemicolonBody;
+ method.modifiers |= ExtraCompilerModifiers.AccSemicolonBody;
}
if (isAbstract) {
hasAbstractMethods = true;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Buffer.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Buffer.java
index c24fbd0..de332fa 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Buffer.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Buffer.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Tim Hanson (thanson@bea.com) - patch for https://bugs.eclipse.org/bugs/show_bug.cgi?id=126673
*******************************************************************************/
package org.eclipse.jdt.internal.core;
@@ -19,7 +20,8 @@
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.ISafeRunnable;
-import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.SafeRunner;
+import org.eclipse.core.runtime.content.IContentDescription;
import org.eclipse.jdt.core.*;
import org.eclipse.jdt.internal.core.util.Util;
@@ -105,7 +107,9 @@
this.flags |= F_IS_CLOSED;
}
notifyChanged(event); // notify outside of synchronized block
- this.changeListeners = null;
+ synchronized(this) { // ensure that no other thread is adding/removing a listener at the same time (https://bugs.eclipse.org/bugs/show_bug.cgi?id=126673)
+ this.changeListeners = null;
+ }
}
/**
* @see IBuffer
@@ -253,7 +257,7 @@
if (listeners != null) {
for (int i = 0, size = listeners.size(); i < size; ++i) {
final IBufferChangedListener listener = (IBufferChangedListener) listeners.get(i);
- Platform.run(new ISafeRunnable() {
+ SafeRunner.run(new ISafeRunnable() {
public void handleException(Throwable exception) {
Util.log(exception, "Exception occurred in listener of buffer change notification"); //$NON-NLS-1$
}
@@ -334,6 +338,10 @@
// use a platform operation to update the resource contents
try {
+ String stringContents = this.getContents();
+ if (stringContents == null) return;
+
+ // Get encoding
String encoding = null;
try {
encoding = this.file.getCharset();
@@ -341,13 +349,27 @@
catch (CoreException ce) {
// use no encoding
}
- String stringContents = this.getContents();
- if (stringContents == null) return;
+
+ // Create bytes array
byte[] bytes = encoding == null
? stringContents.getBytes()
: stringContents.getBytes(encoding);
- ByteArrayInputStream stream = new ByteArrayInputStream(bytes);
+ // Special case for UTF-8 BOM files
+ // see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=110576
+ if (encoding != null && encoding.equals(org.eclipse.jdt.internal.compiler.util.Util.UTF_8)) {
+ IContentDescription description = this.file.getContentDescription();
+ if (description != null && description.getProperty(IContentDescription.BYTE_ORDER_MARK) != null) {
+ int bomLength= IContentDescription.BOM_UTF_8.length;
+ byte[] bytesWithBOM= new byte[bytes.length + bomLength];
+ System.arraycopy(IContentDescription.BOM_UTF_8, 0, bytesWithBOM, 0, bomLength);
+ System.arraycopy(bytes, 0, bytesWithBOM, bomLength, bytes.length);
+ bytes= bytesWithBOM;
+ }
+ }
+
+ // Set file contents
+ ByteArrayInputStream stream = new ByteArrayInputStream(bytes);
if (this.file.exists()) {
this.file.setContents(
stream,
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BufferCache.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BufferCache.java
index c5252ab..3e35339 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BufferCache.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BufferCache.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,6 +10,8 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core;
+import java.util.ArrayList;
+
import org.eclipse.jdt.core.IBuffer;
import org.eclipse.jdt.internal.core.util.LRUCache;
@@ -17,6 +19,8 @@
* An LRU cache of <code>IBuffers</code>.
*/
public class BufferCache extends OverflowingLRUCache {
+
+ private ThreadLocal buffersToClose = new ThreadLocal();
/**
* Constructs a new buffer cache of the given size.
*/
@@ -44,10 +48,25 @@
if (!((Openable)buffer.getOwner()).canBufferBeRemovedFromCache(buffer)) {
return false;
} else {
- buffer.close();
+ ArrayList buffers = (ArrayList) this.buffersToClose.get();
+ if (buffers == null) {
+ buffers = new ArrayList();
+ this.buffersToClose.set(buffers);
+ }
+ buffers.add(buffer);
return true;
}
}
+
+void closeBuffers() {
+ ArrayList buffers = (ArrayList) this.buffersToClose.get();
+ if (buffers == null)
+ return;
+ this.buffersToClose.set(null);
+ for (int i = 0, length = buffers.size(); i < length; i++) {
+ ((IBuffer) buffers.get(i)).close();
+ }
+}
/**
* Returns a new instance of the reciever.
*/
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BufferFactoryWrapper.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BufferFactoryWrapper.java
index ca2f16c..036677f 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BufferFactoryWrapper.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BufferFactoryWrapper.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BufferManager.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BufferManager.java
index 5ade7f2..3bbe868 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BufferManager.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BufferManager.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -32,7 +32,7 @@
* LRU cache of buffers. The key and value for an entry
* in the table is the identical buffer.
*/
- protected OverflowingLRUCache openBuffers = new BufferCache(60);
+ private BufferCache openBuffers = new BufferCache(60);
/**
* @deprecated
@@ -42,7 +42,7 @@
* @deprecated
*/
public IBuffer createBuffer(IOpenable owner) {
- return BufferManager.this.createBuffer(owner);
+ return BufferManager.createBuffer(owner);
}
};
@@ -54,12 +54,16 @@
String owner = ((Openable)buffer.getOwner()).toStringWithAncestors();
System.out.println("Adding buffer for " + owner); //$NON-NLS-1$
}
- this.openBuffers.put(buffer.getOwner(), buffer);
+ synchronized (this.openBuffers) {
+ this.openBuffers.put(buffer.getOwner(), buffer);
+ }
+ // close buffers that were removed from the cache if space was needed
+ this.openBuffers.closeBuffers();
if (VERBOSE) {
System.out.println("-> Buffer cache filling ratio = " + NumberFormat.getInstance().format(this.openBuffers.fillingRatio()) + "%"); //$NON-NLS-1$//$NON-NLS-2$
}
}
-public IBuffer createBuffer(IOpenable owner) {
+public static IBuffer createBuffer(IOpenable owner) {
IJavaElement element = (IJavaElement)owner;
IResource resource = element.getResource();
return
@@ -68,13 +72,24 @@
owner,
element.isReadOnly());
}
+public static IBuffer createNullBuffer(IOpenable owner) {
+ IJavaElement element = (IJavaElement)owner;
+ IResource resource = element.getResource();
+ return
+ new NullBuffer(
+ resource instanceof IFile ? (IFile)resource : null,
+ owner,
+ element.isReadOnly());
+}
/**
* Returns the open buffer associated with the given owner,
* or <code>null</code> if the owner does not have an open
* buffer associated with it.
*/
public IBuffer getBuffer(IOpenable owner) {
- return (IBuffer)this.openBuffers.get(owner);
+ synchronized (this.openBuffers) {
+ return (IBuffer)this.openBuffers.get(owner);
+ }
}
/**
* Returns the default buffer manager.
@@ -101,10 +116,14 @@
* @return Enumeration of IBuffer
*/
public Enumeration getOpenBuffers() {
+ Enumeration result;
synchronized (this.openBuffers) {
this.openBuffers.shrink();
- return this.openBuffers.elements();
+ result = this.openBuffers.elements();
}
+ // close buffers that were removed from the cache if space was needed
+ this.openBuffers.closeBuffers();
+ return result;
}
/**
@@ -115,7 +134,11 @@
String owner = ((Openable)buffer.getOwner()).toStringWithAncestors();
System.out.println("Removing buffer for " + owner); //$NON-NLS-1$
}
- this.openBuffers.remove(buffer.getOwner());
+ synchronized (this.openBuffers) {
+ this.openBuffers.remove(buffer.getOwner());
+ }
+ // close buffers that were removed from the cache (should be only one)
+ this.openBuffers.closeBuffers();
if (VERBOSE) {
System.out.println("-> Buffer cache filling ratio = " + NumberFormat.getInstance().format(this.openBuffers.fillingRatio()) + "%"); //$NON-NLS-1$//$NON-NLS-2$
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CancelableNameEnvironment.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CancelableNameEnvironment.java
index f62da56..ef0ea71 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CancelableNameEnvironment.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CancelableNameEnvironment.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004 IBM Corporation and others.
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -50,8 +50,8 @@
return super.findType(compoundTypeName);
}
- public void findTypes(char[] prefix, boolean findMembers, ISearchRequestor storage) {
+ public void findTypes(char[] prefix, boolean findMembers, boolean camelCaseMatch, int searchFor, ISearchRequestor storage) {
checkCanceled();
- super.findTypes(prefix, findMembers, storage);
+ super.findTypes(prefix, findMembers, camelCaseMatch, searchFor, storage);
}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CancelableProblemFactory.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CancelableProblemFactory.java
index 8108478..8359de0 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CancelableProblemFactory.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CancelableProblemFactory.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004 IBM Corporation and others.
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -12,7 +12,7 @@
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
-import org.eclipse.jdt.core.compiler.IProblem;
+import org.eclipse.jdt.core.compiler.CategorizedProblem;
import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
@@ -25,9 +25,9 @@
this.monitor = monitor;
}
- public IProblem createProblem(char[] originatingFileName, int problemId, String[] problemArguments, String[] messageArguments, int severity, int startPosition, int endPosition, int lineNumber) {
+ public CategorizedProblem createProblem(char[] originatingFileName, int problemId, String[] problemArguments, String[] messageArguments, int severity, int startPosition, int endPosition, int lineNumber, int columnNumber) {
if (this.monitor != null && this.monitor.isCanceled())
throw new AbortCompilation(true/*silent*/, new OperationCanceledException());
- return super.createProblem(originatingFileName, problemId, problemArguments, messageArguments, severity, startPosition, endPosition, lineNumber);
+ return super.createProblem(originatingFileName, problemId, problemArguments, messageArguments, severity, startPosition, endPosition, lineNumber, columnNumber);
}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ChangeClasspathOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ChangeClasspathOperation.java
new file mode 100755
index 0000000..bef87e4
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ChangeClasspathOperation.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core;
+
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.JavaModelException;
+
+/*
+ * Abstract class for operations that change the classpath
+ */
+public abstract class ChangeClasspathOperation extends JavaModelOperation {
+
+ protected boolean canChangeResources;
+
+ public ChangeClasspathOperation(IJavaElement[] elements, boolean canChangeResources) {
+ super(elements);
+ this.canChangeResources = canChangeResources;
+ }
+
+ protected boolean canModifyRoots() {
+ // changing the classpath can modify roots
+ return true;
+ }
+
+ /*
+ * The resolved classpath of the given project may have changed:
+ * - generate a delta
+ * - trigger indexing
+ * - update project references
+ * - create resolved classpath markers
+ */
+ protected void classpathChanged(JavaProject project) throws JavaModelException {
+ DeltaProcessingState state = JavaModelManager.getJavaModelManager().deltaState;
+ DeltaProcessor deltaProcessor = state.getDeltaProcessor();
+ ClasspathChange change = (ClasspathChange) deltaProcessor.classpathChanges.get(project.getProject());
+ if (this.canChangeResources) {
+ // workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=177922
+ if (isTopLevelOperation() && !ResourcesPlugin.getWorkspace().isTreeLocked()) {
+ new ClasspathValidation(project).validate();
+ }
+
+ // delta, indexing and classpath markers are going to be created by the delta processor
+ // while handling the .classpath file change
+
+ // however ensure project references are updated
+ // since some clients rely on the project references when run inside an IWorkspaceRunnable
+ new ProjectReferenceChange(project, change.oldResolvedClasspath).updateProjectReferencesIfNecessary();
+ } else {
+ JavaElementDelta delta = new JavaElementDelta(getJavaModel());
+ int result = change.generateDelta(delta);
+ if ((result & ClasspathChange.HAS_DELTA) != 0) {
+ // create delta
+ addDelta(delta);
+
+ // ensure indexes are updated
+ change.requestIndexing();
+
+ // ensure classpath is validated on next build
+ state.addClasspathValidation(project);
+ }
+ if ((result & ClasspathChange.HAS_PROJECT_CHANGE) != 0) {
+ // ensure project references are updated on next build
+ state.addProjectReferenceChange(project, change.oldResolvedClasspath);
+ }
+ }
+ }
+
+ protected ISchedulingRule getSchedulingRule() {
+ return null; // no lock taken while changing classpath
+ }
+
+ public boolean isReadOnly() {
+ return !this.canChangeResources;
+ }
+
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFile.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFile.java
index 4ece9fb..976e7ee 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFile.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFile.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -11,32 +11,20 @@
package org.eclipse.jdt.internal.core;
import java.io.IOException;
+import java.util.HashMap;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
-import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.*;
-import org.eclipse.jdt.core.IBuffer;
-import org.eclipse.jdt.core.IClassFile;
-import org.eclipse.jdt.core.ICompilationUnit;
-import org.eclipse.jdt.core.IJavaElement;
-import org.eclipse.jdt.core.IJavaModelMarker;
-import org.eclipse.jdt.core.IJavaModelStatusConstants;
-import org.eclipse.jdt.core.IPackageFragmentRoot;
-import org.eclipse.jdt.core.IParent;
-import org.eclipse.jdt.core.ISourceRange;
-import org.eclipse.jdt.core.IType;
-import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
@@ -54,16 +42,32 @@
protected String name;
protected BinaryType binaryType = null;
- private boolean checkAutomaticSourceMapping;
+
/*
* Creates a handle to a class file.
*/
-protected ClassFile(PackageFragment parent, String name) {
+protected ClassFile(PackageFragment parent, String nameWithoutExtension) {
super(parent);
- // don't hold on the .class file extension to save memory
- // also make sure to copy the string (so that it doesn't hold on the underlying char[] that might be much bigger than necessary)
- this.name = new String(name.substring(0, name.length() - 6)); // don't hold on the .class file extension to save memory
- this.checkAutomaticSourceMapping = false;
+ this.name = nameWithoutExtension;
+}
+
+/*
+ * @see IClassFile#becomeWorkingCopy(IProblemRequestor, WorkingCopyOwner, IProgressMonitor)
+ */
+public ICompilationUnit becomeWorkingCopy(IProblemRequestor problemRequestor, WorkingCopyOwner owner, IProgressMonitor monitor) throws JavaModelException {
+ JavaModelManager manager = JavaModelManager.getJavaModelManager();
+ CompilationUnit workingCopy = new ClassFileWorkingCopy(this, owner == null ? DefaultWorkingCopyOwner.PRIMARY : owner);
+ JavaModelManager.PerWorkingCopyInfo perWorkingCopyInfo = manager.getPerWorkingCopyInfo(workingCopy, false/*don't create*/, true /*record usage*/, null/*no problem requestor needed*/);
+ if (perWorkingCopyInfo == null) {
+ // close cu and its children
+ close();
+
+ BecomeWorkingCopyOperation operation = new BecomeWorkingCopyOperation(workingCopy, problemRequestor);
+ operation.runOperation(monitor);
+
+ return workingCopy;
+ }
+ return perWorkingCopyInfo.workingCopy;
}
/**
@@ -89,9 +93,13 @@
}
// Make the type
- IType type = new BinaryType(this, simpleName(typeInfo.getName()));
- info.addChild(type);
+ IType type = getType();
+ info.setChildren(new IJavaElement[] {type});
newElements.put(type, typeInfo);
+
+ // Read children
+ ((ClassFileInfo) info).readBinaryChildren(this, (HashMap) newElements, typeInfo);
+
return true;
}
/**
@@ -161,15 +169,50 @@
* Returns a new element info for this element.
*/
protected Object createElementInfo() {
- return new ClassFileInfo(this);
+ return new ClassFileInfo();
}
public boolean equals(Object o) {
if (!(o instanceof ClassFile)) return false;
- return super.equals(o);
+ ClassFile other = (ClassFile) o;
+ return this.name.equals(other.name) && this.parent.equals(other.parent);
}
public boolean exists() {
return super.exists() && validateClassFile().isOK();
}
+public boolean existsUsingJarTypeCache() {
+ if (getPackageFragmentRoot().isArchive()) {
+ JavaModelManager manager = JavaModelManager.getJavaModelManager();
+ IType type = getType();
+ Object info = manager.getInfo(type);
+ if (info == JavaModelCache.NON_EXISTING_JAR_TYPE_INFO)
+ return false;
+ else if (info != null)
+ return true;
+ // info is null
+ JavaElementInfo parentInfo = (JavaElementInfo) manager.getInfo(getParent());
+ if (parentInfo != null) {
+ // if parent is open, this class file must be in its children
+ IJavaElement[] children = parentInfo.getChildren();
+ for (int i = 0, length = children.length; i < length; i++) {
+ if (this.name.equals(((ClassFile) children[i]).name))
+ return true;
+ }
+ return false;
+ }
+ try {
+ info = getJarBinaryTypeInfo((PackageFragment) getParent());
+ } catch (CoreException e) {
+ // leave info null
+ } catch (IOException e) {
+ // leave info null
+ } catch (ClassFormatException e) {
+ // leave info null
+ }
+ manager.putJarTypeInfo(type, info == null ? JavaModelCache.NON_EXISTING_JAR_TYPE_INFO : info);
+ return info != null;
+ } else
+ return exists();
+}
/**
* Finds the deepest <code>IJavaElement</code> in the hierarchy of
@@ -198,6 +241,19 @@
return elt;
}
/**
+ * @see ITypeRoot#findPrimaryType()
+ */
+public IType findPrimaryType() {
+ IType primaryType= getType();
+ if (primaryType.exists()) {
+ return primaryType;
+ }
+ return null;
+}
+public String getAttachedJavadoc(IProgressMonitor monitor) throws JavaModelException {
+ return this.getType().getAttachedJavadoc(monitor);
+}
+/**
* Returns the <code>ClassFileReader</code>specific for this IClassFile, based
* on its underlying resource, or <code>null</code> if unable to create
* the diet class file.
@@ -210,25 +266,10 @@
* or when this class file is not present in the JAR
*/
public IBinaryType getBinaryTypeInfo(IFile file) throws JavaModelException {
- JavaElement le = (JavaElement) getParent();
- if (le instanceof JarPackageFragment) {
+ JavaElement pkg = (JavaElement) getParent();
+ if (pkg instanceof JarPackageFragment) {
try {
- JarPackageFragmentRoot root = (JarPackageFragmentRoot) le.getParent();
- IBinaryType info = null;
- ZipFile zip = null;
- try {
- zip = root.getJar();
- PackageFragment pkg = (PackageFragment) le;
- String entryName = Util.concatWith(pkg.names, getElementName(), '/');
- ZipEntry ze = zip.getEntry(entryName);
- if (ze != null) {
- byte contents[] = org.eclipse.jdt.internal.compiler.util.Util.getZipEntryByteContent(ze, zip);
- String fileName = root.getHandleIdentifier() + IDependent.JAR_FILE_ENTRY_SEPARATOR + entryName;
- info = new ClassFileReader(contents, fileName.toCharArray(), true/*fully initialize so as to not keep a reference to the byte array*/);
- }
- } finally {
- JavaModelManager.getJavaModelManager().closeZipFile(zip);
- }
+ IBinaryType info = getJarBinaryTypeInfo((PackageFragment) pkg);
if (info == null) {
throw newNotPresentException();
}
@@ -258,12 +299,66 @@
}
}
}
+
+public byte[] getBytes() throws JavaModelException {
+ JavaElement pkg = (JavaElement) getParent();
+ if (pkg instanceof JarPackageFragment) {
+ JarPackageFragmentRoot root = (JarPackageFragmentRoot) pkg.getParent();
+ ZipFile zip = null;
+ try {
+ zip = root.getJar();
+ String entryName = Util.concatWith(((PackageFragment) pkg).names, getElementName(), '/');
+ ZipEntry ze = zip.getEntry(entryName);
+ if (ze != null) {
+ return org.eclipse.jdt.internal.compiler.util.Util.getZipEntryByteContent(ze, zip);
+ }
+ throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
+ } catch (IOException ioe) {
+ throw new JavaModelException(ioe, IJavaModelStatusConstants.IO_EXCEPTION);
+ } catch (CoreException e) {
+ if (e instanceof JavaModelException) {
+ throw (JavaModelException)e;
+ } else {
+ throw new JavaModelException(e);
+ }
+ } finally {
+ JavaModelManager.getJavaModelManager().closeZipFile(zip);
+ }
+ } else {
+ IFile file = (IFile) getResource();
+ return Util.getResourceContentsAsByteArray(file);
+ }
+}
+private IBinaryType getJarBinaryTypeInfo(PackageFragment pkg) throws CoreException, IOException, ClassFormatException {
+ JarPackageFragmentRoot root = (JarPackageFragmentRoot) pkg.getParent();
+ ZipFile zip = null;
+ try {
+ zip = root.getJar();
+ String entryName = Util.concatWith(pkg.names, getElementName(), '/');
+ ZipEntry ze = zip.getEntry(entryName);
+ if (ze != null) {
+ byte contents[] = org.eclipse.jdt.internal.compiler.util.Util.getZipEntryByteContent(ze, zip);
+ String fileName = root.getHandleIdentifier() + IDependent.JAR_FILE_ENTRY_SEPARATOR + entryName;
+ return new ClassFileReader(contents, fileName.toCharArray(), true/*fully initialize so as to not keep a reference to the byte array*/);
+ }
+ } finally {
+ JavaModelManager.getJavaModelManager().closeZipFile(zip);
+ }
+ return null;
+}
public IBuffer getBuffer() throws JavaModelException {
- if (validateClassFile().isOK()) {
+ IStatus status = validateClassFile();
+ if (status.isOK()) {
return super.getBuffer();
} else {
// .class file not on classpath, create a new buffer to be nice (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=41444)
- return openBuffer(null, null);
+ Object info = ((ClassFile) getClassFile()).getBinaryTypeInfo((IFile) getResource());
+ IBuffer buffer = openBuffer(null, info);
+ if (buffer != null && !(buffer instanceof NullBuffer))
+ return buffer;
+ if (status.getCode() == IJavaModelStatusConstants.ELEMENT_NOT_ON_CLASSPATH)
+ return null; // don't throw a JavaModelException to be able to open .class file outside the classpath (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=138507)
+ throw new JavaModelException((IJavaModelStatus) status);
}
}
/**
@@ -273,6 +368,12 @@
return this;
}
/**
+ * @see IMember#getTypeRoot()
+ */
+public ITypeRoot getTypeRoot() {
+ return this;
+}
+/**
* A class file has a corresponding resource unless it is contained
* in a jar.
*
@@ -313,14 +414,8 @@
if (mapper == null) {
return null;
} else {
- String prefix = null;
int index = this.name.indexOf('$');
- if (index > -1) {
- prefix = this.name.substring(0, index);
- } else {
- prefix = this.name;
- }
-
+ int prefixLength = index < 0 ? this.name.length() : index;
IType type = null;
int start = -1;
@@ -329,22 +424,16 @@
for (int i = 0; i < children.length; i++) {
String childName = children[i].getElementName();
- String childPrefix = null;
int childIndex = childName.indexOf('$');
- if (childIndex > -1) {
- childPrefix = childName.substring(0, childIndex);
- } else {
- childPrefix = childName.substring(0, childName.indexOf('.'));
- }
-
- if(prefix.equals(childPrefix)) {
+ int childPrefixLength = childIndex < 0 ? childName.indexOf('.') : childIndex;
+ if (prefixLength == childPrefixLength && this.name.regionMatches(0, childName, 0, prefixLength)) {
IClassFile classFile = (IClassFile) children[i];
// ensure this class file's buffer is open so that source ranges are computed
classFile.getBuffer();
SourceRange range = mapper.getSourceRange(classFile.getType());
- if (range == SourceMapper.fgUnknownRange) continue;
+ if (range == SourceMapper.UNKNOWN_RANGE) continue;
int newStart = range.offset;
int newEnd = newStart + range.length - 1;
if(newStart > start && newEnd < end
@@ -465,24 +554,15 @@
* @see IClassFile
*/
public ICompilationUnit getWorkingCopy(WorkingCopyOwner owner, IProgressMonitor monitor) throws JavaModelException {
- // get the source if possible
- char[] contents = null;
- SourceMapper mapper = this.getSourceMapper();
- if (mapper != null) {
- contents = mapper.findSource(getType());
+ CompilationUnit workingCopy = new ClassFileWorkingCopy(this, owner == null ? DefaultWorkingCopyOwner.PRIMARY : owner);
+ JavaModelManager manager = JavaModelManager.getJavaModelManager();
+ JavaModelManager.PerWorkingCopyInfo perWorkingCopyInfo =
+ manager.getPerWorkingCopyInfo(workingCopy, false/*don't create*/, true/*record usage*/, null/*not used since don't create*/);
+ if (perWorkingCopyInfo != null) {
+ return perWorkingCopyInfo.getWorkingCopy(); // return existing handle instead of the one created above
}
- if (contents == null) {
- return null;
- }
-
- ClassFileWorkingCopy workingCopy = new ClassFileWorkingCopy();
- IBuffer buffer = owner == null ? this.getBuffer() : owner.createBuffer(workingCopy);
- workingCopy.buffer = buffer;
-
- // set the buffer source
- if (buffer != null && buffer.getCharacters() == null){
- buffer.setContents(contents);
- }
+ BecomeWorkingCopyOperation op = new BecomeWorkingCopyOperation(workingCopy, null);
+ op.runOperation(monitor);
return workingCopy;
}
/**
@@ -498,6 +578,9 @@
protected boolean hasBuffer() {
return true;
}
+public int hashCode() {
+ return Util.combineHashCodes(this.name.hashCode(), this.parent.hashCode());
+}
/**
* @see IClassFile
*/
@@ -524,7 +607,8 @@
} catch (JavaModelException e) {
return e.getJavaModelStatus();
}
- return JavaConventions.validateClassFileName(getElementName());
+ IJavaProject project = getJavaProject();
+ return JavaConventions.validateClassFileName(getElementName(), project.getOption(JavaCore.COMPILER_SOURCE, true), project.getOption(JavaCore.COMPILER_COMPLIANCE, true));
}
/**
* Opens and returns buffer on the source code associated with this class file.
@@ -537,116 +621,42 @@
protected IBuffer openBuffer(IProgressMonitor pm, Object info) throws JavaModelException {
SourceMapper mapper = getSourceMapper();
if (mapper != null) {
- return mapSource(mapper);
- } else if (!this.checkAutomaticSourceMapping) {
- /*
- * We try to see if we can automatically attach a source
- * source files located inside the same folder than its .class file
- * See bug 36510.
- */
- PackageFragmentRoot root = getPackageFragmentRoot();
- if (root.isArchive()) {
- // root is a jar file or a zip file
- String elementName = getElementName();
- String sourceFileWithoutExtension = elementName.substring(0, elementName.lastIndexOf('.'));
- JarPackageFragmentRoot jarPackageFragmentRoot = (JarPackageFragmentRoot) root;
- ZipFile jar = null;
- try {
- jar = jarPackageFragmentRoot.getJar();
- String[] pkgName = ((PackageFragment) getParent()).names;
- char[][] javaLikeExtensions = Util.getJavaLikeExtensions();
- for (int i = 0, length = javaLikeExtensions.length; i < length; i++) {
- StringBuffer entryName = new StringBuffer();
- for (int j = 0, pkgNameLength = pkgName.length; j < pkgNameLength; j++) {
- entryName.append(pkgName[j]);
- entryName.append('/');
- }
- entryName.append(sourceFileWithoutExtension);
- entryName.append(javaLikeExtensions[i]);
- ZipEntry zipEntry = jar.getEntry(entryName.toString());
- if (zipEntry != null) {
- // found a source file
- this.checkAutomaticSourceMapping = true;
- root.attachSource(root.getPath(), null, null);
- SourceMapper sourceMapper = getSourceMapper();
- if (sourceMapper != null) {
- return mapSource(sourceMapper);
- }
- }
- }
- } catch (CoreException e) {
- if (e instanceof JavaModelException) throw (JavaModelException)e;
- throw new JavaModelException(e);
- } finally {
- JavaModelManager.getJavaModelManager().closeZipFile(jar);
- }
- } else {
- // Attempts to find the corresponding java file
- String qualifiedName = getType().getFullyQualifiedName();
- NameLookup lookup = ((JavaProject) getJavaProject()).newNameLookup(DefaultWorkingCopyOwner.PRIMARY);
- ICompilationUnit cu = lookup.findCompilationUnit(qualifiedName);
- if (cu != null) {
- return cu.getBuffer();
- } else {
- // root is a class folder
-
- IContainer pkgFolder = (IContainer) getParent().getResource();
- IResource[] files = null;
- try {
- files = pkgFolder.members();
- } catch (CoreException e) {
- throw new JavaModelException(e);
- }
- IResource sourceFile = null;
- String classFileName = getElementName();
- String simpleName = classFileName.substring(0, classFileName.lastIndexOf('.'));
- for (int i = 0, length = files.length; i < length; i++) {
- IResource resource = files[i];
- if (resource.getType() == IResource.FILE
- && Util.equalsIgnoreJavaLikeExtension(resource.getName(), simpleName)) {
- sourceFile = resource;
- break;
- }
- }
- if (sourceFile != null) {
-
- // found a source file
- // we don't need to check again. The source will be attached.
- this.checkAutomaticSourceMapping = true;
- root.attachSource(root.getPath(), null, null);
- SourceMapper sourceMapper = getSourceMapper();
- if (sourceMapper != null) {
- return mapSource(sourceMapper);
- }
- }
- }
- }
+ return mapSource(mapper, info instanceof IBinaryType ? (IBinaryType) info : null);
}
return null;
}
-private IBuffer mapSource(SourceMapper mapper) {
- char[] contents = mapper.findSource(getType());
+private IBuffer mapSource(SourceMapper mapper, IBinaryType info) {
+ char[] contents = mapper.findSource(getType(), info);
if (contents != null) {
// create buffer
- IBuffer buffer = getBufferManager().createBuffer(this);
+ IBuffer buffer = BufferManager.createBuffer(this);
if (buffer == null) return null;
BufferManager bufManager = getBufferManager();
bufManager.addBuffer(buffer);
-
+
// set the buffer source
if (buffer.getCharacters() == null){
buffer.setContents(contents);
}
-
+
// listen to buffer changes
- buffer.addBufferChangedListener(this);
-
+ buffer.addBufferChangedListener(this);
+
// do the source mapping
- mapper.mapSource(getType(), contents);
-
+ mapper.mapSource(getType(), contents, info);
+
+ return buffer;
+ } else {
+ // create buffer
+ IBuffer buffer = BufferManager.createNullBuffer(this);
+ if (buffer == null) return null;
+ BufferManager bufManager = getBufferManager();
+ bufManager.addBuffer(buffer);
+
+ // listen to buffer changes
+ buffer.addBufferChangedListener(this);
return buffer;
}
- return null;
}
/* package */ static String simpleName(char[] className) {
if (className == null)
@@ -745,20 +755,7 @@
requestor.acceptClass(packageName, className, completionName, modifiers, completionStart, completionEnd);
}
public void acceptError(IProblem error) {
- if (true) return; // was disabled in 1.0
-
- try {
- IMarker marker = ResourcesPlugin.getWorkspace().getRoot().createMarker(IJavaModelMarker.TRANSIENT_PROBLEM);
- marker.setAttribute(IJavaModelMarker.ID, error.getID());
- marker.setAttribute(IMarker.CHAR_START, error.getSourceStart());
- marker.setAttribute(IMarker.CHAR_END, error.getSourceEnd() + 1);
- marker.setAttribute(IMarker.LINE_NUMBER, error.getSourceLineNumber());
- marker.setAttribute(IMarker.MESSAGE, error.getMessage());
- marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
- requestor.acceptError(marker);
- } catch(CoreException e){
- // marker could not be created: ignore
- }
+ // was disabled in 1.0
}
public void acceptField(char[] declaringTypePackageName, char[] declaringTypeName, char[] fieldName, char[] typePackageName, char[] typeName, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) {
requestor.acceptField(declaringTypePackageName, declaringTypeName, fieldName, typePackageName, typeName, completionName, modifiers, completionStart, completionEnd);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileInfo.java
index 65a2d89..0a9f255 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileInfo.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -13,7 +13,6 @@
import java.util.ArrayList;
import java.util.HashMap;
-import org.eclipse.core.resources.IFile;
import org.eclipse.jdt.core.*;
import org.eclipse.jdt.core.IClassFile;
import org.eclipse.jdt.core.IField;
@@ -38,26 +37,13 @@
* The children of the <code>BinaryType</code> corresponding to our
* <code>ClassFile</code>. These are kept here because we don't have
* access to the <code>BinaryType</code> info (<code>ClassFileReader</code>).
- * <p>
- * The children are lazily initialized, on the first call to
- * <code>getBinaryChildren()</code>, which in turn is called by
- * <code>BinaryType.getChildren()</code>.
*/
protected JavaElement[] binaryChildren = null;
/*
* The type parameters in this class file.
*/
protected ITypeParameter[] typeParameters;
- /**
- * Back-pointer to the IClassFile to allow lazy initialization.
- */
- protected ClassFile classFile = null;
-/**
- * Creates a new <code>ClassFileInfo</code> for <code>classFile</code>.
- */
-ClassFileInfo(ClassFile classFile) {
- this.classFile = classFile;
-}
+
/**
* Creates the handles and infos for the fields of the given binary type.
* Adds new handles to the given vector.
@@ -87,10 +73,11 @@
// Can also return an entry for the enclosing type of an inner type.
IBinaryNestedType[] innerTypes = typeInfo.getMemberTypes();
if (innerTypes != null) {
+ IPackageFragment pkg = (IPackageFragment) type.getAncestor(IJavaElement.PACKAGE_FRAGMENT);
for (int i = 0, typeCount = innerTypes.length; i < typeCount; i++) {
IBinaryNestedType binaryType = innerTypes[i];
- IClassFile parentClassFile= ((IPackageFragment)this.classFile.getParent()).getClassFile(new String(ClassFile.unqualifiedName(binaryType.getName())) + SUFFIX_STRING_class);
- IType innerType = new BinaryType((JavaElement)parentClassFile, ClassFile.simpleName(binaryType.getName()));
+ IClassFile parentClassFile= pkg.getClassFile(new String(ClassFile.unqualifiedName(binaryType.getName())) + SUFFIX_STRING_class);
+ IType innerType = new BinaryType((JavaElement) parentClassFile, ClassFile.simpleName(binaryType.getName()));
childrenHandles.add(innerType);
}
}
@@ -177,16 +164,6 @@
}
}
/**
- * Returns the list of children (<code>BinaryMember</code>s) of the
- * <code>BinaryType</code> of our <code>ClassFile</code>.
- */
-IJavaElement[] getBinaryChildren(HashMap newElements) {
- if (this.binaryChildren == null) {
- readBinaryChildren(newElements, null/*type info not known here*/);
- }
- return this.binaryChildren;
-}
-/**
* Returns true iff the <code>readBinaryChildren</code> has already
* been called.
*/
@@ -198,21 +175,9 @@
* <code>ClassFile</code> and adds them to the
* <code>JavaModelManager</code>'s cache.
*/
-protected void readBinaryChildren(HashMap newElements, IBinaryType typeInfo) {
+protected void readBinaryChildren(ClassFile classFile, HashMap newElements, IBinaryType typeInfo) {
ArrayList childrenHandles = new ArrayList();
- BinaryType type = null;
- try {
- type = (BinaryType) this.classFile.getType();
- if (typeInfo == null) {
- typeInfo = (IBinaryType) newElements.get(type);
- if (typeInfo == null) {
- // create a classfile reader
- typeInfo = this.classFile.getBinaryTypeInfo((IFile)this.classFile.getResource());
- }
- }
- } catch (JavaModelException npe) {
- return;
- }
+ BinaryType type = (BinaryType) classFile.getType();
ArrayList typeParameterHandles = new ArrayList();
if (typeInfo != null) { //may not be a valid class file
generateTypeParameterInfos(type, typeInfo.getGenericSignature(), newElements, typeParameterHandles);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileWorkingCopy.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileWorkingCopy.java
index fbbc2ba..e867eb4 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileWorkingCopy.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileWorkingCopy.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,653 +10,105 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core;
-import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.jobs.ISchedulingRule;
-import org.eclipse.jdt.core.*;
import org.eclipse.jdt.core.IBuffer;
-import org.eclipse.jdt.core.ICompilationUnit;
-import org.eclipse.jdt.core.IImportContainer;
-import org.eclipse.jdt.core.IImportDeclaration;
+import org.eclipse.jdt.core.IClassFile;
import org.eclipse.jdt.core.IJavaElement;
-import org.eclipse.jdt.core.IJavaModel;
import org.eclipse.jdt.core.IJavaModelStatusConstants;
-import org.eclipse.jdt.core.IJavaProject;
-import org.eclipse.jdt.core.IOpenable;
-import org.eclipse.jdt.core.IPackageDeclaration;
-import org.eclipse.jdt.core.IProblemRequestor;
-import org.eclipse.jdt.core.ISourceRange;
-import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
-import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.ToolFactory;
+import org.eclipse.jdt.core.WorkingCopyOwner;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.util.ClassFileBytesDisassembler;
+import org.eclipse.jdt.core.util.IClassFileReader;
+import org.eclipse.jdt.internal.core.util.Disassembler;
+import org.eclipse.jdt.internal.core.util.Util;
/**
* A working copy on an <code>IClassFile</code>.
- * Only the <code>getBuffer()</code> and <code>getOriginalElement()</code> operations are valid.
- * All other operations return either <code>null</code> or throw a <code>JavaModelException</code>.
*/
-public class ClassFileWorkingCopy implements ICompilationUnit {
+public class ClassFileWorkingCopy extends CompilationUnit {
- public IBuffer buffer;
+ public IClassFile classFile;
- /*
- * @see ICompilationUnit#becomeWorkingCopy(IProblemRequestor, IProgressMonitor)
- */
- public void becomeWorkingCopy(IProblemRequestor problemRequestor, IProgressMonitor monitor) throws JavaModelException {
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
- }
-
- /*
- * @see ICompilationUnit#createImport(String, IJavaElement, IProgressMonitor)
- */
- public IImportDeclaration createImport(
- String name,
- IJavaElement sibling,
- IProgressMonitor monitor)
- throws JavaModelException {
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
- }
-
- /*
- * @see ICompilationUnit#createImport(String, IJavaElement, int, IProgressMonitor)
- * @since 3.0
- */
- public IImportDeclaration createImport(
- String name,
- IJavaElement sibling,
- int flags,
- IProgressMonitor monitor)
- throws JavaModelException {
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
- }
-
- /*
- * @see ICompilationUnit#createPackageDeclaration(String, IProgressMonitor)
- */
- public IPackageDeclaration createPackageDeclaration(
- String name,
- IProgressMonitor monitor)
- throws JavaModelException {
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
- }
-
- /*
- * @see ICompilationUnit#createType(String, IJavaElement, boolean, IProgressMonitor)
- */
- public IType createType(
- String contents,
- IJavaElement sibling,
- boolean force,
- IProgressMonitor monitor)
- throws JavaModelException {
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
- }
-
- /*
- * @see ICompilationUnit#discardWorkingCopy
- */
- public void discardWorkingCopy() throws JavaModelException {
- // not a real working copy: ignore
- }
-
- /*
- * @see ICompilationUnit#getAllTypes()
- */
- public IType[] getAllTypes() throws JavaModelException {
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
- }
-
- /*
- * @see ICompilationUnit#getElementAt(int)
- */
- public IJavaElement getElementAt(int position) throws JavaModelException {
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
- }
-
- /*
- * @see ICompilationUnit#getImport(String)
- */
- public IImportDeclaration getImport(String name) {
- return null;
- }
-
- /*
- * @see ICompilationUnit#getImportContainer()
- */
- public IImportContainer getImportContainer() {
- return null;
- }
-
- /*
- * @see ICompilationUnit#getImports()
- */
- public IImportDeclaration[] getImports() throws JavaModelException {
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
- }
-
- /*
- * @see IJavaElement#getOpenable()
- */
- public IOpenable getOpenable() {
- return null;
- }
-
- /*
- * @see ICompilationUnit#getOwner()
- */
- public WorkingCopyOwner getOwner() {
- return null;
- }
-
- /*
- * @see ICompilationUnit#getPackageDeclaration(String)
- */
- public IPackageDeclaration getPackageDeclaration(String name) {
- return null;
- }
-
- /*
- * @see ICompilationUnit#getPackageDeclarations()
- */
- public IPackageDeclaration[] getPackageDeclarations()
- throws JavaModelException {
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
- }
-
- /*
- * @see ICompilationUnit#getType(String)
- */
- public IType getType(String name) {
- return null;
- }
-
- /*
- * @see ICompilationUnit#getTypes()
- */
- public IType[] getTypes() throws JavaModelException {
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
- }
-
- /*
- * @see IJavaElement#exists()
- */
- public boolean exists() {
- return false;
- }
-/*
- * @see IWorkingCopy
- */
-public IJavaElement[] findElements(IJavaElement element) {
- return null;
-}
-/*
- * @see IWorkingCopy
- */
-public IType findPrimaryType() {
- return null;
+public ClassFileWorkingCopy(IClassFile classFile, WorkingCopyOwner owner) {
+ super((PackageFragment) classFile.getParent(), ((BinaryType) ((ClassFile) classFile).getType()).getSourceFileName(null/*no info available*/), owner);
+ this.classFile = classFile;
}
- /*
- * @see IJavaElement#getCorrespondingResource()
- */
- public IResource getCorrespondingResource() throws JavaModelException {
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
- }
+public void commitWorkingCopy(boolean force, IProgressMonitor monitor) throws JavaModelException {
+ throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, this));
+}
- /*
- * @see IJavaElement#getElementName()
- */
- public String getElementName() {
- return null;
- }
+public IBuffer getBuffer() throws JavaModelException {
+ if (isWorkingCopy())
+ return super.getBuffer();
+ else
+ return this.classFile.getBuffer();
+}
- /*
- * @see IJavaElement#getElementType()
- */
- public int getElementType() {
- return 0;
+public char[] getContents() {
+ try {
+ IBuffer buffer = getBuffer();
+ if (buffer == null) return CharOperation.NO_CHAR;
+ char[] characters = buffer.getCharacters();
+ if (characters == null) return CharOperation.NO_CHAR;
+ return characters;
+ } catch (JavaModelException e) {
+ return CharOperation.NO_CHAR;
}
+}
- /*
- * @see IJavaElement#getHandleIdentifier()
- */
- public String getHandleIdentifier() {
- return null;
- }
+public IPath getPath() {
+ return this.classFile.getPath();
+}
- /*
- * @see IJavaElement#getJavaModel()
- */
- public IJavaModel getJavaModel() {
- return null;
- }
+public IJavaElement getPrimaryElement(boolean checkOwner) {
+ if (checkOwner && isPrimary()) return this;
+ return new ClassFileWorkingCopy(this.classFile, DefaultWorkingCopyOwner.PRIMARY);
+}
- /*
- * @see IJavaElement#getJavaProject()
- */
- public IJavaProject getJavaProject() {
- return null;
- }
+public IResource getResource() {
+ return this.classFile.getResource();
+}
- /*
- * @see IJavaElement#getParent()
- */
- public IJavaElement getParent() {
- return null;
- }
+/**
+ * @see Openable#openBuffer(IProgressMonitor, Object)
+ */
+protected IBuffer openBuffer(IProgressMonitor pm, Object info) throws JavaModelException {
- /*
- * @see IJavaElement
- */
- public IPath getPath() {
- return null;
- }
-
- /*
- * @see ICompilationUnit#getPrimary()
- */
- public ICompilationUnit getPrimary() {
- return this;
- }
+ // create buffer
+ IBuffer buffer = this.owner.createBuffer(this);
+ if (buffer == null) return null;
- /*
- * @see ICompilationUnit#getPrimaryElement()
- */
- public IJavaElement getPrimaryElement() {
- return getPrimary();
+ // set the buffer source
+ if (buffer.getCharacters() == null) {
+ IBuffer classFileBuffer = this.classFile.getBuffer();
+ if (classFileBuffer != null) {
+ buffer.setContents(classFileBuffer.getCharacters());
+ } else {
+ // Disassemble
+ IClassFileReader reader = ToolFactory.createDefaultClassFileReader(this.classFile, IClassFileReader.ALL);
+ Disassembler disassembler = new Disassembler();
+ String contents = disassembler.disassemble(reader, Util.getLineSeparator("", getJavaProject()), ClassFileBytesDisassembler.WORKING_COPY); //$NON-NLS-1$
+ buffer.setContents(contents);
+ }
}
+
+ // add buffer to buffer cache
+ BufferManager bufManager = getBufferManager();
+ bufManager.addBuffer(buffer);
+
+ // listen to buffer changes
+ buffer.addBufferChangedListener(this);
- /*
- * @see IJavaElement
- */
- public IResource getResource() {
- return null;
- }
+ return buffer;
+}
- /*
- * @see IJavaElement
- */
- public ISchedulingRule getSchedulingRule() {
- return null;
- }
-
- /*
- * @see IJavaElement#getUnderlyingResource()
- */
- public IResource getUnderlyingResource() throws JavaModelException {
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
- }
-
- /*
- * @see IJavaElement#isReadOnly()
- */
- public boolean isReadOnly() {
- return true;
- }
-
- /*
- * @see IJavaElement#isStructureKnown()
- */
- public boolean isStructureKnown() {
- return false;
- }
-
- /*
- * @see ISourceReference#getSource()
- */
- public String getSource() throws JavaModelException {
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
- }
-
- /*
- * @see ISourceReference#getSourceRange()
- */
- public ISourceRange getSourceRange() throws JavaModelException {
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
- }
-
- /*
- * @see IParent#getChildren()
- */
- public IJavaElement[] getChildren() throws JavaModelException {
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
- }
-
- /*
- * @see IParent#hasChildren()
- */
- public boolean hasChildren() throws JavaModelException {
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
- }
-
- /*
- * @see IOpenable#close()
- */
- public void close() throws JavaModelException {
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
- }
-
- /*
- * @see IOpenable#getBuffer()
- */
- public IBuffer getBuffer() {
- return this.buffer;
- }
-
- /*
- * @see ICompilationUnit#hasResourceChanged()
- */
- public boolean hasResourceChanged() {
- return false;
- }
-
- /*
- * @see IOpenable#hasUnsavedChanges()
- */
- public boolean hasUnsavedChanges() {
- return false;
- }
-
- /*
- * @see IOpenable#isConsistent()
- */
- public boolean isConsistent() {
- return false;
- }
-
- /*
- * @see IOpenable#isOpen()
- */
- public boolean isOpen() {
- return false;
- }
-
- /*
- * @see IOpenable#makeConsistent(IProgressMonitor)
- */
- public void makeConsistent(IProgressMonitor progress)
- throws JavaModelException {
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
- }
-
- /*
- * @see IOpenable#open(IProgressMonitor)
- */
- public void open(IProgressMonitor progress) throws JavaModelException {
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
- }
-
- /*
- * @see IOpenable#save(IProgressMonitor, boolean)
- */
- public void save(IProgressMonitor progress, boolean force)
- throws JavaModelException {
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
- }
-
- /**
- * @see IWorkingCopy#commit(boolean, IProgressMonitor)
- * @deprecated
- */
- public void commit(boolean force, IProgressMonitor monitor) throws JavaModelException {
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
- }
-
- /*
- * @see IWorkingCopy#commitWorkingCopy(boolean, IProgressMonitor)
- */
- public void commitWorkingCopy(boolean force, IProgressMonitor monitor)
- throws JavaModelException {
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
- }
-
- /**
- * @see IWorkingCopy#destroy()
- * @deprecated
- */
- public void destroy() {
- // not a real working copy: ignore
- }
-
- /**
- * @see IWorkingCopy#findSharedWorkingCopy(IBufferFactory)
- * @deprecated
- */
- public IJavaElement findSharedWorkingCopy(IBufferFactory bufferFactory) {
- return null;
- }
-
- /**
- * @see ICompilationUnit#findWorkingCopy(WorkingCopyOwner)
- */
- public ICompilationUnit findWorkingCopy(WorkingCopyOwner owner) {
- return null;
- }
-
- /**
- * @see IWorkingCopy#getOriginal(IJavaElement)
- * @deprecated
- */
- public IJavaElement getOriginal(IJavaElement workingCopyElement) {
- return null;
- }
-
- /**
- * @see IWorkingCopy#getOriginalElement()
- * @deprecated
- */
- public IJavaElement getOriginalElement() {
- return getPrimaryElement();
- }
-
- /**
- * @see IWorkingCopy#getSharedWorkingCopy(IProgressMonitor, IBufferFactory, IProblemRequestor)
- * @deprecated
- */
- public IJavaElement getSharedWorkingCopy(
- IProgressMonitor monitor,
- IBufferFactory factory,
- IProblemRequestor problemRequestor)
- throws JavaModelException {
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
- }
-
- /**
- * @see IWorkingCopy#getWorkingCopy()
- * @deprecated
- */
- public IJavaElement getWorkingCopy() throws JavaModelException {
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
- }
-
- /**
- * @see ICompilationUnit#getWorkingCopy(IProgressMonitor)
- */
- public ICompilationUnit getWorkingCopy(IProgressMonitor monitor) throws JavaModelException {
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
- }
-
- /**
- * @see IWorkingCopy#getWorkingCopy(IProgressMonitor, IBufferFactory, IProblemRequestor)
- * @deprecated
- */
- public IJavaElement getWorkingCopy(IProgressMonitor monitor, IBufferFactory factory, IProblemRequestor problemRequestor) throws JavaModelException {
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.jdt.core.ICompilationUnit#getWorkingCopy(org.eclipse.jdt.core.WorkingCopyOwner, org.eclipse.jdt.core.IProblemRequestor, org.eclipse.core.runtime.IProgressMonitor)
- */
- public ICompilationUnit getWorkingCopy(WorkingCopyOwner owner, IProblemRequestor problemRequestor, IProgressMonitor monitor) throws JavaModelException {
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
- }
-
- /**
- * @see IWorkingCopy#isBasedOn(IResource)
- * @deprecated
- */
- public boolean isBasedOn(IResource resource) {
- return false;
- }
-
- /*
- * @see IWorkingCopy#isWorkingCopy()
- */
- public boolean isWorkingCopy() {
- return true;
- }
-
- /**
- * @see org.eclipse.jdt.core.IWorkingCopy#reconcile()
- * @deprecated
- */
- public IMarker[] reconcile() throws JavaModelException {
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
- }
-
- /**
- * @see ICompilationUnit#reconcile(int, boolean, WorkingCopyOwner, IProgressMonitor)
- * @since 3.0
- */
- public CompilationUnit reconcile(
- int astLevel,
- boolean forceProblemDetection,
- WorkingCopyOwner owner,
- IProgressMonitor monitor)
- throws JavaModelException {
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.jdt.core.IWorkingCopy#reconcile(boolean, org.eclipse.core.runtime.IProgressMonitor)
- */
- public void reconcile(
- boolean forceProblemDetection,
- IProgressMonitor monitor)
- throws JavaModelException {
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.jdt.core.IWorkingCopy#restore()
- */
- public void restore() throws JavaModelException {
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
- }
-
- /**
- * @see org.eclipse.jdt.core.ISourceManipulation#copy(IJavaElement, IJavaElement, String, boolean, IProgressMonitor)
- */
- public void copy(
- IJavaElement container,
- IJavaElement sibling,
- String rename,
- boolean replace,
- IProgressMonitor monitor)
- throws JavaModelException {
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
- }
-
- /**
- * @see org.eclipse.jdt.core.ISourceManipulation#delete(boolean, IProgressMonitor)
- */
- public void delete(boolean force, IProgressMonitor monitor)
- throws JavaModelException {
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
- }
-
- /**
- * @see org.eclipse.jdt.core.ISourceManipulation#move(IJavaElement, IJavaElement, String, boolean, IProgressMonitor)
- */
- public void move(
- IJavaElement container,
- IJavaElement sibling,
- String rename,
- boolean replace,
- IProgressMonitor monitor)
- throws JavaModelException {
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
- }
-
- /**
- * @see org.eclipse.jdt.core.ISourceManipulation#rename(String, boolean, IProgressMonitor)
- */
- public void rename(String name, boolean replace, IProgressMonitor monitor)
- throws JavaModelException {
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
- }
-
- /**
- * @see org.eclipse.jdt.core.ICodeAssist#codeComplete(int, ICompletionRequestor)
- * @deprecated
- */
- public void codeComplete(int offset, ICompletionRequestor requestor)
- throws JavaModelException {
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
- }
-
- /**
- * @see org.eclipse.jdt.core.ICodeAssist#codeComplete(int, ICompletionRequestor, WorkingCopyOwner)
- * @deprecated
- */
- public void codeComplete(int offset, ICompletionRequestor requestor, WorkingCopyOwner owner)
- throws JavaModelException {
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
- }
-
- /**
- * @see org.eclipse.jdt.core.ICodeAssist#codeSelect(int, int)
- */
- public IJavaElement[] codeSelect(int offset, int length)
- throws JavaModelException {
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
- }
-
- /**
- * @see org.eclipse.jdt.core.ICodeAssist#codeSelect(int, int, WorkingCopyOwner)
- */
- public IJavaElement[] codeSelect(int offset, int length, WorkingCopyOwner owner)
- throws JavaModelException {
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
- }
-
- /**
- * @see org.eclipse.jdt.core.ICodeAssist#codeComplete(int, ICodeCompletionRequestor)
- * @deprecated
- */
- public void codeComplete(int offset, org.eclipse.jdt.core.ICodeCompletionRequestor requestor)
- throws JavaModelException {
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.jdt.core.ICodeAssist#codeComplete(int, org.eclipse.jdt.core.CompletionRequestor)
- */
- public void codeComplete(int offset, CompletionRequestor requestor) throws JavaModelException {
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.jdt.core.ICodeAssist#codeComplete(int, org.eclipse.jdt.core.CompletionRequestor, org.eclipse.jdt.core.WorkingCopyOwner)
- */
- public void codeComplete(int offset, CompletionRequestor requestor, WorkingCopyOwner wcowner) throws JavaModelException {
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
- }
-
- /**
- * @see org.eclipse.core.runtime.IAdaptable#getAdapter(Class)
- */
- public Object getAdapter(Class adapter) {
- return null;
- }
-
- /**
- * @see IJavaElement#getAncestor(int)
- */
- public IJavaElement getAncestor(int ancestorType) {
- return null;
- }
+protected void toStringName(StringBuffer buffer) {
+ buffer.append(this.classFile.getElementName());
+}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathAccessRule.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathAccessRule.java
index 9beb6d1..8dee3a6 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathAccessRule.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathAccessRule.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -27,13 +27,14 @@
}
private static int toProblemId(int kind) {
- switch (kind) {
+ boolean ignoreIfBetter = (kind & IAccessRule.IGNORE_IF_BETTER) != 0;
+ switch (kind & ~IAccessRule.IGNORE_IF_BETTER) {
case K_NON_ACCESSIBLE:
- return IProblem.ForbiddenReference;
+ return ignoreIfBetter ? IProblem.ForbiddenReference | AccessRule.IgnoreIfBetter : IProblem.ForbiddenReference;
case K_DISCOURAGED:
- return IProblem.DiscouragedReference;
+ return ignoreIfBetter ? IProblem.DiscouragedReference | AccessRule.IgnoreIfBetter : IProblem.DiscouragedReference;
default:
- return -1;
+ return ignoreIfBetter ? AccessRule.IgnoreIfBetter : 0;
}
}
@@ -42,7 +43,7 @@
}
public int getKind() {
- switch (this.problemId) {
+ switch (getProblemId()) {
case IProblem.ForbiddenReference:
return K_NON_ACCESSIBLE;
case IProblem.DiscouragedReference:
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathChange.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathChange.java
new file mode 100755
index 0000000..92f8f6e
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathChange.java
@@ -0,0 +1,501 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaElementDelta;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.internal.compiler.util.ObjectVector;
+import org.eclipse.jdt.internal.core.JavaModelManager.PerProjectInfo;
+import org.eclipse.jdt.internal.core.search.indexing.IndexManager;
+import org.eclipse.jdt.internal.core.util.Util;
+
+public class ClasspathChange {
+ public static int NO_DELTA = 0x00;
+ public static int HAS_DELTA = 0x01;
+ public static int HAS_PROJECT_CHANGE = 0x10;
+
+ JavaProject project;
+ IClasspathEntry[] oldRawClasspath;
+ IPath oldOutputLocation;
+ IClasspathEntry[] oldResolvedClasspath;
+
+ public ClasspathChange(JavaProject project, IClasspathEntry[] oldRawClasspath, IPath oldOutputLocation, IClasspathEntry[] oldResolvedClasspath) {
+ this.project = project;
+ this.oldRawClasspath = oldRawClasspath;
+ this.oldOutputLocation = oldOutputLocation;
+ this.oldResolvedClasspath = oldResolvedClasspath;
+ }
+
+ private void addClasspathDeltas(JavaElementDelta delta, IPackageFragmentRoot[] roots, int flag) {
+ for (int i = 0; i < roots.length; i++) {
+ IPackageFragmentRoot root = roots[i];
+ delta.changed(root, flag);
+ if ((flag & IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) != 0
+ || (flag & IJavaElementDelta.F_SOURCEATTACHED) != 0
+ || (flag & IJavaElementDelta.F_SOURCEDETACHED) != 0){
+ try {
+ root.close();
+ } catch (JavaModelException e) {
+ // ignore
+ }
+ }
+ }
+ }
+
+ /*
+ * Returns the index of the item in the list if the given list contains the specified entry. If the list does
+ * not contain the entry, -1 is returned.
+ */
+ private int classpathContains(IClasspathEntry[] list, IClasspathEntry entry) {
+ IPath[] exclusionPatterns = entry.getExclusionPatterns();
+ IPath[] inclusionPatterns = entry.getInclusionPatterns();
+ nextEntry: for (int i = 0; i < list.length; i++) {
+ IClasspathEntry other = list[i];
+ if (other.getContentKind() == entry.getContentKind()
+ && other.getEntryKind() == entry.getEntryKind()
+ && other.isExported() == entry.isExported()
+ && other.getPath().equals(entry.getPath())) {
+ // check custom outputs
+ IPath entryOutput = entry.getOutputLocation();
+ IPath otherOutput = other.getOutputLocation();
+ if (entryOutput == null) {
+ if (otherOutput != null)
+ continue;
+ } else {
+ if (!entryOutput.equals(otherOutput))
+ continue;
+ }
+
+ // check inclusion patterns
+ IPath[] otherIncludes = other.getInclusionPatterns();
+ if (inclusionPatterns != otherIncludes) {
+ if (inclusionPatterns == null) continue;
+ int includeLength = inclusionPatterns.length;
+ if (otherIncludes == null || otherIncludes.length != includeLength)
+ continue;
+ for (int j = 0; j < includeLength; j++) {
+ // compare toStrings instead of IPaths
+ // since IPath.equals is specified to ignore trailing separators
+ if (!inclusionPatterns[j].toString().equals(otherIncludes[j].toString()))
+ continue nextEntry;
+ }
+ }
+ // check exclusion patterns
+ IPath[] otherExcludes = other.getExclusionPatterns();
+ if (exclusionPatterns != otherExcludes) {
+ if (exclusionPatterns == null) continue;
+ int excludeLength = exclusionPatterns.length;
+ if (otherExcludes == null || otherExcludes.length != excludeLength)
+ continue;
+ for (int j = 0; j < excludeLength; j++) {
+ // compare toStrings instead of IPaths
+ // since IPath.equals is specified to ignore trailing separators
+ if (!exclusionPatterns[j].toString().equals(otherExcludes[j].toString()))
+ continue nextEntry;
+ }
+ }
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /*
+ * Recursively adds all subfolders of <code>folder</code> to the given collection.
+ */
+ private void collectAllSubfolders(IFolder folder, ArrayList collection) throws JavaModelException {
+ try {
+ IResource[] members= folder.members();
+ for (int i = 0, max = members.length; i < max; i++) {
+ IResource r= members[i];
+ if (r.getType() == IResource.FOLDER) {
+ collection.add(r);
+ collectAllSubfolders((IFolder)r, collection);
+ }
+ }
+ } catch (CoreException e) {
+ throw new JavaModelException(e);
+ }
+ }
+
+ /*
+ * Returns a collection of package fragments that have been added/removed
+ * as the result of changing the output location to/from the given
+ * location. The collection is empty if no package fragments are
+ * affected.
+ */
+ private ArrayList determineAffectedPackageFragments(IPath location) throws JavaModelException {
+ ArrayList fragments = new ArrayList();
+
+ // see if this will cause any package fragments to be affected
+ IWorkspace workspace = ResourcesPlugin.getWorkspace();
+ IResource resource = null;
+ if (location != null) {
+ resource = workspace.getRoot().findMember(location);
+ }
+ if (resource != null && resource.getType() == IResource.FOLDER) {
+ IFolder folder = (IFolder) resource;
+ // only changes if it actually existed
+ IClasspathEntry[] classpath = this.project.getExpandedClasspath();
+ for (int i = 0; i < classpath.length; i++) {
+ IClasspathEntry entry = classpath[i];
+ IPath path = classpath[i].getPath();
+ if (entry.getEntryKind() != IClasspathEntry.CPE_PROJECT && path.isPrefixOf(location) && !path.equals(location)) {
+ IPackageFragmentRoot[] roots = this.project.computePackageFragmentRoots(classpath[i]);
+ PackageFragmentRoot root = (PackageFragmentRoot) roots[0];
+ // now the output location becomes a package fragment - along with any subfolders
+ ArrayList folders = new ArrayList();
+ folders.add(folder);
+ collectAllSubfolders(folder, folders);
+ Iterator elements = folders.iterator();
+ int segments = path.segmentCount();
+ while (elements.hasNext()) {
+ IFolder f = (IFolder) elements.next();
+ IPath relativePath = f.getFullPath().removeFirstSegments(segments);
+ String[] pkgName = relativePath.segments();
+ IPackageFragment pkg = root.getPackageFragment(pkgName);
+ if (!Util.isExcluded(pkg))
+ fragments.add(pkg);
+ }
+ }
+ }
+ }
+ return fragments;
+ }
+
+ public boolean equals(Object obj) {
+ if (!(obj instanceof ClasspathChange))
+ return false;
+ return this.project.equals(((ClasspathChange) obj).project);
+ }
+
+ /*
+ * Generates a classpath change delta for this classpath change.
+ * Returns whether a delta was generated, and whether project reference have changed.
+ */
+ public int generateDelta(JavaElementDelta delta) {
+ JavaModelManager manager = JavaModelManager.getJavaModelManager();
+ DeltaProcessingState state = manager.deltaState;
+ if (state.findJavaProject(this.project.getElementName()) == null)
+ // project doesn't exist yet (we're in an IWorkspaceRunnable)
+ // no need to create a delta here and no need to index (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=133334)
+ // the delta processor will create an ADDED project delta, and index the project
+ return NO_DELTA;
+
+ DeltaProcessor deltaProcessor = state.getDeltaProcessor();
+ IClasspathEntry[] newResolvedClasspath = null;
+ IPath newOutputLocation = null;
+ int result = NO_DELTA;
+ try {
+ PerProjectInfo perProjectInfo = this.project.getPerProjectInfo();
+
+ // get new info
+ this.project.resolveClasspath(perProjectInfo);
+ IClasspathEntry[] newRawClasspath;
+
+ // use synchronized block to ensure consistency
+ synchronized (perProjectInfo) {
+ newRawClasspath = perProjectInfo.rawClasspath;
+ newResolvedClasspath = perProjectInfo.resolvedClasspath;
+ newOutputLocation = perProjectInfo.outputLocation;
+ }
+
+ // check if raw classpath has changed
+ if (this.oldRawClasspath != null && !JavaProject.areClasspathsEqual(this.oldRawClasspath, newRawClasspath, this.oldOutputLocation, newOutputLocation)) {
+ delta.changed(this.project, IJavaElementDelta.F_CLASSPATH_CHANGED);
+ result |= HAS_DELTA;
+ }
+
+ // if no changes to resolved classpath, nothing more to do
+ if (this.oldResolvedClasspath != null && JavaProject.areClasspathsEqual(this.oldResolvedClasspath, newResolvedClasspath, this.oldOutputLocation, newOutputLocation))
+ return NO_DELTA;
+
+ // close cached info
+ this.project.close();
+ } catch (JavaModelException e) {
+ if (DeltaProcessor.VERBOSE) {
+ e.printStackTrace();
+ }
+ // project no longer exist
+ return NO_DELTA;
+ }
+
+ if (this.oldResolvedClasspath == null)
+ return NO_DELTA;
+
+ Map removedRoots = null;
+ IPackageFragmentRoot[] roots = null;
+ Map allOldRoots ;
+ if ((allOldRoots = deltaProcessor.oldRoots) != null) {
+ roots = (IPackageFragmentRoot[]) allOldRoots.get(this.project);
+ }
+ if (roots != null) {
+ removedRoots = new HashMap();
+ for (int i = 0; i < roots.length; i++) {
+ IPackageFragmentRoot root = roots[i];
+ removedRoots.put(root.getPath(), root);
+ }
+ }
+
+ int newLength = newResolvedClasspath.length;
+ int oldLength = this.oldResolvedClasspath.length;
+ for (int i = 0; i < oldLength; i++) {
+ int index = classpathContains(newResolvedClasspath, this.oldResolvedClasspath[i]);
+ if (index == -1) {
+ // remote project changes
+ if (this.oldResolvedClasspath[i].getEntryKind() == IClasspathEntry.CPE_PROJECT) {
+ result |= HAS_PROJECT_CHANGE;
+ continue;
+ }
+
+ IPackageFragmentRoot[] pkgFragmentRoots = null;
+ if (removedRoots != null) {
+ IPackageFragmentRoot oldRoot = (IPackageFragmentRoot) removedRoots.get(this.oldResolvedClasspath[i].getPath());
+ if (oldRoot != null) { // use old root if any (could be none if entry wasn't bound)
+ pkgFragmentRoots = new IPackageFragmentRoot[] { oldRoot };
+ }
+ }
+ if (pkgFragmentRoots == null) {
+ try {
+ ObjectVector accumulatedRoots = new ObjectVector();
+ HashSet rootIDs = new HashSet(5);
+ rootIDs.add(this.project.rootID());
+ this.project.computePackageFragmentRoots(
+ this.oldResolvedClasspath[i],
+ accumulatedRoots,
+ rootIDs,
+ null, // inside original project
+ false, // don't check existency
+ false, // don't retrieve exported roots
+ null); /*no reverse map*/
+ pkgFragmentRoots = new IPackageFragmentRoot[accumulatedRoots.size()];
+ accumulatedRoots.copyInto(pkgFragmentRoots);
+ } catch (JavaModelException e) {
+ pkgFragmentRoots = new IPackageFragmentRoot[] {};
+ }
+ }
+ addClasspathDeltas(delta, pkgFragmentRoots, IJavaElementDelta.F_REMOVED_FROM_CLASSPATH);
+ result |= HAS_DELTA;
+ } else {
+ // remote project changes
+ if (this.oldResolvedClasspath[i].getEntryKind() == IClasspathEntry.CPE_PROJECT) {
+ result |= HAS_PROJECT_CHANGE;
+ continue;
+ }
+ if (index != i) { //reordering of the classpath
+ addClasspathDeltas(delta, this.project.computePackageFragmentRoots(this.oldResolvedClasspath[i]), IJavaElementDelta.F_REORDER);
+ result |= HAS_DELTA;
+ }
+
+ // check source attachment
+ IPath newSourcePath = newResolvedClasspath[index].getSourceAttachmentPath();
+ int sourceAttachmentFlags = getSourceAttachmentDeltaFlag(this.oldResolvedClasspath[i].getSourceAttachmentPath(), newSourcePath);
+ IPath oldRootPath = this.oldResolvedClasspath[i].getSourceAttachmentRootPath();
+ IPath newRootPath = newResolvedClasspath[index].getSourceAttachmentRootPath();
+ int sourceAttachmentRootFlags = getSourceAttachmentDeltaFlag(oldRootPath, newRootPath);
+ int flags = sourceAttachmentFlags | sourceAttachmentRootFlags;
+ if (flags != 0) {
+ addClasspathDeltas(delta, this.project.computePackageFragmentRoots(this.oldResolvedClasspath[i]), flags);
+ result |= HAS_DELTA;
+ } else {
+ if (oldRootPath == null && newRootPath == null) {
+ // if source path is specified and no root path, it needs to be recomputed dynamically
+ // force detach source on jar package fragment roots (source will be lazily computed when needed)
+ IPackageFragmentRoot[] computedRoots = this.project.computePackageFragmentRoots(this.oldResolvedClasspath[i]);
+ for (int j = 0; j < computedRoots.length; j++) {
+ IPackageFragmentRoot root = computedRoots[j];
+ // force detach source on jar package fragment roots (source will be lazily computed when needed)
+ try {
+ root.close();
+ } catch (JavaModelException e) {
+ // ignore
+ }
+ }
+ }
+ }
+ }
+ }
+
+ for (int i = 0; i < newLength; i++) {
+ int index = classpathContains(this.oldResolvedClasspath, newResolvedClasspath[i]);
+ if (index == -1) {
+ // remote project changes
+ if (newResolvedClasspath[i].getEntryKind() == IClasspathEntry.CPE_PROJECT) {
+ result |= HAS_PROJECT_CHANGE;
+ continue;
+ }
+ addClasspathDeltas(delta, this.project.computePackageFragmentRoots(newResolvedClasspath[i]), IJavaElementDelta.F_ADDED_TO_CLASSPATH);
+ result |= HAS_DELTA;
+ } // classpath reordering has already been generated in previous loop
+ }
+
+ // see if a change in output location will cause any package fragments to be added/removed
+ if ((newOutputLocation == null && this.oldOutputLocation != null)
+ || (newOutputLocation != null && !newOutputLocation.equals(this.oldOutputLocation))) {
+ try {
+ ArrayList added= determineAffectedPackageFragments(this.oldOutputLocation);
+ Iterator iter = added.iterator();
+ while (iter.hasNext()){
+ IPackageFragment frag= (IPackageFragment)iter.next();
+ ((IPackageFragmentRoot)frag.getParent()).close();
+ delta.added(frag);
+ result |= HAS_DELTA;
+ }
+
+ // see if this will cause any package fragments to be removed
+ ArrayList removed= determineAffectedPackageFragments(newOutputLocation);
+ iter = removed.iterator();
+ while (iter.hasNext()) {
+ IPackageFragment frag= (IPackageFragment)iter.next();
+ ((IPackageFragmentRoot)frag.getParent()).close();
+ delta.removed(frag);
+ result |= HAS_DELTA;
+ }
+ } catch (JavaModelException e) {
+ if (DeltaProcessor.VERBOSE)
+ e.printStackTrace();
+ }
+ }
+
+ return result;
+ }
+
+ /*
+ * Returns the source attachment flag for the delta between the 2 give source paths.
+ * Returns either F_SOURCEATTACHED, F_SOURCEDETACHED, F_SOURCEATTACHED | F_SOURCEDETACHED
+ * or 0 if there is no difference.
+ */
+ private int getSourceAttachmentDeltaFlag(IPath oldPath, IPath newPath) {
+ if (oldPath == null) {
+ if (newPath != null) {
+ return IJavaElementDelta.F_SOURCEATTACHED;
+ } else {
+ return 0;
+ }
+ } else if (newPath == null) {
+ return IJavaElementDelta.F_SOURCEDETACHED;
+ } else if (!oldPath.equals(newPath)) {
+ return IJavaElementDelta.F_SOURCEATTACHED | IJavaElementDelta.F_SOURCEDETACHED;
+ } else {
+ return 0;
+ }
+ }
+
+ public int hashCode() {
+ return this.project.hashCode();
+ }
+
+ /*
+ * Request the indexing of entries that have been added, and remove the index for removed entries.
+ */
+ public void requestIndexing() {
+ IClasspathEntry[] newResolvedClasspath = null;
+ try {
+ newResolvedClasspath = this.project.getResolvedClasspath();
+ } catch (JavaModelException e) {
+ // project doesn't exist
+ return;
+ }
+
+ JavaModelManager manager = JavaModelManager.getJavaModelManager();
+ IndexManager indexManager = manager.indexManager;
+ if (indexManager == null)
+ return;
+ DeltaProcessingState state = manager.deltaState;
+
+ int newLength = newResolvedClasspath.length;
+ int oldLength = this.oldResolvedClasspath.length;
+ for (int i = 0; i < oldLength; i++) {
+ int index = classpathContains(newResolvedClasspath, this.oldResolvedClasspath[i]);
+ if (index == -1) {
+ // remote projects are not indexed in this project
+ if (this.oldResolvedClasspath[i].getEntryKind() == IClasspathEntry.CPE_PROJECT){
+ continue;
+ }
+
+ // Remove the .java files from the index for a source folder
+ // For a lib folder or a .jar file, remove the corresponding index if not shared.
+ IClasspathEntry oldEntry = this.oldResolvedClasspath[i];
+ final IPath path = oldEntry.getPath();
+ int changeKind = this.oldResolvedClasspath[i].getEntryKind();
+ switch (changeKind) {
+ case IClasspathEntry.CPE_SOURCE:
+ char[][] inclusionPatterns = ((ClasspathEntry)oldEntry).fullInclusionPatternChars();
+ char[][] exclusionPatterns = ((ClasspathEntry)oldEntry).fullExclusionPatternChars();
+ indexManager.removeSourceFolderFromIndex(this.project, path, inclusionPatterns, exclusionPatterns);
+ break;
+ case IClasspathEntry.CPE_LIBRARY:
+ if (state.otherRoots.get(path) == null) { // if root was not shared
+ indexManager.discardJobs(path.toString());
+ indexManager.removeIndex(path);
+ // TODO (kent) we could just remove the in-memory index and have the indexing check for timestamps
+ }
+ break;
+ }
+ }
+ }
+
+ for (int i = 0; i < newLength; i++) {
+ int index = classpathContains(this.oldResolvedClasspath, newResolvedClasspath[i]);
+ if (index == -1) {
+ // remote projects are not indexed in this project
+ if (newResolvedClasspath[i].getEntryKind() == IClasspathEntry.CPE_PROJECT){
+ continue;
+ }
+
+ // Request indexing
+ int entryKind = newResolvedClasspath[i].getEntryKind();
+ switch (entryKind) {
+ case IClasspathEntry.CPE_LIBRARY:
+ boolean pathHasChanged = true;
+ IPath newPath = newResolvedClasspath[i].getPath();
+ for (int j = 0; j < oldLength; j++) {
+ IClasspathEntry oldEntry = this.oldResolvedClasspath[j];
+ if (oldEntry.getPath().equals(newPath)) {
+ pathHasChanged = false;
+ break;
+ }
+ }
+ if (pathHasChanged) {
+ indexManager.indexLibrary(newPath, this.project.getProject());
+ }
+ break;
+ case IClasspathEntry.CPE_SOURCE:
+ IClasspathEntry entry = newResolvedClasspath[i];
+ IPath path = entry.getPath();
+ char[][] inclusionPatterns = ((ClasspathEntry)entry).fullInclusionPatternChars();
+ char[][] exclusionPatterns = ((ClasspathEntry)entry).fullExclusionPatternChars();
+ indexManager.indexSourceFolder(this.project, path, inclusionPatterns, exclusionPatterns);
+ break;
+ }
+ }
+ }
+ }
+
+ public String toString() {
+ return "ClasspathChange: " + this.project.getElementName(); //$NON-NLS-1$
+ }
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java
index 66183fc..4278ac2 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,7 +10,11 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core;
+import java.io.ByteArrayOutputStream;
import java.io.File;
+import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@@ -19,8 +23,10 @@
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.AssertionFailedException;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IAccessRule;
import org.eclipse.jdt.core.IClasspathAttribute;
@@ -39,9 +45,12 @@
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.core.util.Messages;
import org.eclipse.jdt.internal.core.util.Util;
+import org.w3c.dom.DOMException;
import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
/**
* @see IClasspathEntry
@@ -69,9 +78,10 @@
public static final String TAG_ACCESSIBLE = "accessible"; //$NON-NLS-1$
public static final String TAG_NON_ACCESSIBLE = "nonaccessible"; //$NON-NLS-1$
public static final String TAG_DISCOURAGED = "discouraged"; //$NON-NLS-1$
-
+ public static final String TAG_IGNORE_IF_BETTER = "ignoreifbetter"; //$NON-NLS-1$
+
/**
- * Describes the kind of classpath entry - one of
+ * Describes the kind of classpath entry - one of
* CPE_PROJECT, CPE_LIBRARY, CPE_SOURCE, CPE_VARIABLE or CPE_CONTAINER
*/
public int entryKind;
@@ -85,15 +95,15 @@
/**
* The meaning of the path of a classpath entry depends on its entry kind:<ul>
- * <li>Source code in the current project (<code>CPE_SOURCE</code>) -
+ * <li>Source code in the current project (<code>CPE_SOURCE</code>) -
* The path associated with this entry is the absolute path to the root folder. </li>
* <li>A binary library in the current project (<code>CPE_LIBRARY</code>) - the path
- * associated with this entry is the absolute path to the JAR (or root folder), and
- * in case it refers to an external JAR, then there is no associated resource in
+ * associated with this entry is the absolute path to the JAR (or root folder), and
+ * in case it refers to an external JAR, then there is no associated resource in
* the workbench.
* <li>A required project (<code>CPE_PROJECT</code>) - the path of the entry denotes the
* path to the corresponding project resource.</li>
- * <li>A variable entry (<code>CPE_VARIABLE</code>) - the first segment of the path
+ * <li>A variable entry (<code>CPE_VARIABLE</code>) - the first segment of the path
* is the name of a classpath variable. If this classpath variable
* is bound to the path <it>P</it>, the path of the corresponding classpath entry
* is computed by appending to <it>P</it> the segments of the returned
@@ -113,32 +123,38 @@
private IPath[] exclusionPatterns;
private char[][] fullExclusionPatternChars;
private final static char[][] UNINIT_PATTERNS = new char[][] { "Non-initialized yet".toCharArray() }; //$NON-NLS-1$
-
+
private boolean combineAccessRules;
-
+
private String rootID;
private AccessRuleSet accessRuleSet;
-
+
+
+ static class UnknownXmlElements {
+ String[] attributes;
+ ArrayList children;
+ }
+
/*
* Default inclusion pattern set
*/
public final static IPath[] INCLUDE_ALL = {};
-
+
/*
* Default exclusion pattern set
*/
public final static IPath[] EXCLUDE_NONE = {};
-
+
/*
* Default extra attributes
*/
public final static IClasspathAttribute[] NO_EXTRA_ATTRIBUTES = {};
-
+
/*
* Default access rules
*/
public final static IAccessRule[] NO_ACCESS_RULES = {};
-
+
/**
* Describes the path to the source archive associated with this
* classpath entry, or <code>null</code> if this classpath entry has no
@@ -147,7 +163,7 @@
* Only library and variable classpath entries may have source attachments.
* For library classpath entries, the result path (if present) locates a source
* archive. For variable classpath entries, the result path (if present) has
- * an analogous form and meaning as the variable path, namely the first segment
+ * an analogous form and meaning as the variable path, namely the first segment
* is the name of a classpath variable.
*/
public IPath sourceAttachmentPath;
@@ -156,7 +172,7 @@
* Describes the path within the source archive where package fragments
* are located. An empty path indicates that packages are located at
* the root of the source archive. Returns a non-<code>null</code> value
- * if and only if <code>getSourceAttachmentPath</code> returns
+ * if and only if <code>getSourceAttachmentPath</code> returns
* a non-<code>null</code> value.
*/
public IPath sourceAttachmentRootPath;
@@ -165,7 +181,7 @@
* Specific output location (for this source entry)
*/
public IPath specificOutputLocation;
-
+
/**
* A constant indicating an output location.
*/
@@ -175,7 +191,7 @@
* The export flag
*/
public boolean isExported;
-
+
/*
* The extra attributes
*/
@@ -203,17 +219,20 @@
this.path = path;
this.inclusionPatterns = inclusionPatterns;
this.exclusionPatterns = exclusionPatterns;
-
- AccessRuleSet ruleSet = createAccessRuleSet(accessRules);
- if (ruleSet != null) {
- // compute message template
- ruleSet.messageTemplate = getMessageTemplate();
+
+ int length;
+ if (accessRules != null && (length = accessRules.length) > 0) {
+ AccessRule[] rules = new AccessRule[length];
+ System.arraycopy(accessRules, 0, rules, 0, length);
+ this.accessRuleSet = new AccessRuleSet(rules, getMessageTemplates());
}
- this.accessRuleSet = ruleSet;
-
+// else { -- implicit!
+// this.accessRuleSet = null;
+// }
+
this.combineAccessRules = combineAccessRules;
this.extraAttributes = extraAttributes;
-
+
if (inclusionPatterns != INCLUDE_ALL && inclusionPatterns.length > 0) {
this.fullInclusionPatternChars = UNINIT_PATTERNS;
}
@@ -225,19 +244,11 @@
this.specificOutputLocation = specificOutputLocation;
this.isExported = isExported;
}
-
- private static AccessRuleSet createAccessRuleSet(IAccessRule[] accessRules) {
- int length = accessRules == null ? 0 : accessRules.length;
- if (length == 0) return null;
- AccessRule[] rules = new AccessRule[length];
- System.arraycopy(accessRules, 0, rules, 0, length);
- return new AccessRuleSet(rules);
- }
-
+
public boolean combineAccessRules() {
return this.combineAccessRules;
}
-
+
/**
* Used to perform export/restriction propagation across referring projects/containers
*/
@@ -246,18 +257,18 @@
if (referringEntry.isExported() || referringEntry.getAccessRuleSet() != null ) {
boolean combine = this.entryKind == CPE_SOURCE || referringEntry.combineAccessRules();
return new ClasspathEntry(
- getContentKind(),
- getEntryKind(),
+ getContentKind(),
+ getEntryKind(),
getPath(),
- this.inclusionPatterns,
- this.exclusionPatterns,
- getSourceAttachmentPath(),
- getSourceAttachmentRootPath(),
- getOutputLocation(),
+ this.inclusionPatterns,
+ this.exclusionPatterns,
+ getSourceAttachmentPath(),
+ getSourceAttachmentRootPath(),
+ getOutputLocation(),
referringEntry.isExported() || this.isExported, // duplicate container entry for tagging it as exported
combine(referringEntry.getAccessRules(), getAccessRules(), combine),
this.combineAccessRules,
- this.extraAttributes);
+ this.extraAttributes);
}
// no need to clone
return this;
@@ -266,7 +277,7 @@
private IAccessRule[] combine(IAccessRule[] referringRules, IAccessRule[] rules, boolean combine) {
if (!combine) return rules;
if (rules == null || rules.length == 0) return referringRules;
-
+
// concat access rules
int referringRulesLength = referringRules.length;
int accessRulesLength = rules.length;
@@ -274,14 +285,11 @@
IAccessRule[] result = new IAccessRule[rulesLength];
System.arraycopy(referringRules, 0, result, 0, referringRulesLength);
System.arraycopy(rules, 0, result, referringRulesLength, accessRulesLength);
-
+
return result;
}
- static IClasspathAttribute[] decodeExtraAttributes(Element element) {
- Node extra = element.getElementsByTagName(TAG_ATTRIBUTES).item(0);
- if (extra == null) return NO_EXTRA_ATTRIBUTES;
- NodeList attributes = element.getElementsByTagName(TAG_ATTRIBUTE);
+ static IClasspathAttribute[] decodeExtraAttributes(NodeList attributes) {
if (attributes == null) return NO_EXTRA_ATTRIBUTES;
int length = attributes.getLength();
if (length == 0) return NO_EXTRA_ATTRIBUTES;
@@ -302,56 +310,110 @@
System.arraycopy(result, 0, result = new IClasspathAttribute[index], 0, index);
return result;
}
-
- static IAccessRule[] decodeAccessRules(Element element) {
- Node accessRules = element.getElementsByTagName(TAG_ACCESS_RULES).item(0);
- if (accessRules == null || accessRules.getNodeType() != Node.ELEMENT_NODE) return null;
- NodeList list = ((Element) accessRules).getElementsByTagName(TAG_ACCESS_RULE);
+
+ static IAccessRule[] decodeAccessRules(NodeList list) {
+ if (list == null) return null;
int length = list.getLength();
if (length == 0) return null;
IAccessRule[] result = new IAccessRule[length];
int index = 0;
for (int i = 0; i < length; i++) {
Node accessRule = list.item(i);
- if (accessRule == null || accessRule.getNodeType() != Node.ELEMENT_NODE) return null;
- Element elementAccessRule = (Element) accessRule;
- String pattern = elementAccessRule.getAttribute(TAG_PATTERN);
- if (pattern == null) continue;
- String tagKind = elementAccessRule.getAttribute(TAG_KIND);
- int kind;
- if (TAG_ACCESSIBLE.equals(tagKind))
- kind = IAccessRule.K_ACCESSIBLE;
- else if (TAG_NON_ACCESSIBLE.equals(tagKind))
- kind = IAccessRule.K_NON_ACCESSIBLE;
- else if (TAG_DISCOURAGED.equals(tagKind))
- kind = IAccessRule.K_DISCOURAGED;
- else
- continue;
- result[index++] = new ClasspathAccessRule(new Path(pattern), kind);
+ if (accessRule.getNodeType() == Node.ELEMENT_NODE) {
+ Element elementAccessRule = (Element) accessRule;
+ String pattern = elementAccessRule.getAttribute(TAG_PATTERN);
+ if (pattern == null) continue;
+ String tagKind = elementAccessRule.getAttribute(TAG_KIND);
+ int kind;
+ if (TAG_ACCESSIBLE.equals(tagKind))
+ kind = IAccessRule.K_ACCESSIBLE;
+ else if (TAG_NON_ACCESSIBLE.equals(tagKind))
+ kind = IAccessRule.K_NON_ACCESSIBLE;
+ else if (TAG_DISCOURAGED.equals(tagKind))
+ kind = IAccessRule.K_DISCOURAGED;
+ else
+ continue;
+ boolean ignoreIfBetter = "true".equals(elementAccessRule.getAttribute(TAG_IGNORE_IF_BETTER)); //$NON-NLS-1$
+ result[index++] = new ClasspathAccessRule(new Path(pattern), ignoreIfBetter ? kind | IAccessRule.IGNORE_IF_BETTER : kind);
+ }
}
if (index != length)
System.arraycopy(result, 0, result = new IAccessRule[index], 0, index);
return result;
}
-
+
/**
* Decode some element tag containing a sequence of patterns into IPath[]
*/
- private static IPath[] decodePatterns(Element element, String tag) {
- String sequence = element.getAttribute(tag);
- if (!sequence.equals("")) { //$NON-NLS-1$
+ private static IPath[] decodePatterns(NamedNodeMap nodeMap, String tag) {
+ String sequence = removeAttribute(tag, nodeMap);
+ if (!sequence.equals("")) { //$NON-NLS-1$
char[][] patterns = CharOperation.splitOn('|', sequence.toCharArray());
int patternCount;
- if ((patternCount = patterns.length) > 0) {
+ if ((patternCount = patterns.length) > 0) {
IPath[] paths = new IPath[patternCount];
- for (int j = 0; j < patterns.length; j++){
- paths[j] = new Path(new String(patterns[j]));
+ int index = 0;
+ for (int j = 0; j < patternCount; j++) {
+ char[] pattern = patterns[j];
+ if (pattern.length == 0) continue; // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=105581
+ paths[index++] = new Path(new String(pattern));
}
+ if (index < patternCount)
+ System.arraycopy(paths, 0, paths = new IPath[index], 0, index);
return paths;
}
}
return null;
}
+
+ private static void decodeUnknownNode(Node node, StringBuffer buffer, IJavaProject project) {
+ ByteArrayOutputStream s = new ByteArrayOutputStream();
+ OutputStreamWriter writer;
+ try {
+ writer = new OutputStreamWriter(s, "UTF8"); //$NON-NLS-1$
+ XMLWriter xmlWriter = new XMLWriter(writer, project, false/*don't print XML version*/);
+ decodeUnknownNode(node, xmlWriter, true/*insert new line*/);
+ xmlWriter.flush();
+ xmlWriter.close();
+ buffer.append(s.toString("UTF8")); //$NON-NLS-1$
+ } catch (UnsupportedEncodingException e) {
+ // ignore (UTF8 is always supported)
+ }
+ }
+
+ private static void decodeUnknownNode(Node node, XMLWriter xmlWriter, boolean insertNewLine) {
+ switch (node.getNodeType()) {
+ case Node.ELEMENT_NODE:
+ NamedNodeMap attributes;
+ HashMap parameters = null;
+ if ((attributes = node.getAttributes()) != null) {
+ int length = attributes.getLength();
+ if (length > 0) {
+ parameters = new HashMap();
+ for (int i = 0; i < length; i++) {
+ Node attribute = attributes.item(i);
+ parameters.put(attribute.getNodeName(), attribute.getNodeValue());
+ }
+ }
+ }
+ NodeList children = node.getChildNodes();
+ int childrenLength = children.getLength();
+ String nodeName = node.getNodeName();
+ xmlWriter.printTag(nodeName, parameters, false/*don't insert tab*/, false/*don't insert new line*/, childrenLength == 0/*close tag if no children*/);
+ if (childrenLength > 0) {
+ for (int i = 0; i < childrenLength; i++) {
+ decodeUnknownNode(children.item(i), xmlWriter, false/*don't insert new line*/);
+ }
+ xmlWriter.endTag(nodeName, false/*don't insert tab*/, insertNewLine);
+ }
+ break;
+ case Node.TEXT_NODE:
+ String data = ((Text) node).getData();
+ xmlWriter.printString(data, false/*don't insert tab*/, false/*don't insert new line*/);
+ break;
+ }
+ }
+
/*
* Returns a char based representation of the exclusions patterns full path.
*/
@@ -362,13 +424,13 @@
this.fullExclusionPatternChars = new char[length][];
IPath prefixPath = this.path.removeTrailingSeparator();
for (int i = 0; i < length; i++) {
- this.fullExclusionPatternChars[i] =
+ this.fullExclusionPatternChars[i] =
prefixPath.append(this.exclusionPatterns[i]).toString().toCharArray();
}
}
return this.fullExclusionPatternChars;
}
-
+
/*
* Returns a char based representation of the exclusions patterns full path.
*/
@@ -379,7 +441,7 @@
this.fullInclusionPatternChars = new char[length][];
IPath prefixPath = this.path.removeTrailingSeparator();
for (int i = 0; i < length; i++) {
- this.fullInclusionPatternChars[i] =
+ this.fullInclusionPatternChars[i] =
prefixPath.append(this.inclusionPatterns[i]).toString().toCharArray();
}
}
@@ -389,11 +451,11 @@
/**
* Returns the XML encoding of the class path.
*/
- public void elementEncode(XMLWriter writer, IPath projectPath, boolean indent, boolean newLine) {
+ public void elementEncode(XMLWriter writer, IPath projectPath, boolean indent, boolean newLine, Map unknownElements) {
HashMap parameters = new HashMap();
-
+
parameters.put(TAG_KIND, ClasspathEntry.kindToString(this.entryKind));
-
+
IPath xmlPath = this.path;
if (this.entryKind != IClasspathEntry.CPE_VARIABLE && this.entryKind != IClasspathEntry.CPE_CONTAINER) {
// translate to project relative from absolute (unless a device path)
@@ -409,10 +471,10 @@
}
}
parameters.put(TAG_PATH, String.valueOf(xmlPath));
-
+
if (this.sourceAttachmentPath != null) {
xmlPath = this.sourceAttachmentPath;
- // translate to project relative from absolute
+ // translate to project relative from absolute
if (this.entryKind != IClasspathEntry.CPE_VARIABLE && projectPath != null && projectPath.isPrefixOf(xmlPath)) {
if (xmlPath.segment(0).equals(projectPath.segment(0))) {
xmlPath = xmlPath.removeFirstSegments(1);
@@ -431,8 +493,18 @@
encodePatterns(this.exclusionPatterns, TAG_EXCLUDING, parameters);
if (this.entryKind == CPE_PROJECT && !this.combineAccessRules)
parameters.put(TAG_COMBINE_ACCESS_RULES, "false"); //$NON-NLS-1$
-
-
+
+
+ // unknown attributes
+ UnknownXmlElements unknownXmlElements = unknownElements == null ? null : (UnknownXmlElements) unknownElements.get(this.path);
+ String[] unknownAttributes;
+ if (unknownXmlElements != null && (unknownAttributes = unknownXmlElements.attributes) != null)
+ for (int i = 0, length = unknownAttributes.length; i < length; i+=2) {
+ String tagName = unknownAttributes[i];
+ String tagValue = unknownAttributes[i+1];
+ parameters.put(tagName, tagValue);
+ }
+
if (this.specificOutputLocation != null) {
IPath outputLocation = this.specificOutputLocation.removeFirstSegments(1);
outputLocation = outputLocation.makeRelative();
@@ -441,18 +513,28 @@
boolean hasExtraAttributes = this.extraAttributes.length != 0;
boolean hasRestrictions = getAccessRuleSet() != null; // access rule set is null if no access rules
- writer.printTag(TAG_CLASSPATHENTRY, parameters, indent, newLine, !hasExtraAttributes && !hasRestrictions /*close tag if no extra attributes and no restriction*/);
-
+ ArrayList unknownChildren = unknownXmlElements != null ? unknownXmlElements.children : null;
+ boolean hasUnknownChildren = unknownChildren != null;
+ writer.printTag(
+ TAG_CLASSPATHENTRY,
+ parameters,
+ indent,
+ newLine,
+ !hasExtraAttributes && !hasRestrictions && !hasUnknownChildren/*close tag if no extra attributes, no restriction and no unknown children*/);
+
if (hasExtraAttributes)
encodeExtraAttributes(writer, indent, newLine);
-
+
if (hasRestrictions)
encodeAccessRules(writer, indent, newLine);
- if (hasExtraAttributes || hasRestrictions)
- writer.endTag(TAG_CLASSPATHENTRY, indent);
+ if (hasUnknownChildren)
+ encodeUnknownChildren(writer, indent, newLine, unknownChildren);
+
+ if (hasExtraAttributes || hasRestrictions || hasUnknownChildren)
+ writer.endTag(TAG_CLASSPATHENTRY, indent, true/*insert new line*/);
}
-
+
void encodeExtraAttributes(XMLWriter writer, boolean indent, boolean newLine) {
writer.startTag(TAG_ATTRIBUTES, indent);
for (int i = 0; i < this.extraAttributes.length; i++) {
@@ -462,9 +544,9 @@
parameters.put(TAG_ATTRIBUTE_VALUE, attribute.getValue());
writer.printTag(TAG_ATTRIBUTE, parameters, indent, newLine, true);
}
- writer.endTag(TAG_ATTRIBUTES, indent);
+ writer.endTag(TAG_ATTRIBUTES, indent, true/*insert new line*/);
}
-
+
void encodeAccessRules(XMLWriter writer, boolean indent, boolean newLine) {
writer.startTag(TAG_ACCESS_RULES, indent);
@@ -472,15 +554,15 @@
for (int i = 0, length = rules.length; i < length; i++) {
encodeAccessRule(rules[i], writer, indent, newLine);
}
- writer.endTag(TAG_ACCESS_RULES, indent);
+ writer.endTag(TAG_ACCESS_RULES, indent, true/*insert new line*/);
}
-
+
private void encodeAccessRule(AccessRule accessRule, XMLWriter writer, boolean indent, boolean newLine) {
HashMap parameters = new HashMap();
parameters.put(TAG_PATTERN, new String(accessRule.pattern));
-
- switch (accessRule.problemId) {
+
+ switch (accessRule.getProblemId()) {
case IProblem.ForbiddenReference:
parameters.put(TAG_KIND, TAG_NON_ACCESSIBLE);
break;
@@ -491,76 +573,126 @@
parameters.put(TAG_KIND, TAG_ACCESSIBLE);
break;
}
-
+ if (accessRule.ignoreIfBetter())
+ parameters.put(TAG_IGNORE_IF_BETTER, "true"); //$NON-NLS-1$
+
writer.printTag(TAG_ACCESS_RULE, parameters, indent, newLine, true);
}
-
- public static IClasspathEntry elementDecode(Element element, IJavaProject project) {
-
+
+ private void encodeUnknownChildren(XMLWriter writer, boolean indent, boolean newLine, ArrayList unknownChildren) {
+ for (int i = 0, length = unknownChildren.size(); i < length; i++) {
+ String child = (String) unknownChildren.get(i);
+ writer.printString(child, indent, false/*don't insert new line*/);
+ }
+ }
+
+ public static IClasspathEntry elementDecode(Element element, IJavaProject project, Map unknownElements) {
+
IPath projectPath = project.getProject().getFullPath();
- String kindAttr = element.getAttribute(TAG_KIND);
- String pathAttr = element.getAttribute(TAG_PATH);
+ NamedNodeMap attributes = element.getAttributes();
+ NodeList children = element.getChildNodes();
+ boolean[] foundChildren = new boolean[children.getLength()];
+ String kindAttr = removeAttribute(TAG_KIND, attributes);
+ String pathAttr = removeAttribute(TAG_PATH, attributes);
// ensure path is absolute
- IPath path = new Path(pathAttr);
+ IPath path = new Path(pathAttr);
int kind = kindFromString(kindAttr);
if (kind != IClasspathEntry.CPE_VARIABLE && kind != IClasspathEntry.CPE_CONTAINER && !path.isAbsolute()) {
path = projectPath.append(path);
}
// source attachment info (optional)
- IPath sourceAttachmentPath =
- element.hasAttribute(TAG_SOURCEPATH)
- ? new Path(element.getAttribute(TAG_SOURCEPATH))
+ IPath sourceAttachmentPath =
+ element.hasAttribute(TAG_SOURCEPATH)
+ ? new Path(removeAttribute(TAG_SOURCEPATH, attributes))
: null;
if (kind != IClasspathEntry.CPE_VARIABLE && sourceAttachmentPath != null && !sourceAttachmentPath.isAbsolute()) {
sourceAttachmentPath = projectPath.append(sourceAttachmentPath);
}
- IPath sourceAttachmentRootPath =
+ IPath sourceAttachmentRootPath =
element.hasAttribute(TAG_ROOTPATH)
- ? new Path(element.getAttribute(TAG_ROOTPATH))
+ ? new Path(removeAttribute(TAG_ROOTPATH, attributes))
: null;
-
+
// exported flag (optional)
- boolean isExported = element.getAttribute(TAG_EXPORTED).equals("true"); //$NON-NLS-1$
+ boolean isExported = removeAttribute(TAG_EXPORTED, attributes).equals("true"); //$NON-NLS-1$
// inclusion patterns (optional)
- IPath[] inclusionPatterns = decodePatterns(element, TAG_INCLUDING);
+ IPath[] inclusionPatterns = decodePatterns(attributes, TAG_INCLUDING);
if (inclusionPatterns == null) inclusionPatterns = INCLUDE_ALL;
-
+
// exclusion patterns (optional)
- IPath[] exclusionPatterns = decodePatterns(element, TAG_EXCLUDING);
+ IPath[] exclusionPatterns = decodePatterns(attributes, TAG_EXCLUDING);
if (exclusionPatterns == null) exclusionPatterns = EXCLUDE_NONE;
-
+
// access rules (optional)
- IAccessRule[] accessRules = decodeAccessRules(element);
-
+ NodeList attributeList = getChildAttributes(TAG_ACCESS_RULES, children, foundChildren);
+ IAccessRule[] accessRules = decodeAccessRules(attributeList);
+
// backward compatibility
if (accessRules == null) {
accessRules = getAccessRules(inclusionPatterns, exclusionPatterns);
}
// combine access rules (optional)
- boolean combineAccessRestrictions = !element.getAttribute(TAG_COMBINE_ACCESS_RULES).equals("false"); //$NON-NLS-1$
-
+ boolean combineAccessRestrictions = !removeAttribute(TAG_COMBINE_ACCESS_RULES, attributes).equals("false"); //$NON-NLS-1$
+
// extra attributes (optional)
- IClasspathAttribute[] extraAttributes = decodeExtraAttributes(element);
-
+ attributeList = getChildAttributes(TAG_ATTRIBUTES, children, foundChildren);
+ IClasspathAttribute[] extraAttributes = decodeExtraAttributes(attributeList);
+
// custom output location
- IPath outputLocation = element.hasAttribute(TAG_OUTPUT) ? projectPath.append(element.getAttribute(TAG_OUTPUT)) : null;
-
+ IPath outputLocation = element.hasAttribute(TAG_OUTPUT) ? projectPath.append(removeAttribute(TAG_OUTPUT, attributes)) : null;
+
+ String[] unknownAttributes = null;
+ ArrayList unknownChildren = null;
+
+ if (unknownElements != null) {
+ // unknown attributes
+ int unknownAttributeLength = attributes.getLength();
+ if (unknownAttributeLength != 0) {
+ unknownAttributes = new String[unknownAttributeLength*2];
+ for (int i = 0; i < unknownAttributeLength; i++) {
+ Node attribute = attributes.item(i);
+ unknownAttributes[i*2] = attribute.getNodeName();
+ unknownAttributes[i*2 + 1] = attribute.getNodeValue();
+ }
+ }
+
+ // unknown children
+ for (int i = 0, length = foundChildren.length; i < length; i++) {
+ if (!foundChildren[i]) {
+ Node node = children.item(i);
+ if (node.getNodeType() != Node.ELEMENT_NODE) continue;
+ if (unknownChildren == null)
+ unknownChildren = new ArrayList();
+ StringBuffer buffer = new StringBuffer();
+ decodeUnknownNode(node, buffer, project);
+ unknownChildren.add(buffer.toString());
+ }
+ }
+ }
+
// recreate the CP entry
IClasspathEntry entry = null;
switch (kind) {
case IClasspathEntry.CPE_PROJECT :
- entry = JavaCore.newProjectEntry(
- path,
- accessRules,
- combineAccessRestrictions,
- extraAttributes,
- isExported);
- break;
+ entry = new ClasspathEntry(
+ IPackageFragmentRoot.K_SOURCE,
+ IClasspathEntry.CPE_PROJECT,
+ path,
+ ClasspathEntry.INCLUDE_ALL, // inclusion patterns
+ ClasspathEntry.EXCLUDE_NONE, // exclusion patterns
+ null, // source attachment
+ null, // source attachment root
+ null, // specific output folder
+ isExported,
+ accessRules,
+ combineAccessRestrictions,
+ extraAttributes);
+ break;
case IClasspathEntry.CPE_LIBRARY :
entry = JavaCore.newLibraryEntry(
path,
@@ -574,19 +706,19 @@
// must be an entry in this project or specify another project
String projSegment = path.segment(0);
if (projSegment != null && projSegment.equals(project.getElementName())) { // this project
- return JavaCore.newSourceEntry(path, inclusionPatterns, exclusionPatterns, outputLocation, extraAttributes);
- } else {
+ entry = JavaCore.newSourceEntry(path, inclusionPatterns, exclusionPatterns, outputLocation, extraAttributes);
+ } else {
if (path.segmentCount() == 1) {
// another project
entry = JavaCore.newProjectEntry(
- path,
+ path,
accessRules,
combineAccessRestrictions,
extraAttributes,
isExported);
} else {
// an invalid source folder
- return JavaCore.newSourceEntry(path, inclusionPatterns, exclusionPatterns, outputLocation, extraAttributes);
+ entry = JavaCore.newSourceEntry(path, inclusionPatterns, exclusionPatterns, outputLocation, extraAttributes);
}
}
break;
@@ -594,7 +726,7 @@
entry = JavaCore.newVariableEntry(
path,
sourceAttachmentPath,
- sourceAttachmentRootPath,
+ sourceAttachmentRootPath,
accessRules,
extraAttributes,
isExported);
@@ -608,12 +740,12 @@
break;
case ClasspathEntry.K_OUTPUT :
if (!path.isAbsolute()) return null;
- return new ClasspathEntry(
+ entry = new ClasspathEntry(
ClasspathEntry.K_OUTPUT,
IClasspathEntry.CPE_LIBRARY,
path,
- INCLUDE_ALL,
- EXCLUDE_NONE,
+ INCLUDE_ALL,
+ EXCLUDE_NONE,
null, // source attachment
null, // source attachment root
null, // custom output location
@@ -621,12 +753,50 @@
null, // no access rules
false, // no accessible files to combine
NO_EXTRA_ATTRIBUTES);
+ break;
default :
- throw new Assert.AssertionFailedException(Messages.bind(Messages.classpath_unknownKind, kindAttr));
+ throw new AssertionFailedException(Messages.bind(Messages.classpath_unknownKind, kindAttr));
}
+
+ if (unknownAttributes != null || unknownChildren != null) {
+ UnknownXmlElements unknownXmlElements = new UnknownXmlElements();
+ unknownXmlElements.attributes = unknownAttributes;
+ unknownXmlElements.children = unknownChildren;
+ unknownElements.put(path, unknownXmlElements);
+ }
+
return entry;
}
+ public static NodeList getChildAttributes(String childName, NodeList children, boolean[] foundChildren) {
+ for (int i = 0, length = foundChildren.length; i < length; i++) {
+ Node node = children.item(i);
+ if (childName.equals(node.getNodeName())) {
+ foundChildren[i] = true;
+ return node.getChildNodes();
+ }
+ }
+ return null;
+ }
+
+
+ private static String removeAttribute(String nodeName, NamedNodeMap nodeMap) {
+ Node node = removeNode(nodeName, nodeMap);
+ if (node == null)
+ return ""; // //$NON-NLS-1$
+ return node.getNodeValue();
+ }
+
+ private static Node removeNode(String nodeName, NamedNodeMap nodeMap) {
+ try {
+ return nodeMap.removeNamedItem(nodeName);
+ } catch (DOMException e) {
+ if (e.code != DOMException.NOT_FOUND_ERR)
+ throw e;
+ return null;
+ }
+ }
+
/**
* Encode some patterns into XML parameter tag
*/
@@ -713,7 +883,7 @@
if (firstAttributes != secondAttributes){
if (firstAttributes == null) return false;
int length = firstAttributes.length;
- if (secondAttributes == null || secondAttributes.length != length)
+ if (secondAttributes == null || secondAttributes.length != length)
return false;
for (int i = 0; i < length; i++) {
if (!firstAttributes[i].equals(secondAttributes[i]))
@@ -722,15 +892,15 @@
}
return true;
}
-
+
private static boolean equalPatterns(IPath[] firstPatterns, IPath[] secondPatterns) {
if (firstPatterns != secondPatterns){
if (firstPatterns == null) return false;
int length = firstPatterns.length;
- if (secondPatterns == null || secondPatterns.length != length)
+ if (secondPatterns == null || secondPatterns.length != length)
return false;
for (int i = 0; i < length; i++) {
- // compare toStrings instead of IPaths
+ // compare toStrings instead of IPaths
// since IPath.equals is specified to ignore trailing separators
if (!firstPatterns[i].toString().equals(secondPatterns[i].toString()))
return false;
@@ -738,7 +908,7 @@
}
return true;
}
-
+
/**
* @see IClasspathEntry#getAccessRules()
*/
@@ -751,7 +921,7 @@
System.arraycopy(rules, 0, result, 0, length);
return result;
}
-
+
public AccessRuleSet getAccessRuleSet() {
return this.accessRuleSet;
}
@@ -776,16 +946,27 @@
public IPath[] getExclusionPatterns() {
return this.exclusionPatterns;
}
-
+
public IClasspathAttribute[] getExtraAttributes() {
return this.extraAttributes;
}
-
- private String getMessageTemplate() {
+
+ private String[] getMessageTemplates() {
+ JavaModelManager manager = JavaModelManager.getJavaModelManager();
+ String [] result = new String[AccessRuleSet.MESSAGE_TEMPLATES_LENGTH];
if (this.entryKind == CPE_PROJECT || this.entryKind == CPE_SOURCE) { // can be remote source entry when reconciling
- return Messages.bind(
+ result[0] = manager.intern(Messages.bind(
org.eclipse.jdt.internal.core.util.Messages.restrictedAccess_project,
- new String[] {"{0}", getPath().segment(0)}); //$NON-NLS-1$
+ new String[] {"{0}", getPath().segment(0)})); //$NON-NLS-1$
+ result[1] = manager.intern(Messages.bind(
+ org.eclipse.jdt.internal.core.util.Messages.restrictedAccess_constructor_project,
+ new String[] {"{0}", getPath().segment(0)})); //$NON-NLS-1$
+ result[2] = manager.intern(Messages.bind(
+ org.eclipse.jdt.internal.core.util.Messages.restrictedAccess_method_project,
+ new String[] {"{0}", "{1}", getPath().segment(0)})); //$NON-NLS-1$ //$NON-NLS-2$
+ result[3] = manager.intern(Messages.bind(
+ org.eclipse.jdt.internal.core.util.Messages.restrictedAccess_field_project,
+ new String[] {"{0}", "{1}", getPath().segment(0)})); //$NON-NLS-1$ //$NON-NLS-2$
} else {
IPath libPath = getPath();
Object target = JavaModel.getTarget(ResourcesPlugin.getWorkspace().getRoot(), libPath, false);
@@ -794,10 +975,20 @@
pathString = libPath.toOSString();
else
pathString = libPath.makeRelative().toString();
- return Messages.bind(
+ result[0] = manager.intern(Messages.bind(
org.eclipse.jdt.internal.core.util.Messages.restrictedAccess_library,
- new String[] {"{0}", pathString}); //$NON-NLS-1$
+ new String[] {"{0}", pathString})); //$NON-NLS-1$
+ result[1] = manager.intern(Messages.bind(
+ org.eclipse.jdt.internal.core.util.Messages.restrictedAccess_constructor_library,
+ new String[] {"{0}", pathString})); //$NON-NLS-1$
+ result[2] = manager.intern(Messages.bind(
+ org.eclipse.jdt.internal.core.util.Messages.restrictedAccess_method_library,
+ new String[] {"{0}", "{1}", pathString})); //$NON-NLS-1$ //$NON-NLS-2$
+ result[3] = manager.intern(Messages.bind(
+ org.eclipse.jdt.internal.core.util.Messages.restrictedAccess_field_library,
+ new String[] {"{0}", "{1}", pathString})); //$NON-NLS-1$ //$NON-NLS-2$
}
+ return result;
}
/**
@@ -820,7 +1011,7 @@
public IPath getPath() {
return this.path;
}
-
+
/**
* @see IClasspathEntry
*/
@@ -849,6 +1040,15 @@
return this.isExported;
}
+ public boolean isOptional() {
+ for (int i = 0, length = this.extraAttributes.length; i < length; i++) {
+ IClasspathAttribute attribute = this.extraAttributes[i];
+ if (IClasspathAttribute.OPTIONAL.equals(attribute.getName()) && "true".equals(attribute.getValue())) //$NON-NLS-1$
+ return true;
+ }
+ return false;
+ }
+
/**
* Returns the kind of a <code>PackageFragmentRoot</code> from its <code>String</code> form.
*/
@@ -892,6 +1092,9 @@
}
}
+ /*
+ * Backward compatibility: only accessible and non-accessible files are suported.
+ */
public static IAccessRule[] getAccessRules(IPath[] accessibleFiles, IPath[] nonAccessibleFiles) {
int accessibleFilesLength = accessibleFiles == null ? 0 : accessibleFiles.length;
int nonAccessibleFilesLength = nonAccessibleFiles == null ? 0 : nonAccessibleFiles.length;
@@ -906,13 +1109,13 @@
}
return accessRules;
}
-
+
/**
* Returns a printable representation of this classpath entry.
*/
public String toString() {
StringBuffer buffer = new StringBuffer();
- buffer.append(getPath().toString());
+ buffer.append(String.valueOf(getPath()));
buffer.append('[');
switch (getEntryKind()) {
case IClasspathEntry.CPE_LIBRARY :
@@ -1007,7 +1210,7 @@
}
return buffer.toString();
}
-
+
/**
* Answers an ID which is used to distinguish entries during package
* fragment root computations
@@ -1038,16 +1241,16 @@
}
return this.rootID;
}
-
+
/**
* @see IClasspathEntry
* @deprecated
*/
public IClasspathEntry getResolvedEntry() {
-
+
return JavaCore.getResolvedClasspathEntry(this);
}
-
+
/**
* Validate a given classpath and output location for a project, using the following rules:
* <ul>
@@ -1056,15 +1259,15 @@
* <li> Specific output locations (specified on source entries) can be null, if not they must be located inside the project,
* <li> A project entry cannot refer to itself directly (that is, a project cannot prerequisite itself).
* <li> Classpath entries or output locations cannot coincidate or be nested in each other, except for the following scenarii listed below:
- * <ul><li> A source folder can coincidate with its own output location, in which case this output can then contain library archives.
- * However, a specific output location cannot coincidate with any library or a distinct source folder than the one referring to it. </li>
+ * <ul><li> A source folder can coincidate with its own output location, in which case this output can then contain library archives.
+ * However, a specific output location cannot coincidate with any library or a distinct source folder than the one referring to it. </li>
* <li> A source/library folder can be nested in any source folder as long as the nested folder is excluded from the enclosing one. </li>
* <li> An output location can be nested in a source folder, if the source folder coincidates with the project itself, or if the output
* location is excluded from the source folder. </li>
* </ul>
* </ul>
- *
- * Note that the classpath entries are not validated automatically. Only bound variables or containers are considered
+ *
+ * Note that the classpath entries are not validated automatically. Only bound variables or containers are considered
* in the checking process (this allows to perform a consistency check on a classpath which has references to
* yet non existing projects, folders, ...).
* <p>
@@ -1075,15 +1278,15 @@
* @param rawClasspath a given classpath
* @param projectOutputLocation a given output location
* @return a status object with code <code>IStatus.OK</code> if
- * the given classpath and output location are compatible, otherwise a status
+ * the given classpath and output location are compatible, otherwise a status
* object indicating what is wrong with the classpath or output location
*/
public static IJavaModelStatus validateClasspath(IJavaProject javaProject, IClasspathEntry[] rawClasspath, IPath projectOutputLocation) {
-
+
IProject project = javaProject.getProject();
IPath projectPath= project.getFullPath();
String projectName = javaProject.getElementName();
-
+
/* validate output location */
if (projectOutputLocation == null) {
return new JavaModelStatus(IJavaModelStatusConstants.NULL_PATH);
@@ -1095,39 +1298,39 @@
} else {
return new JavaModelStatus(IJavaModelStatusConstants.RELATIVE_PATH, projectOutputLocation);
}
-
+
boolean hasSource = false;
boolean hasLibFolder = false;
-
+
// tolerate null path, it will be reset to default
- if (rawClasspath == null)
+ if (rawClasspath == null)
return JavaModelStatus.VERIFIED_OK;
-
+
// retrieve resolved classpath
- IClasspathEntry[] classpath;
+ IClasspathEntry[] classpath;
try {
- classpath = ((JavaProject)javaProject).getResolvedClasspath(rawClasspath, null /*output*/, true/*ignore pb*/, false/*no marker*/, null /*no reverse map*/);
+ classpath = ((JavaProject)javaProject).resolveClasspath(rawClasspath);
} catch(JavaModelException e){
return e.getJavaModelStatus();
}
- int length = classpath.length;
+ int length = classpath.length;
int outputCount = 1;
IPath[] outputLocations = new IPath[length+1];
boolean[] allowNestingInOutputLocations = new boolean[length+1];
outputLocations[0] = projectOutputLocation;
-
+
// retrieve and check output locations
IPath potentialNestedOutput = null; // for error reporting purpose
int sourceEntryCount = 0;
boolean disableExclusionPatterns = JavaCore.DISABLED.equals(javaProject.getOption(JavaCore.CORE_ENABLE_CLASSPATH_EXCLUSION_PATTERNS, true));
boolean disableCustomOutputLocations = JavaCore.DISABLED.equals(javaProject.getOption(JavaCore.CORE_ENABLE_CLASSPATH_MULTIPLE_OUTPUT_LOCATIONS, true));
-
+
for (int i = 0 ; i < length; i++) {
IClasspathEntry resolvedEntry = classpath[i];
if (disableExclusionPatterns &&
- ((resolvedEntry.getInclusionPatterns() != null && resolvedEntry.getInclusionPatterns().length > 0)
+ ((resolvedEntry.getInclusionPatterns() != null && resolvedEntry.getInclusionPatterns().length > 0)
|| (resolvedEntry.getExclusionPatterns() != null && resolvedEntry.getExclusionPatterns().length > 0))) {
return new JavaModelStatus(IJavaModelStatusConstants.DISABLED_CP_EXCLUSION_PATTERNS, javaProject, resolvedEntry.getPath());
}
@@ -1135,7 +1338,7 @@
case IClasspathEntry.CPE_SOURCE :
sourceEntryCount++;
- IPath customOutput;
+ IPath customOutput;
if ((customOutput = resolvedEntry.getOutputLocation()) != null) {
if (disableCustomOutputLocations) {
@@ -1149,7 +1352,7 @@
} else {
return new JavaModelStatus(IJavaModelStatusConstants.RELATIVE_PATH, customOutput);
}
-
+
// ensure custom output doesn't conflict with other outputs
// check exact match
if (Util.indexOfMatchingPath(customOutput, outputLocations, outputCount) != -1) {
@@ -1171,15 +1374,15 @@
// output before complaining
if (potentialNestedOutput == null) potentialNestedOutput = customOutput;
} else {
- return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_cannotNestOutputInOutput, new String[] {customOutput.makeRelative().toString(), outputLocations[index].makeRelative().toString()}));
+ return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_cannotNestOutputInOutput, new String[] {customOutput.makeRelative().toString(), outputLocations[index].makeRelative().toString()}));
}
}
- }
+ }
// allow custom output nesting in project's output if all source entries have a custom output
if (sourceEntryCount <= outputCount-1) {
allowNestingInOutputLocations[0] = true;
} else if (potentialNestedOutput != null) {
- return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_cannotNestOutputInOutput, new String[] {potentialNestedOutput.makeRelative().toString(), outputLocations[0].makeRelative().toString()}));
+ return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_cannotNestOutputInOutput, new String[] {potentialNestedOutput.makeRelative().toString(), outputLocations[0].makeRelative().toString()}));
}
for (int i = 0 ; i < length; i++) {
@@ -1187,7 +1390,7 @@
IPath path = resolvedEntry.getPath();
int index;
switch(resolvedEntry.getEntryKind()){
-
+
case IClasspathEntry.CPE_SOURCE :
hasSource = true;
if ((index = Util.indexOfMatchingPath(path, outputLocations, outputCount)) != -1){
@@ -1206,23 +1409,23 @@
if (!hasSource && !hasLibFolder) { // if no source and no lib folder, then allowed
for (int i = 0; i < outputCount; i++) allowNestingInOutputLocations[i] = true;
}
-
+
HashSet pathes = new HashSet(length);
-
+
// check all entries
for (int i = 0 ; i < length; i++) {
IClasspathEntry entry = classpath[i];
if (entry == null) continue;
IPath entryPath = entry.getPath();
int kind = entry.getEntryKind();
-
+
// Build some common strings for status message
boolean isProjectRelative = projectName.equals(entryPath.segment(0));
String entryPathMsg = isProjectRelative ? entryPath.removeFirstSegments(1).toString() : entryPath.makeRelative().toString();
-
+
// complain if duplicate path
if (!pathes.add(entryPath)){
- return new JavaModelStatus(IJavaModelStatusConstants.NAME_COLLISION, Messages.bind(Messages.classpath_duplicateEntryPath, new String[] {entryPathMsg, projectName}));
+ return new JavaModelStatus(IJavaModelStatusConstants.NAME_COLLISION, Messages.bind(Messages.classpath_duplicateEntryPath, new String[] {entryPathMsg, projectName}));
}
// no further check if entry coincidates with project or output location
if (entryPath.equals(projectPath)){
@@ -1233,39 +1436,43 @@
// tolerate nesting output in src if src==prj
continue;
}
-
+
// allow nesting source entries in each other as long as the outer entry excludes the inner one
- if (kind == IClasspathEntry.CPE_SOURCE
+ if (kind == IClasspathEntry.CPE_SOURCE
|| (kind == IClasspathEntry.CPE_LIBRARY && !org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(entryPath.lastSegment()))){
for (int j = 0; j < classpath.length; j++){
IClasspathEntry otherEntry = classpath[j];
if (otherEntry == null) continue;
int otherKind = otherEntry.getEntryKind();
IPath otherPath = otherEntry.getPath();
- if (entry != otherEntry
- && (otherKind == IClasspathEntry.CPE_SOURCE
- || (otherKind == IClasspathEntry.CPE_LIBRARY
+ if (entry != otherEntry
+ && (otherKind == IClasspathEntry.CPE_SOURCE
+ || (otherKind == IClasspathEntry.CPE_LIBRARY
&& !org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(otherPath.lastSegment())))){
char[][] inclusionPatterns, exclusionPatterns;
- if (otherPath.isPrefixOf(entryPath)
+ if (otherPath.isPrefixOf(entryPath)
&& !otherPath.equals(entryPath)
&& !Util.isExcluded(entryPath.append("*"), inclusionPatterns = ((ClasspathEntry)otherEntry).fullInclusionPatternChars(), exclusionPatterns = ((ClasspathEntry)otherEntry).fullExclusionPatternChars(), false)) { //$NON-NLS-1$
String exclusionPattern = entryPath.removeFirstSegments(otherPath.segmentCount()).segment(0);
if (Util.isExcluded(entryPath, inclusionPatterns, exclusionPatterns, false)) {
- return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_mustEndWithSlash, new String[] {exclusionPattern, entryPath.makeRelative().toString()}));
+ return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_mustEndWithSlash, new String[] {exclusionPattern, entryPath.makeRelative().toString()}));
} else {
if (otherKind == IClasspathEntry.CPE_SOURCE) {
exclusionPattern += '/';
- return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_cannotNestEntryInEntry, new String[] {entryPath.makeRelative().toString(), otherEntry.getPath().makeRelative().toString(), exclusionPattern}));
+ if (!disableExclusionPatterns) {
+ return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_cannotNestEntryInEntry, new String[] {entryPath.makeRelative().toString(), otherEntry.getPath().makeRelative().toString(), exclusionPattern}));
+ } else {
+ return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_cannotNestEntryInEntryNoExclusion, new String[] {entryPath.makeRelative().toString(), otherEntry.getPath().makeRelative().toString(), exclusionPattern}));
+ }
} else {
- return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_cannotNestEntryInLibrary, new String[] {entryPath.makeRelative().toString(), otherEntry.getPath().makeRelative().toString()}));
+ return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_cannotNestEntryInLibrary, new String[] {entryPath.makeRelative().toString(), otherEntry.getPath().makeRelative().toString()}));
}
}
}
}
}
}
-
+
// prevent nesting output location inside entry unless enclosing is a source entry which explicitly exclude the output location
char[][] inclusionPatterns = ((ClasspathEntry)entry).fullInclusionPatternChars();
char[][] exclusionPatterns = ((ClasspathEntry)entry).fullExclusionPatternChars();
@@ -1274,7 +1481,7 @@
if (entryPath.equals(currentOutput)) continue;
if (entryPath.isPrefixOf(currentOutput)) {
if (kind != IClasspathEntry.CPE_SOURCE || !Util.isExcluded(currentOutput, inclusionPatterns, exclusionPatterns, true)) {
- return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_cannotNestOutputInEntry, new String[] {currentOutput.makeRelative().toString(), entryPath.makeRelative().toString()}));
+ return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_cannotNestOutputInEntry, new String[] {currentOutput.makeRelative().toString(), entryPath.makeRelative().toString()}));
}
}
}
@@ -1284,9 +1491,9 @@
if (allowNestingInOutputLocations[j]) continue;
IPath currentOutput = outputLocations[j];
if (currentOutput.isPrefixOf(entryPath)) {
- return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_cannotNestEntryInOutput, new String[] {entryPath.makeRelative().toString(), currentOutput.makeRelative().toString()}));
+ return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_cannotNestEntryInOutput, new String[] {entryPath.makeRelative().toString(), currentOutput.makeRelative().toString()}));
}
- }
+ }
}
// ensure that no specific output is coincidating with another source folder (only allowed if matching current source folder)
// 36465 - for 2.0 backward compatibility, only check specific output locations (the default can still coincidate)
@@ -1302,7 +1509,7 @@
// Build some common strings for status message
boolean isProjectRelative = projectName.equals(entryPath.segment(0));
String entryPathMsg = isProjectRelative ? entryPath.removeFirstSegments(1).toString() : entryPath.makeRelative().toString();
-
+
if (kind == IClasspathEntry.CPE_SOURCE) {
IPath output = entry.getOutputLocation();
if (output == null) continue; // 36465 - for 2.0 backward compatibility, only check specific output locations (the default can still coincidate)
@@ -1314,29 +1521,29 @@
// Build some common strings for status message
boolean opStartsWithProject = projectName.equals(otherEntry.getPath().segment(0));
String otherPathMsg = opStartsWithProject ? otherEntry.getPath().removeFirstSegments(1).toString() : otherEntry.getPath().makeRelative().toString();
-
+
switch (otherEntry.getEntryKind()) {
case IClasspathEntry.CPE_SOURCE :
if (otherEntry.getPath().equals(output)) {
- return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_cannotUseDistinctSourceFolderAsOutput, new String[] {entryPathMsg, otherPathMsg, projectName}));
+ return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_cannotUseDistinctSourceFolderAsOutput, new String[] {entryPathMsg, otherPathMsg, projectName}));
}
break;
case IClasspathEntry.CPE_LIBRARY :
if (otherEntry.getPath().equals(output)) {
- return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_cannotUseLibraryAsOutput, new String[] {entryPathMsg, otherPathMsg, projectName}));
+ return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_cannotUseLibraryAsOutput, new String[] {entryPathMsg, otherPathMsg, projectName}));
}
}
}
- }
+ }
}
- return JavaModelStatus.VERIFIED_OK;
+ return JavaModelStatus.VERIFIED_OK;
}
-
+
/**
- * Returns a Java model status describing the problem related to this classpath entry if any,
+ * Returns a Java model status describing the problem related to this classpath entry if any,
* a status object with code <code>IStatus.OK</code> if the entry is fine (that is, if the
* given classpath entry denotes a valid element to be referenced onto a classpath).
- *
+ *
* @param project the given java project
* @param entry the given classpath entry
* @param checkSourceAttachment a flag to determine if source attachement should be checked
@@ -1344,20 +1551,20 @@
* @return a java model status describing the problem related to this classpath entry if any, a status object with code <code>IStatus.OK</code> if the entry is fine
*/
public static IJavaModelStatus validateClasspathEntry(IJavaProject project, IClasspathEntry entry, boolean checkSourceAttachment, boolean recurseInContainers){
-
- IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
+
+ IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
IPath path = entry.getPath();
-
+
// Build some common strings for status message
String projectName = project.getElementName();
boolean pathStartsWithProject = projectName.equals(path.segment(0));
String entryPathMsg = pathStartsWithProject ? path.removeFirstSegments(1).makeRelative().toString() : path.toString();
-
+
switch(entry.getEntryKind()){
-
+
// container entry check
case IClasspathEntry.CPE_CONTAINER :
- if (path != null && path.segmentCount() >= 1){
+ if (path.segmentCount() >= 1){
try {
IClasspathContainer container = JavaModelManager.getJavaModelManager().getClasspathContainer(path, project);
// container retrieval is performing validation check on container entry kinds.
@@ -1372,7 +1579,7 @@
for (int i=0; i<length; i++) {
String attName = extraAttributes[i].getName();
if (!set.add(attName)) {
- return new JavaModelStatus(IJavaModelStatusConstants.NAME_COLLISION, Messages.bind(Messages.classpath_duplicateEntryExtraAttribute, new String[] {attName, entryPathMsg, projectName}));
+ return new JavaModelStatus(IJavaModelStatusConstants.NAME_COLLISION, Messages.bind(Messages.classpath_duplicateEntryExtraAttribute, new String[] {attName, entryPathMsg, projectName}));
}
}
}
@@ -1397,23 +1604,23 @@
if (!containerEntryStatus.isOK()){
return containerEntryStatus;
}
- }
+ }
}
}
} catch(JavaModelException e){
return new JavaModelStatus(e);
}
} else {
- return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_illegalContainerPath, new String[] {entryPathMsg, projectName}));
+ return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_illegalContainerPath, new String[] {entryPathMsg, projectName}));
}
break;
-
+
// variable entry check
case IClasspathEntry.CPE_VARIABLE :
- if (path != null && path.segmentCount() >= 1){
+ if (path.segmentCount() >= 1){
try {
entry = JavaCore.getResolvedClasspathEntry(entry);
- } catch (Assert.AssertionFailedException e) {
+ } catch (AssertionFailedException e) {
// Catch the assertion failure and throw java model exception instead
// see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=55992
return new JavaModelStatus(IJavaModelStatusConstants.INVALID_PATH, e.getMessage());
@@ -1421,21 +1628,32 @@
if (entry == null){
return new JavaModelStatus(IJavaModelStatusConstants.CP_VARIABLE_PATH_UNBOUND, project, path);
}
- return validateClasspathEntry(project, entry, checkSourceAttachment, recurseInContainers);
+
+ // get validation status
+ IJavaModelStatus status = validateClasspathEntry(project, entry, checkSourceAttachment, recurseInContainers);
+ if (!status.isOK()) return status;
+
+ // return deprecation status if any
+ String variableName = path.segment(0);
+ String deprecatedMessage = JavaCore.getClasspathVariableDeprecationMessage(variableName);
+ if (deprecatedMessage != null) {
+ return new JavaModelStatus(IStatus.WARNING, IJavaModelStatusConstants.DEPRECATED_VARIABLE, project, path, deprecatedMessage);
+ }
+ return status;
} else {
- return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_illegalVariablePath, new String[] {entryPathMsg, projectName}));
+ return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_illegalVariablePath, new String[] {entryPathMsg, projectName}));
}
-
+
// library entry check
case IClasspathEntry.CPE_LIBRARY :
- if (path != null && path.isAbsolute() && !path.isEmpty()) {
+ if (path.isAbsolute() && !path.isEmpty()) {
IPath sourceAttachment = entry.getSourceAttachmentPath();
Object target = JavaModel.getTarget(workspaceRoot, path, true);
- if (target != null && project.getOption(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL, true) != JavaCore.IGNORE) {
+ if (target != null && !JavaCore.IGNORE.equals(project.getOption(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL, true))) {
long projectTargetJDK = CompilerOptions.versionToJdkLevel(project.getOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, true));
long libraryJDK = Util.getJdkLevel(target);
if (libraryJDK != 0 && libraryJDK > projectTargetJDK) {
- return new JavaModelStatus(IJavaModelStatusConstants.INCOMPATIBLE_JDK_LEVEL, project, path, CompilerOptions.versionFromJdkLevel(libraryJDK));
+ return new JavaModelStatus(IJavaModelStatusConstants.INCOMPATIBLE_JDK_LEVEL, project, path, CompilerOptions.versionFromJdkLevel(libraryJDK));
}
}
if (target instanceof IResource){
@@ -1443,76 +1661,76 @@
switch(resolvedResource.getType()){
case IResource.FILE :
if (org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(resolvedResource.getName())) {
- if (checkSourceAttachment
+ if (checkSourceAttachment
&& sourceAttachment != null
&& !sourceAttachment.isEmpty()
&& JavaModel.getTarget(workspaceRoot, sourceAttachment, true) == null){
- return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundSourceAttachment, new String [] {sourceAttachment.toString(), path.toString(), projectName}));
+ return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundSourceAttachment, new String [] {sourceAttachment.toString(), path.toString(), projectName}));
}
} else {
- return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_illegalLibraryArchive, new String[] {entryPathMsg, projectName}));
+ return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_illegalLibraryArchive, new String[] {entryPathMsg, projectName}));
}
break;
case IResource.FOLDER : // internal binary folder
- if (checkSourceAttachment
- && sourceAttachment != null
+ if (checkSourceAttachment
+ && sourceAttachment != null
&& !sourceAttachment.isEmpty()
&& JavaModel.getTarget(workspaceRoot, sourceAttachment, true) == null){
- return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundSourceAttachment, new String [] {sourceAttachment.toString(), path.toString(), projectName}));
+ return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundSourceAttachment, new String [] {sourceAttachment.toString(), path.toString(), projectName}));
}
}
} else if (target instanceof File){
File file = JavaModel.getFile(target);
if (file == null) {
- return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_illegalExternalFolder, new String[] {path.toOSString(), projectName}));
+ return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_illegalExternalFolder, new String[] {path.toOSString(), projectName}));
} else if (!org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(file.getName())) {
- return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_illegalLibraryArchive, (new String[] {path.toOSString(), projectName})));
- } else if (checkSourceAttachment
- && sourceAttachment != null
+ return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_illegalLibraryArchive, (new String[] {path.toOSString(), projectName})));
+ } else if (checkSourceAttachment
+ && sourceAttachment != null
&& !sourceAttachment.isEmpty()
&& JavaModel.getTarget(workspaceRoot, sourceAttachment, true) == null){
- return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundSourceAttachment, new String [] {sourceAttachment.toString(), path.toOSString(), projectName}));
+ return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundSourceAttachment, new String [] {sourceAttachment.toString(), path.toOSString(), projectName}));
}
} else {
boolean isExternal = path.getDevice() != null || !workspaceRoot.getProject(path.segment(0)).exists();
if (isExternal) {
- return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundLibrary, new String[] {path.toOSString(), projectName}));
+ return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundLibrary, new String[] {path.toOSString(), projectName}));
} else {
- return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundLibrary, new String[] {entryPathMsg, projectName}));
+ return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundLibrary, new String[] {entryPathMsg, projectName}));
}
}
} else {
- return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_illegalLibraryPath, new String[] {entryPathMsg, projectName}));
+ return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_illegalLibraryPath, new String[] {entryPathMsg, projectName}));
}
break;
-
+
// project entry check
case IClasspathEntry.CPE_PROJECT :
- if (path != null && path.isAbsolute() && !path.isEmpty()) {
+ if (path.isAbsolute() && path.segmentCount() == 1) {
IProject prereqProjectRsc = workspaceRoot.getProject(path.segment(0));
IJavaProject prereqProject = JavaCore.create(prereqProjectRsc);
try {
if (!prereqProjectRsc.exists() || !prereqProjectRsc.hasNature(JavaCore.NATURE_ID)){
- return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundProject, new String[] {path.segment(0), projectName}));
+ return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundProject, new String[] {path.segment(0), projectName}));
}
if (!prereqProjectRsc.isOpen()){
- return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_closedProject, new String[] {path.segment(0)}));
+ return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_closedProject, new String[] {path.segment(0)}));
}
- if (project.getOption(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL, true) != JavaCore.IGNORE) {
+ if (!JavaCore.IGNORE.equals(project.getOption(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL, true))) {
long projectTargetJDK = CompilerOptions.versionToJdkLevel(project.getOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, true));
long prereqProjectTargetJDK = CompilerOptions.versionToJdkLevel(prereqProject.getOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, true));
if (prereqProjectTargetJDK > projectTargetJDK) {
- return new JavaModelStatus(IJavaModelStatusConstants.INCOMPATIBLE_JDK_LEVEL, project, path, CompilerOptions.versionFromJdkLevel(prereqProjectTargetJDK));
+ return new JavaModelStatus(IJavaModelStatusConstants.INCOMPATIBLE_JDK_LEVEL, project, path, CompilerOptions.versionFromJdkLevel(prereqProjectTargetJDK));
}
}
} catch (CoreException e){
- return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundProject, new String[] {path.segment(0), projectName}));
+ return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundProject, new String[] {path.segment(0), projectName}));
}
} else {
- return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_illegalProjectPath, new String[] {path.segment(0), projectName}));
+ return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_illegalProjectPath, new String[] {path.toString(), projectName}));
}
break;
-
+
// project source folder
case IClasspathEntry.CPE_SOURCE :
if (((entry.getInclusionPatterns() != null && entry.getInclusionPatterns().length > 0)
@@ -1523,13 +1741,13 @@
if (entry.getOutputLocation() != null && JavaCore.DISABLED.equals(project.getOption(JavaCore.CORE_ENABLE_CLASSPATH_MULTIPLE_OUTPUT_LOCATIONS, true))) {
return new JavaModelStatus(IJavaModelStatusConstants.DISABLED_CP_MULTIPLE_OUTPUT_LOCATIONS, project, path);
}
- if (path != null && path.isAbsolute() && !path.isEmpty()) {
+ if (path.isAbsolute() && !path.isEmpty()) {
IPath projectPath= project.getProject().getFullPath();
if (!projectPath.isPrefixOf(path) || JavaModel.getTarget(workspaceRoot, path, true) == null){
- return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundSourceFolder, new String[] {entryPathMsg, projectName}));
+ return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundSourceFolder, new String[] {entryPathMsg, projectName}));
}
} else {
- return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_illegalSourceFolderPath, new String[] {entryPathMsg, projectName}));
+ return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_illegalSourceFolderPath, new String[] {entryPathMsg, projectName}));
}
break;
}
@@ -1542,11 +1760,11 @@
for (int i=0; i<length; i++) {
String attName = extraAttributes[i].getName();
if (!set.add(attName)) {
- return new JavaModelStatus(IJavaModelStatusConstants.NAME_COLLISION, Messages.bind(Messages.classpath_duplicateEntryExtraAttribute, new String[] {attName, entryPathMsg, projectName}));
+ return new JavaModelStatus(IJavaModelStatusConstants.NAME_COLLISION, Messages.bind(Messages.classpath_duplicateEntryExtraAttribute, new String[] {attName, entryPathMsg, projectName}));
}
}
}
- return JavaModelStatus.VERIFIED_OK;
+ return JavaModelStatus.VERIFIED_OK;
}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathValidation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathValidation.java
new file mode 100755
index 0000000..03ce9e5
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathValidation.java
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaModelStatus;
+import org.eclipse.jdt.core.IJavaModelStatusConstants;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.internal.core.builder.JavaBuilder;
+
+/*
+ * Validates the raw classpath format and the resolved classpath of this project,
+ * updating markers if necessary.
+ */
+public class ClasspathValidation {
+
+ private JavaProject project;
+
+ public ClasspathValidation(JavaProject project) {
+ this.project = project;
+ }
+
+ public void validate() {
+ JavaModelManager.PerProjectInfo perProjectInfo;
+ try {
+ perProjectInfo = this.project.getPerProjectInfo();
+ } catch (JavaModelException e) {
+ // project doesn't exist
+ IProject resource = this.project.getProject();
+ if (resource.isAccessible()) {
+ this.project.flushClasspathProblemMarkers(true/*flush cycle markers*/, true/*flush classpath format markers*/);
+
+ // remove problems and tasks created by the builder
+ JavaBuilder.removeProblemsAndTasksFor(resource);
+ }
+ return;
+ }
+
+ // use synchronized block to ensure consistency
+ IClasspathEntry[] rawClasspath;
+ IPath outputLocation;
+ IJavaModelStatus status;
+ synchronized (perProjectInfo) {
+ rawClasspath = perProjectInfo.rawClasspath;
+ outputLocation = perProjectInfo.outputLocation;
+ status = perProjectInfo.rawClasspathStatus; // status has been set during POST_CHANGE
+ }
+
+ // update classpath format problems
+ this.project.flushClasspathProblemMarkers(false/*cycle*/, true/*format*/);
+ if (!status.isOK())
+ this.project.createClasspathProblemMarker(status);
+
+ // update resolved classpath problems
+ this.project.flushClasspathProblemMarkers(false/*cycle*/, false/*format*/);
+
+ if (rawClasspath != JavaProject.INVALID_CLASSPATH && outputLocation != null) {
+ for (int i = 0; i < rawClasspath.length; i++) {
+ status = ClasspathEntry.validateClasspathEntry(this.project, rawClasspath[i], false/*src attach*/, true /*recurse in container*/);
+ if (!status.isOK()) {
+ if (status.getCode() == IJavaModelStatusConstants.INVALID_CLASSPATH && ((ClasspathEntry) rawClasspath[i]).isOptional())
+ continue; // ignore this entry
+ this.project.createClasspathProblemMarker(status);
+ }
+ }
+ status = ClasspathEntry.validateClasspath(this.project, rawClasspath, outputLocation);
+ if (!status.isOK())
+ this.project.createClasspathProblemMarker(status);
+ }
+ }
+
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CommitWorkingCopyOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CommitWorkingCopyOperation.java
index 19b321b..84a7ea5 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CommitWorkingCopyOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CommitWorkingCopyOperation.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -18,12 +18,13 @@
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
-//import org.eclipse.jdt.core.*;
import org.eclipse.jdt.core.IBuffer;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaModelStatus;
import org.eclipse.jdt.core.IJavaModelStatusConstants;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.core.util.Messages;
import org.eclipse.jdt.internal.core.util.Util;
@@ -69,14 +70,22 @@
try {
beginTask(Messages.workingCopy_commit, 2);
CompilationUnit workingCopy = getCompilationUnit();
- IFile resource = (IFile)workingCopy.getResource();
+
+ if (ExternalJavaProject.EXTERNAL_PROJECT_NAME.equals(workingCopy.getJavaProject().getElementName())) {
+ // case of a working copy without a resource
+ workingCopy.getBuffer().save(this.progressMonitor, this.force);
+ return;
+ }
+
ICompilationUnit primary = workingCopy.getPrimary();
boolean isPrimary = workingCopy.isPrimary();
JavaElementDeltaBuilder deltaBuilder = null;
PackageFragmentRoot root = (PackageFragmentRoot)workingCopy.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
boolean isIncluded = !Util.isExcluded(workingCopy);
- if (isPrimary || (root.validateOnClasspath().isOK() && isIncluded && resource.isAccessible() && Util.isValidCompilationUnitName(workingCopy.getElementName()))) {
+ IFile resource = (IFile)workingCopy.getResource();
+ IJavaProject project = root.getJavaProject();
+ if (isPrimary || (root.validateOnClasspath().isOK() && isIncluded && resource.isAccessible() && Util.isValidCompilationUnitName(workingCopy.getElementName(), project.getOption(JavaCore.COMPILER_SOURCE, true), project.getOption(JavaCore.COMPILER_COMPLIANCE, true)))) {
// force opening so that the delta builder can get the old info
if (!isPrimary && !primary.isOpen()) {
@@ -178,6 +187,7 @@
}
protected ISchedulingRule getSchedulingRule() {
IResource resource = getElementToProcess().getResource();
+ if (resource == null) return null;
IWorkspace workspace = resource.getWorkspace();
if (resource.exists()) {
return workspace.getRuleFactory().modifyRule(resource);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnit.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnit.java
index 1345700..636ce73 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnit.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnit.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -7,6 +7,8 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Alex Smirnoff (alexsmr@sympatico.ca) - part of the changes to support Java-like extension
+ * (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=71460)
*******************************************************************************/
package org.eclipse.jdt.internal.core;
@@ -16,9 +18,7 @@
import org.eclipse.core.runtime.*;
import org.eclipse.jdt.core.*;
import org.eclipse.jdt.core.compiler.*;
-import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.core.dom.AST;
-import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.IProblemFactory;
import org.eclipse.jdt.internal.compiler.SourceElementParser;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
@@ -40,6 +40,8 @@
*/
/*package*/ static final int JLS2_INTERNAL = AST.JLS2;
+ private static final IImportDeclaration[] NO_IMPORTS = new IImportDeclaration[0];
+
protected String name;
public WorkingCopyOwner owner;
@@ -47,28 +49,11 @@
* Constructs a handle to a compilation unit with the given name in the
* specified package for the specified owner
*/
-protected CompilationUnit(PackageFragment parent, String name, WorkingCopyOwner owner) {
+public CompilationUnit(PackageFragment parent, String name, WorkingCopyOwner owner) {
super(parent);
this.name = name;
this.owner = owner;
}
-/**
- * Accepts the given visitor onto the parsed tree of this compilation unit, after
- * having runned the name resolution.
- * The visitor's corresponding <code>visit</code> method is called with the
- * corresponding parse tree. If the visitor returns <code>true</code>, this method
- * visits this parse node's members.
- *
- * @param visitor the visitor
- * @exception JavaModelException if this method fails. Reasons include:
- * <ul>
- * <li> This element does not exist.</li>
- * <li> The visitor failed with this exception.</li>
- * </ul>
- */
-public void accept(ASTVisitor visitor) throws JavaModelException {
- CompilationUnitVisitor.visit(this, visitor);
-}
/*
* @see ICompilationUnit#becomeWorkingCopy(IProblemRequestor, IProgressMonitor)
*/
@@ -83,6 +68,13 @@
operation.runOperation(monitor);
}
}
+/*
+ * @see ICompilationUnit#becomeWorkingCopy(IProgressMonitor)
+ */
+public void becomeWorkingCopy(IProgressMonitor monitor) throws JavaModelException {
+ IProblemRequestor requestor = this.owner == null ? null : this.owner.getProblemRequestor(this);
+ becomeWorkingCopy(requestor, monitor);
+}
protected boolean buildStructure(OpenableElementInfo info, final IProgressMonitor pm, Map newElements, IResource underlyingResource) throws JavaModelException {
// check if this compilation unit can be opened
@@ -103,20 +95,43 @@
if (buffer == null) {
buffer = openBuffer(pm, unitInfo); // open buffer independently from the info, since we are building the info
}
- final char[] contents = buffer == null ? null : buffer.getCharacters();
+ final char[] contents;
+ if (buffer == null) {
+ contents = CharOperation.NO_CHAR ;
+ } else {
+ char[] characters = buffer.getCharacters();
+ contents = characters == null ? CharOperation.NO_CHAR : characters;
+ }
// generate structure and compute syntax problems if needed
CompilationUnitStructureRequestor requestor = new CompilationUnitStructureRequestor(this, unitInfo, newElements);
JavaModelManager.PerWorkingCopyInfo perWorkingCopyInfo = getPerWorkingCopyInfo();
IJavaProject project = getJavaProject();
- boolean computeProblems = JavaProject.hasJavaNature(project.getProject()) && perWorkingCopyInfo != null && perWorkingCopyInfo.isActive();
+
+ boolean createAST;
+ boolean resolveBindings;
+ int reconcileFlags;
+ HashMap problems;
+ if (info instanceof ASTHolderCUInfo) {
+ ASTHolderCUInfo astHolder = (ASTHolderCUInfo) info;
+ createAST = astHolder.astLevel != NO_AST;
+ resolveBindings = astHolder.resolveBindings;
+ reconcileFlags = astHolder.reconcileFlags;
+ problems = astHolder.problems;
+ } else {
+ createAST = false;
+ resolveBindings = false;
+ reconcileFlags = 0;
+ problems = null;
+ }
+
+ boolean computeProblems = perWorkingCopyInfo != null && perWorkingCopyInfo.isActive() && project != null && JavaProject.hasJavaNature(project.getProject());
IProblemFactory problemFactory = new DefaultProblemFactory();
- Map options = project.getOptions(true);
+ Map options = project == null ? JavaCore.getOptions() : project.getOptions(true);
if (!computeProblems) {
// disable task tags checking to speed up parsing
options.put(JavaCore.COMPILER_TASK_TAGS, ""); //$NON-NLS-1$
}
- boolean createAST = info instanceof ASTHolderCUInfo;
SourceElementParser parser = new SourceElementParser(
requestor,
problemFactory,
@@ -124,10 +139,14 @@
true/*report local declarations*/,
!createAST /*optimize string literals only if not creating a DOM AST*/);
parser.reportOnlyOneSyntaxError = !computeProblems;
- if (!computeProblems && !createAST) // disable javadoc parsing if not computing problems and not creating ast
+ parser.setMethodsFullRecovery(true);
+ parser.setStatementsRecovery((reconcileFlags & ICompilationUnit.ENABLE_STATEMENTS_RECOVERY) != 0);
+
+ if (!computeProblems && !resolveBindings && !createAST) // disable javadoc parsing if not computing problems, not resolving and not creating ast
parser.javadocParser.checkDocComment = false;
requestor.parser = parser;
- CompilationUnitDeclaration unit = parser.parseCompilationUnit(new org.eclipse.jdt.internal.compiler.env.ICompilationUnit() {
+ CompilationUnitDeclaration unit = parser.parseCompilationUnit(
+ new org.eclipse.jdt.internal.compiler.env.ICompilationUnit() {
public char[] getContents() {
return contents;
}
@@ -140,26 +159,46 @@
public char[] getFileName() {
return CompilationUnit.this.getFileName();
}
- }, true /*full parse to find local elements*/);
+ },
+ true /*full parse to find local elements*/);
// update timestamp (might be IResource.NULL_STAMP if original does not exist)
if (underlyingResource == null) {
underlyingResource = getResource();
}
- unitInfo.timestamp = ((IFile)underlyingResource).getModificationStamp();
+ // underlying resource is null in the case of a working copy on a class file in a jar
+ if (underlyingResource != null)
+ unitInfo.timestamp = ((IFile)underlyingResource).getModificationStamp();
// compute other problems if needed
CompilationUnitDeclaration compilationUnitDeclaration = null;
try {
- if (computeProblems){
- perWorkingCopyInfo.beginReporting();
- compilationUnitDeclaration = CompilationUnitProblemFinder.process(unit, this, contents, parser, this.owner, perWorkingCopyInfo, !createAST/*reset env if not creating AST*/, pm);
- perWorkingCopyInfo.endReporting();
+ if (computeProblems) {
+ if (problems == null) {
+ // report problems to the problem requestor
+ problems = new HashMap();
+ compilationUnitDeclaration = CompilationUnitProblemFinder.process(unit, this, contents, parser, this.owner, problems, createAST, reconcileFlags, pm);
+ try {
+ perWorkingCopyInfo.beginReporting();
+ for (Iterator iteraror = problems.values().iterator(); iteraror.hasNext();) {
+ CategorizedProblem[] categorizedProblems = (CategorizedProblem[]) iteraror.next();
+ if (categorizedProblems == null) continue;
+ for (int i = 0, length = categorizedProblems.length; i < length; i++) {
+ perWorkingCopyInfo.acceptProblem(categorizedProblems[i]);
+ }
+ }
+ } finally {
+ perWorkingCopyInfo.endReporting();
+ }
+ } else {
+ // collect problems
+ compilationUnitDeclaration = CompilationUnitProblemFinder.process(unit, this, contents, parser, this.owner, problems, createAST, reconcileFlags, pm);
+ }
}
if (createAST) {
int astLevel = ((ASTHolderCUInfo) info).astLevel;
- org.eclipse.jdt.core.dom.CompilationUnit cu = AST.convertCompilationUnit(astLevel, unit, contents, options, computeProblems, this, pm);
+ org.eclipse.jdt.core.dom.CompilationUnit cu = AST.convertCompilationUnit(astLevel, unit, contents, options, computeProblems, this, reconcileFlags, pm);
((ASTHolderCUInfo) info).ast = cu;
}
} finally {
@@ -235,20 +274,7 @@
requestor.acceptClass(packageName, className, completionName, modifiers, completionStart, completionEnd);
}
public void acceptError(IProblem error) {
- if (true) return; // was disabled in 1.0
-
- try {
- IMarker marker = ResourcesPlugin.getWorkspace().getRoot().createMarker(IJavaModelMarker.TRANSIENT_PROBLEM);
- marker.setAttribute(IJavaModelMarker.ID, error.getID());
- marker.setAttribute(IMarker.CHAR_START, error.getSourceStart());
- marker.setAttribute(IMarker.CHAR_END, error.getSourceEnd() + 1);
- marker.setAttribute(IMarker.LINE_NUMBER, error.getSourceLineNumber());
- marker.setAttribute(IMarker.MESSAGE, error.getMessage());
- marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
- requestor.acceptError(marker);
- } catch(CoreException e){
- // ignore
- }
+ // was disabled in 1.0
}
public void acceptField(char[] declaringTypePackageName, char[] declaringTypeName, char[] fieldName, char[] typePackageName, char[] typeName, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) {
requestor.acceptField(declaringTypePackageName, declaringTypeName, fieldName, typePackageName, typeName, completionName, modifiers, completionStart, completionEnd);
@@ -360,8 +386,7 @@
* @since 3.0
*/
public IImportDeclaration createImport(String importName, IJavaElement sibling, int flags, IProgressMonitor monitor) throws JavaModelException {
- // TODO (jerome) - consult flags to create static imports
- CreateImportOperation op = new CreateImportOperation(importName, this);
+ CreateImportOperation op = new CreateImportOperation(importName, this, flags);
if (sibling != null) {
op.createBefore(sibling);
}
@@ -506,8 +531,8 @@
* @see ICompilationUnit#findPrimaryType()
*/
public IType findPrimaryType() {
- String typeName = Signature.getQualifier(this.getElementName());
- IType primaryType= this.getType(typeName);
+ String typeName = Util.getNameWithoutJavaLikeExtension(getElementName());
+ IType primaryType= getType(typeName);
if (primaryType.exists()) {
return primaryType;
}
@@ -577,12 +602,20 @@
* @see org.eclipse.jdt.internal.compiler.env.ICompilationUnit#getContents()
*/
public char[] getContents() {
- try {
- IBuffer buffer = this.getBuffer();
- return buffer == null ? CharOperation.NO_CHAR : buffer.getCharacters();
- } catch (JavaModelException e) {
- return CharOperation.NO_CHAR;
+ IBuffer buffer = getBufferManager().getBuffer(this);
+ if (buffer == null) {
+ // no need to force opening of CU to get the content
+ // also this cannot be a working copy, as its buffer is never closed while the working copy is alive
+ try {
+ return Util.getResourceContentsAsCharArray((IFile) getResource());
+ } catch (JavaModelException e) {
+ return CharOperation.NO_CHAR;
+ }
}
+ char[] contents = buffer.getCharacters();
+ if (contents == null) // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=129814
+ return CharOperation.NO_CHAR;
+ return contents;
}
/**
* A compilation unit has a corresponding resource unless it is contained
@@ -591,8 +624,8 @@
* @see IJavaElement#getCorrespondingResource()
*/
public IResource getCorrespondingResource() throws JavaModelException {
- IPackageFragmentRoot root= (IPackageFragmentRoot)getParent().getParent();
- if (root.isArchive()) {
+ PackageFragmentRoot root = getPackageFragmentRoot();
+ if (root == null || root.isArchive()) {
return null;
} else {
return getUnderlyingResource();
@@ -673,17 +706,31 @@
*/
public IImportDeclaration[] getImports() throws JavaModelException {
IImportContainer container= getImportContainer();
- if (container.exists()) {
- IJavaElement[] elements= container.getChildren();
- IImportDeclaration[] imprts= new IImportDeclaration[elements.length];
- System.arraycopy(elements, 0, imprts, 0, elements.length);
- return imprts;
- } else if (!exists()) {
- throw newNotPresentException();
- } else {
- return new IImportDeclaration[0];
+ JavaModelManager manager = JavaModelManager.getJavaModelManager();
+ Object info = manager.getInfo(container);
+ if (info == null) {
+ if (manager.getInfo(this) != null)
+ // CU was opened, but no import container, then no imports
+ return NO_IMPORTS;
+ else {
+ open(null); // force opening of CU
+ info = manager.getInfo(container);
+ if (info == null)
+ // after opening, if no import container, then no imports
+ return NO_IMPORTS;
+ }
}
-
+ IJavaElement[] elements = ((JavaElementInfo) info).children;
+ int length = elements.length;
+ IImportDeclaration[] imports = new IImportDeclaration[length];
+ System.arraycopy(elements, 0, imports, 0, length);
+ return imports;
+}
+/**
+ * @see IMember#getTypeRoot()
+ */
+public ITypeRoot getTypeRoot() {
+ return this;
}
/**
* @see org.eclipse.jdt.internal.compiler.env.ICompilationUnit#getMainTypeName()
@@ -741,6 +788,7 @@
*/
public char[][] getPackageName() {
PackageFragment packageFragment = (PackageFragment) getParent();
+ if (packageFragment == null) return CharOperation.NO_CHAR_CHAR;
return Util.toCharArrays(packageFragment.names);
}
@@ -748,11 +796,12 @@
* @see IJavaElement#getPath()
*/
public IPath getPath() {
- PackageFragmentRoot root = this.getPackageFragmentRoot();
+ PackageFragmentRoot root = getPackageFragmentRoot();
+ if (root == null) return new Path(getElementName()); // working copy not in workspace
if (root.isArchive()) {
return root.getPath();
} else {
- return this.getParent().getPath().append(this.getElementName());
+ return getParent().getPath().append(getElementName());
}
}
/*
@@ -779,11 +828,12 @@
* @see IJavaElement#getResource()
*/
public IResource getResource() {
- PackageFragmentRoot root = this.getPackageFragmentRoot();
+ PackageFragmentRoot root = getPackageFragmentRoot();
+ if (root == null) return null; // working copy not in workspace
if (root.isArchive()) {
return root.getResource();
} else {
- return ((IContainer)this.getParent().getResource()).getFile(new Path(this.getElementName()));
+ return ((IContainer) getParent().getResource()).getFile(new Path(getElementName()));
}
}
/**
@@ -847,6 +897,12 @@
return getWorkingCopy(new WorkingCopyOwner() {/*non shared working copy*/}, null/*no problem requestor*/, monitor);
}
/**
+ * @see ITypeRoot#getWorkingCopy(WorkingCopyOwner, IProgressMonitor)
+ */
+public ICompilationUnit getWorkingCopy(WorkingCopyOwner workingCopyOwner, IProgressMonitor monitor) throws JavaModelException {
+ return getWorkingCopy(workingCopyOwner, null, monitor);
+}
+/**
* @see IWorkingCopy#getWorkingCopy(IProgressMonitor, IBufferFactory, IProblemRequestor)
* @deprecated
*/
@@ -855,6 +911,7 @@
}
/**
* @see ICompilationUnit#getWorkingCopy(WorkingCopyOwner, IProblemRequestor, IProgressMonitor)
+ * @deprecated
*/
public ICompilationUnit getWorkingCopy(WorkingCopyOwner workingCopyOwner, IProblemRequestor problemRequestor, IProgressMonitor monitor) throws JavaModelException {
if (!isPrimary()) return this;
@@ -887,7 +944,9 @@
// timestamp
Object info = JavaModelManager.getJavaModelManager().getInfo(this);
if (info == null) return false;
- return ((CompilationUnitElementInfo)info).timestamp != getResource().getModificationStamp();
+ IResource resource = getResource();
+ if (resource == null) return false;
+ return ((CompilationUnitElementInfo)info).timestamp != resource.getModificationStamp();
}
/**
* @see IWorkingCopy#isBasedOn(IResource)
@@ -902,7 +961,7 @@
* @see IOpenable#isConsistent()
*/
public boolean isConsistent() {
- return JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().get(this) == null;
+ return !JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().contains(this);
}
public boolean isPrimary() {
return this.owner == DefaultWorkingCopyOwner.PRIMARY;
@@ -915,6 +974,7 @@
}
protected IStatus validateCompilationUnit(IResource resource) {
IPackageFragmentRoot root = getPackageFragmentRoot();
+ // root never null as validation is not done for working copies
try {
if (root.getKind() != IPackageFragmentRoot.K_SOURCE)
return new JavaModelStatus(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, root);
@@ -929,7 +989,8 @@
if (!resource.isAccessible())
return new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this);
}
- return JavaConventions.validateCompilationUnitName(getElementName());
+ IJavaProject project = getJavaProject();
+ return JavaConventions.validateCompilationUnitName(getElementName(),project.getOption(JavaCore.COMPILER_SOURCE, true), project.getOption(JavaCore.COMPILER_COMPLIANCE, true));
}
/*
* @see ICompilationUnit#isWorkingCopy()
@@ -943,16 +1004,19 @@
* @see IOpenable#makeConsistent(IProgressMonitor)
*/
public void makeConsistent(IProgressMonitor monitor) throws JavaModelException {
- makeConsistent(false/*don't create AST*/, 0, monitor);
+ makeConsistent(NO_AST, false/*don't resolve bindings*/, 0 /* don't perform statements recovery */, null/*don't collect problems but report them*/, monitor);
}
-public org.eclipse.jdt.core.dom.CompilationUnit makeConsistent(boolean createAST, int astLevel, IProgressMonitor monitor) throws JavaModelException {
+public org.eclipse.jdt.core.dom.CompilationUnit makeConsistent(int astLevel, boolean resolveBindings, int reconcileFlags, HashMap problems, IProgressMonitor monitor) throws JavaModelException {
if (isConsistent()) return null;
// create a new info and make it the current info
// (this will remove the info and its children just before storing the new infos)
- if (createAST) {
+ if (astLevel != NO_AST || problems != null) {
ASTHolderCUInfo info = new ASTHolderCUInfo();
info.astLevel = astLevel;
+ info.resolveBindings = resolveBindings;
+ info.reconcileFlags = reconcileFlags;
+ info.problems = problems;
openWhenClosed(info, monitor);
org.eclipse.jdt.core.dom.CompilationUnit result = info.ast;
info.ast = null;
@@ -985,43 +1049,52 @@
protected IBuffer openBuffer(IProgressMonitor pm, Object info) throws JavaModelException {
// create buffer
+ BufferManager bufManager = getBufferManager();
boolean isWorkingCopy = isWorkingCopy();
IBuffer buffer =
isWorkingCopy
? this.owner.createBuffer(this)
- : BufferManager.getDefaultBufferManager().createBuffer(this);
+ : BufferManager.createBuffer(this);
if (buffer == null) return null;
- // set the buffer source
- if (buffer.getCharacters() == null) {
- if (isWorkingCopy) {
- ICompilationUnit original;
- if (!isPrimary()
- && (original = new CompilationUnit((PackageFragment)getParent(), getElementName(), DefaultWorkingCopyOwner.PRIMARY)).isOpen()) {
- buffer.setContents(original.getSource());
- } else {
- IFile file = (IFile)getResource();
- if (file == null || !file.exists()) {
- // initialize buffer with empty contents
- buffer.setContents(CharOperation.NO_CHAR);
+ // synchronize to ensure that 2 threads are not putting 2 different buffers at the same time
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=146331
+ synchronized(bufManager) {
+ IBuffer existingBuffer = bufManager.getBuffer(this);
+ if (existingBuffer != null)
+ return existingBuffer;
+
+ // set the buffer source
+ if (buffer.getCharacters() == null) {
+ if (isWorkingCopy) {
+ ICompilationUnit original;
+ if (!isPrimary()
+ && (original = new CompilationUnit((PackageFragment)getParent(), getElementName(), DefaultWorkingCopyOwner.PRIMARY)).isOpen()) {
+ buffer.setContents(original.getSource());
} else {
- buffer.setContents(Util.getResourceContentsAsCharArray(file));
+ IFile file = (IFile)getResource();
+ if (file == null || !file.exists()) {
+ // initialize buffer with empty contents
+ buffer.setContents(CharOperation.NO_CHAR);
+ } else {
+ buffer.setContents(Util.getResourceContentsAsCharArray(file));
+ }
}
+ } else {
+ IFile file = (IFile)this.getResource();
+ if (file == null || !file.exists()) throw newNotPresentException();
+ buffer.setContents(Util.getResourceContentsAsCharArray(file));
}
- } else {
- IFile file = (IFile)this.getResource();
- if (file == null || !file.exists()) throw newNotPresentException();
- buffer.setContents(Util.getResourceContentsAsCharArray(file));
}
- }
-
- // add buffer to buffer cache
- BufferManager bufManager = getBufferManager();
- bufManager.addBuffer(buffer);
-
- // listen to buffer changes
- buffer.addBufferChangedListener(this);
+ // add buffer to buffer cache
+ // note this may cause existing buffers to be removed from the buffer cache, but only primary compilation unit's buffer
+ // can be closed, thus no call to a client's IBuffer#close() can be done in this synchronized block.
+ bufManager.addBuffer(buffer);
+
+ // listen to buffer changes
+ buffer.addBufferChangedListener(this);
+ }
return buffer;
}
protected void openParent(Object childInfo, HashMap newElements, IProgressMonitor pm) throws JavaModelException {
@@ -1035,14 +1108,14 @@
* @deprecated
*/
public IMarker[] reconcile() throws JavaModelException {
- reconcile(NO_AST, false/*don't force problem detection*/, null/*use primary owner*/, null/*no progress monitor*/);
+ reconcile(NO_AST, false/*don't force problem detection*/, false, null/*use primary owner*/, null/*no progress monitor*/);
return null;
}
/**
* @see ICompilationUnit#reconcile(int, boolean, WorkingCopyOwner, IProgressMonitor)
*/
public void reconcile(boolean forceProblemDetection, IProgressMonitor monitor) throws JavaModelException {
- reconcile(NO_AST, forceProblemDetection, null/*use primary owner*/, monitor);
+ reconcile(NO_AST, forceProblemDetection? ICompilationUnit.FORCE_PROBLEM_DETECTION : 0, null/*use primary owner*/, monitor);
}
/**
@@ -1050,35 +1123,53 @@
* @since 3.0
*/
public org.eclipse.jdt.core.dom.CompilationUnit reconcile(
- int astLevel,
- boolean forceProblemDetection,
- WorkingCopyOwner workingCopyOwner,
- IProgressMonitor monitor)
- throws JavaModelException {
+ int astLevel,
+ boolean forceProblemDetection,
+ WorkingCopyOwner workingCopyOwner,
+ IProgressMonitor monitor) throws JavaModelException {
+ return reconcile(astLevel, forceProblemDetection? ICompilationUnit.FORCE_PROBLEM_DETECTION : 0, workingCopyOwner, monitor);
+}
+
+/**
+ * @see ICompilationUnit#reconcile(int, boolean, WorkingCopyOwner, IProgressMonitor)
+ * @since 3.0
+ */
+public org.eclipse.jdt.core.dom.CompilationUnit reconcile(
+ int astLevel,
+ boolean forceProblemDetection,
+ boolean enableStatementsRecovery,
+ WorkingCopyOwner workingCopyOwner,
+ IProgressMonitor monitor) throws JavaModelException {
+ int flags = 0;
+ if (forceProblemDetection) flags |= ICompilationUnit.FORCE_PROBLEM_DETECTION;
+ if (enableStatementsRecovery) flags |= ICompilationUnit.ENABLE_STATEMENTS_RECOVERY;
+ return reconcile(astLevel, flags, workingCopyOwner, monitor);
+}
+
+public org.eclipse.jdt.core.dom.CompilationUnit reconcile(
+ int astLevel,
+ int reconcileFlags,
+ WorkingCopyOwner workingCopyOwner,
+ IProgressMonitor monitor)
+ throws JavaModelException {
if (!isWorkingCopy()) return null; // Reconciling is not supported on non working copies
if (workingCopyOwner == null) workingCopyOwner = DefaultWorkingCopyOwner.PRIMARY;
- boolean createAST = false;
- switch(astLevel) {
- case JLS2_INTERNAL :
- case AST.JLS3 :
- // client asking for level 2 or level 3 ASTs; these are supported
- createAST = true;
- break;
- default:
- // client asking for no AST (0) or unknown ast level
- // either way, request denied
- createAST = false;
- }
PerformanceStats stats = null;
if(ReconcileWorkingCopyOperation.PERF) {
stats = PerformanceStats.getStats(JavaModelManager.RECONCILE_PERF, this);
stats.startRun(new String(this.getFileName()));
}
- ReconcileWorkingCopyOperation op = new ReconcileWorkingCopyOperation(this, createAST, astLevel, forceProblemDetection, workingCopyOwner);
- op.runOperation(monitor);
+ ReconcileWorkingCopyOperation op = new ReconcileWorkingCopyOperation(this, astLevel, reconcileFlags, workingCopyOwner);
+ JavaModelManager manager = JavaModelManager.getJavaModelManager();
+ try {
+ manager.cacheZipFiles(); // cache zip files for performance (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=134172)
+ op.runOperation(monitor);
+ } finally {
+ manager.flushZipFiles();
+ }
if(ReconcileWorkingCopyOperation.PERF) {
stats.endRun();
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitElementInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitElementInfo.java
index 3712b68..802118a 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitElementInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitElementInfo.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitProblemFinder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitProblemFinder.java
index ad0b386..e640de7 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitProblemFinder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitProblemFinder.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,23 +10,20 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core;
+import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
-import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.*;
-import org.eclipse.jdt.core.compiler.IProblem;
+import org.eclipse.jdt.core.compiler.CategorizedProblem;
import org.eclipse.jdt.internal.compiler.*;
-import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.Compiler;
-import org.eclipse.jdt.internal.compiler.ICompilerRequestor;
-import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy;
-import org.eclipse.jdt.internal.compiler.IProblemFactory;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
import org.eclipse.jdt.internal.compiler.env.ISourceType;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
import org.eclipse.jdt.internal.compiler.parser.Parser;
import org.eclipse.jdt.internal.compiler.parser.SourceTypeConverter;
@@ -59,7 +56,7 @@
* in UI when compiling interactively.
* @see org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies
*
- * @param settings The settings to use for the resolution.
+ * @param compilerOptions The compiler options to use for the resolution.
*
* @param requestor org.eclipse.jdt.internal.compiler.api.ICompilerRequestor
* Component which will receive and persist all compilation results and is intended
@@ -77,11 +74,16 @@
protected CompilationUnitProblemFinder(
INameEnvironment environment,
IErrorHandlingPolicy policy,
- Map settings,
+ CompilerOptions compilerOptions,
ICompilerRequestor requestor,
IProblemFactory problemFactory) {
- super(environment, policy, settings, requestor, problemFactory, true);
+ super(environment,
+ policy,
+ compilerOptions,
+ requestor,
+ problemFactory
+ );
}
/**
@@ -111,6 +113,15 @@
}
}
+ protected static CompilerOptions getCompilerOptions(Map settings, boolean creatingAST, boolean statementsRecovery) {
+ CompilerOptions compilerOptions = new CompilerOptions(settings);
+ compilerOptions.performMethodsFullRecovery = statementsRecovery;
+ compilerOptions.performStatementsRecovery = statementsRecovery;
+ compilerOptions.parseLiteralExpressionsAsConstants = !creatingAST; /*parse literal expressions as constants only if not creating a DOM AST*/
+ compilerOptions.storeAnnotations = creatingAST; /*store annotations in the bindings if creating a DOM AST*/
+ return compilerOptions;
+ }
+
/*
* Low-level API performing the actual compilation
*/
@@ -135,8 +146,9 @@
char[] contents,
Parser parser,
WorkingCopyOwner workingCopyOwner,
- IProblemRequestor problemRequestor,
- boolean resetEnvironment,
+ HashMap problems,
+ boolean creatingAST,
+ int reconcileFlags,
IProgressMonitor monitor)
throws JavaModelException {
@@ -150,7 +162,7 @@
problemFinder = new CompilationUnitProblemFinder(
environment,
getHandlingPolicy(),
- project.getOptions(true),
+ getCompilerOptions(project.getOptions(true), creatingAST, ((reconcileFlags & ICompilationUnit.ENABLE_STATEMENTS_RECOVERY) != 0)),
getRequestor(),
problemFactory);
if (parser != null) {
@@ -179,7 +191,21 @@
true, // analyze code
true); // generate code
}
- reportProblems(unit, problemRequestor, monitor);
+ CompilationResult unitResult = unit.compilationResult;
+ CategorizedProblem[] unitProblems = unitResult.getProblems();
+ int length = unitProblems == null ? 0 : unitProblems.length;
+ if (length > 0) {
+ CategorizedProblem[] categorizedProblems = new CategorizedProblem[length];
+ System.arraycopy(unitProblems, 0, categorizedProblems, 0, length);
+ problems.put(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, categorizedProblems);
+ }
+ unitProblems = unitResult.getTasks();
+ length = unitProblems == null ? 0 : unitProblems.length;
+ if (length > 0) {
+ CategorizedProblem[] categorizedProblems = new CategorizedProblem[length];
+ System.arraycopy(unitProblems, 0, categorizedProblems, 0, length);
+ problems.put(IJavaModelMarker.TASK_MARKER, categorizedProblems);
+ }
if (NameLookup.VERBOSE) {
System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInSourcePackage: " + environment.nameLookup.timeSpentInSeekTypesInSourcePackage + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInBinaryPackage: " + environment.nameLookup.timeSpentInSeekTypesInBinaryPackage + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
@@ -189,7 +215,15 @@
throw e;
} catch(RuntimeException e) {
// avoid breaking other tools due to internal compiler failure (40334)
- Util.log(e, "Exception occurred during problem detection: "); //$NON-NLS-1$
+ String lineDelimiter = unitElement.findRecommendedLineSeparator();
+ StringBuffer message = new StringBuffer("Exception occurred during problem detection:"); //$NON-NLS-1$
+ message.append(lineDelimiter);
+ message.append("----------------------------------- SOURCE BEGIN -------------------------------------"); //$NON-NLS-1$
+ message.append(lineDelimiter);
+ message.append(contents);
+ message.append(lineDelimiter);
+ message.append("----------------------------------- SOURCE END -------------------------------------"); //$NON-NLS-1$
+ Util.log(e, message.toString());
throw new JavaModelException(e, IJavaModelStatusConstants.COMPILER_FAILURE);
} finally {
if (environment != null)
@@ -197,8 +231,8 @@
if (problemFactory != null)
problemFactory.monitor = null; // don't hold a reference to this external object
// NB: unit.cleanUp() is done by caller
- if (problemFinder != null && resetEnvironment)
- problemFinder.lookupEnvironment.reset();
+ if (problemFinder != null && !creatingAST)
+ problemFinder.lookupEnvironment.reset();
}
}
@@ -206,25 +240,13 @@
ICompilationUnit unitElement,
char[] contents,
WorkingCopyOwner workingCopyOwner,
- IProblemRequestor problemRequestor,
- boolean resetEnvironment,
+ HashMap problems,
+ boolean creatingAST,
+ int reconcileFlags,
IProgressMonitor monitor)
throws JavaModelException {
- return process(null/*no CompilationUnitDeclaration*/, unitElement, contents, null/*use default Parser*/, workingCopyOwner, problemRequestor, resetEnvironment, monitor);
- }
-
-
- private static void reportProblems(CompilationUnitDeclaration unit, IProblemRequestor problemRequestor, IProgressMonitor monitor) {
- CompilationResult unitResult = unit.compilationResult;
- IProblem[] problems = unitResult.getAllProblems();
- for (int i = 0, problemLength = problems == null ? 0 : problems.length; i < problemLength; i++) {
- if (JavaModelManager.VERBOSE){
- System.out.println("PROBLEM FOUND while reconciling : "+problems[i].getMessage());//$NON-NLS-1$
- }
- if (monitor != null && monitor.isCanceled()) break;
- problemRequestor.acceptProblem(problems[i]);
- }
+ return process(null/*no CompilationUnitDeclaration*/, unitElement, contents, null/*use default Parser*/, workingCopyOwner, problems, creatingAST, reconcileFlags, monitor);
}
/* (non-Javadoc)
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor.java
index a455ef8..1241703 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,13 +10,14 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core;
+import java.util.ArrayList;
+import java.util.HashMap;
import java.util.Map;
import java.util.Stack;
+import org.eclipse.core.runtime.Assert;
import org.eclipse.jdt.core.*;
-import org.eclipse.jdt.core.ICompilationUnit;
-import org.eclipse.jdt.core.IJavaElement;
-import org.eclipse.jdt.core.Signature;
+import org.eclipse.jdt.core.compiler.CategorizedProblem;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.internal.compiler.ISourceElementRequestor;
@@ -59,6 +60,12 @@
* will be the type the method is contained in.
*/
protected Stack infoStack;
+
+ /*
+ * Map from JavaElementInfo to of ArrayList of IJavaElement representing the children
+ * of the given info.
+ */
+ protected HashMap children;
/**
* Stack of parent handles, corresponding to the info stack. We
@@ -86,7 +93,6 @@
/**
* Empty collections used for efficient initialization
*/
- protected static String[] NO_STRINGS = new String[0];
protected static byte[] NO_BYTES= new byte[]{};
protected HashtableOfObject fieldRefCache;
@@ -102,8 +108,7 @@
/**
* @see ISourceElementRequestor
*/
-public void acceptImport(int declarationStart, int declarationEnd, char[] name, boolean onDemand, int modifiers) {
- JavaElementInfo parentInfo = (JavaElementInfo) this.infoStack.peek();
+public void acceptImport(int declarationStart, int declarationEnd, char[][] tokens, boolean onDemand, int modifiers) {
JavaElement parentHandle= (JavaElement) this.handleStack.peek();
if (!(parentHandle.getElementType() == IJavaElement.COMPILATION_UNIT)) {
Assert.isTrue(false); // Should not happen
@@ -113,12 +118,13 @@
//create the import container and its info
ImportContainer importContainer= (ImportContainer)parentCU.getImportContainer();
if (this.importContainerInfo == null) {
- this.importContainerInfo= new JavaElementInfo();
- parentInfo.addChild(importContainer);
+ this.importContainerInfo = new JavaElementInfo();
+ JavaElementInfo parentInfo = (JavaElementInfo) this.infoStack.peek();
+ addToChildren(parentInfo, importContainer);
this.newElements.put(importContainer, this.importContainerInfo);
}
- String elementName = JavaModelManager.getJavaModelManager().intern(new String(name));
+ String elementName = JavaModelManager.getJavaModelManager().intern(new String(CharOperation.concatWith(tokens, '.')));
ImportDeclaration handle = new ImportDeclaration(importContainer, elementName, onDemand);
resolveDuplicates(handle);
@@ -127,7 +133,7 @@
info.setSourceRangeEnd(declarationEnd);
info.setFlags(modifiers);
- this.importContainerInfo.addChild(handle);
+ addToChildren(this.importContainerInfo, handle);
this.newElements.put(handle, info);
}
/*
@@ -161,25 +167,31 @@
info.setSourceRangeStart(declarationStart);
info.setSourceRangeEnd(declarationEnd);
- parentInfo.addChild(handle);
+ addToChildren(parentInfo, handle);
this.newElements.put(handle, info);
}
-public void acceptProblem(IProblem problem) {
+public void acceptProblem(CategorizedProblem problem) {
if ((problem.getID() & IProblem.Syntax) != 0){
this.hasSyntaxErrors = true;
}
}
+private void addToChildren(JavaElementInfo parentInfo, JavaElement handle) {
+ ArrayList childrenList = (ArrayList) this.children.get(parentInfo);
+ if (childrenList == null)
+ this.children.put(parentInfo, childrenList = new ArrayList());
+ childrenList.add(handle);
+}
/**
* Convert these type names to signatures.
* @see Signature
*/
/* default */ static String[] convertTypeNamesToSigs(char[][] typeNames) {
if (typeNames == null)
- return NO_STRINGS;
+ return CharOperation.NO_STRINGS;
int n = typeNames.length;
if (n == 0)
- return NO_STRINGS;
+ return CharOperation.NO_STRINGS;
JavaModelManager manager = JavaModelManager.getJavaModelManager();
String[] typeSigs = new String[n];
for (int i = 0; i < n; ++i) {
@@ -192,6 +204,7 @@
*/
public void enterCompilationUnit() {
this.infoStack = new Stack();
+ this.children = new HashMap();
this.handleStack= new Stack();
this.infoStack.push(this.unitInfo);
this.handleStack.push(this.unit);
@@ -229,7 +242,8 @@
this.unitInfo.addAnnotationPositions(handle, fieldInfo.annotationPositions);
- parentInfo.addChild(handle);
+ addToChildren(parentInfo, handle);
+ parentInfo.addCategories(handle, fieldInfo.categories);
this.newElements.put(handle, info);
this.infoStack.push(info);
@@ -257,7 +271,7 @@
info.setSourceRangeStart(declarationSourceStart);
info.setFlags(modifiers);
- parentInfo.addChild(handle);
+ addToChildren(parentInfo, handle);
this.newElements.put(handle, info);
this.infoStack.push(info);
@@ -317,7 +331,8 @@
for (int i = 0, length = exceptionTypes.length; i < length; i++)
exceptionTypes[i] = manager.intern(exceptionTypes[i]);
this.unitInfo.addAnnotationPositions(handle, methodInfo.annotationPositions);
- parentInfo.addChild(handle);
+ addToChildren(parentInfo, handle);
+ parentInfo.addCategories(handle, methodInfo.categories);
this.newElements.put(handle, info);
this.infoStack.push(info);
this.handleStack.push(handle);
@@ -338,10 +353,17 @@
JavaElementInfo parentInfo = (JavaElementInfo) this.infoStack.peek();
JavaElement parentHandle= (JavaElement) this.handleStack.peek();
String nameString= new String(typeInfo.name);
- SourceType handle = handle = new SourceType(parentHandle, nameString); //NB: occurenceCount is computed in resolveDuplicates
+ SourceType handle = new SourceType(parentHandle, nameString); //NB: occurenceCount is computed in resolveDuplicates
resolveDuplicates(handle);
- SourceTypeElementInfo info = new SourceTypeElementInfo();
+ SourceTypeElementInfo info =
+ typeInfo.anonymousMember ?
+ new SourceTypeElementInfo() {
+ public boolean isAnonymousMember() {
+ return true;
+ }
+ } :
+ new SourceTypeElementInfo();
info.setHandle(handle);
info.setSourceRangeStart(typeInfo.declarationStart);
info.setFlags(typeInfo.modifiers);
@@ -354,7 +376,10 @@
for (int i = 0, length = superinterfaces == null ? 0 : superinterfaces.length; i < length; i++)
superinterfaces[i] = manager.intern(superinterfaces[i]);
info.setSuperInterfaceNames(superinterfaces);
- parentInfo.addChild(handle);
+ info.addCategories(handle, typeInfo.categories);
+ if (parentHandle.getElementType() == IJavaElement.TYPE)
+ ((SourceTypeElementInfo) parentInfo).addCategories(handle, typeInfo.categories);
+ addToChildren(parentInfo, handle);
this.unitInfo.addAnnotationPositions(handle, typeInfo.annotationPositions);
this.newElements.put(handle, info);
this.infoStack.push(info);
@@ -372,7 +397,7 @@
JavaElementInfo parentInfo = (JavaElementInfo) this.infoStack.peek();
JavaElement parentHandle = (JavaElement) this.handleStack.peek();
String nameString = new String(typeParameterInfo.name);
- TypeParameter handle = handle = new TypeParameter(parentHandle, nameString); //NB: occurenceCount is computed in resolveDuplicates
+ TypeParameter handle = new TypeParameter(parentHandle, nameString); //NB: occurenceCount is computed in resolveDuplicates
resolveDuplicates(handle);
TypeParameterElementInfo info = new TypeParameterElementInfo();
@@ -404,6 +429,14 @@
* @see ISourceElementRequestor
*/
public void exitCompilationUnit(int declarationEnd) {
+ // set import container children
+ if (this.importContainerInfo != null) {
+ setChildren(this.importContainerInfo);
+ }
+
+ // set children
+ setChildren(this.unitInfo);
+
this.unitInfo.setSourceLength(declarationEnd + 1);
// determine if there were any parsing errors
@@ -421,6 +454,7 @@
public void exitField(int initializationStart, int declarationEnd, int declarationSourceEnd) {
SourceFieldElementInfo info = (SourceFieldElementInfo) this.infoStack.pop();
info.setSourceRangeEnd(declarationSourceEnd);
+ setChildren(info);
// remember initializer source if field is a constant
if (initializationStart != -1) {
@@ -451,6 +485,7 @@
protected void exitMember(int declarationEnd) {
SourceRefElementInfo info = (SourceRefElementInfo) this.infoStack.pop();
info.setSourceRangeEnd(declarationEnd);
+ setChildren(info);
this.handleStack.pop();
}
/**
@@ -459,6 +494,7 @@
public void exitMethod(int declarationEnd, int defaultValueStart, int defaultValueEnd) {
SourceMethodElementInfo info = (SourceMethodElementInfo) this.infoStack.pop();
info.setSourceRangeEnd(declarationEnd);
+ setChildren(info);
// remember default value of annotation method
if (info.isAnnotationMethod()) {
@@ -484,4 +520,13 @@
handle.occurrenceCount++;
}
}
+private void setChildren(JavaElementInfo info) {
+ ArrayList childrenList = (ArrayList) this.children.get(info);
+ if (childrenList != null) {
+ int length = childrenList.size();
+ IJavaElement[] elements = new IJavaElement[length];
+ childrenList.toArray(elements);
+ info.children = elements;
+ }
+}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitVisitor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitVisitor.java
deleted file mode 100644
index f61263f..0000000
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitVisitor.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.jdt.internal.core;
-
-import java.util.Locale;
-import java.util.Map;
-
-import org.eclipse.jdt.core.ICompilationUnit;
-import org.eclipse.jdt.core.IJavaElement;
-import org.eclipse.jdt.core.JavaModelException;
-import org.eclipse.jdt.core.compiler.IProblem;
-import org.eclipse.jdt.internal.compiler.CompilationResult;
-import org.eclipse.jdt.internal.compiler.Compiler;
-import org.eclipse.jdt.internal.compiler.ASTVisitor;
-import org.eclipse.jdt.internal.compiler.ICompilerRequestor;
-import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy;
-import org.eclipse.jdt.internal.compiler.IProblemFactory;
-import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
-import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
-import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
-import org.eclipse.jdt.internal.compiler.env.ISourceType;
-import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
-import org.eclipse.jdt.internal.compiler.parser.SourceTypeConverter;
-import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
-import org.eclipse.jdt.internal.core.util.Util;
-
-public class CompilationUnitVisitor extends Compiler {
-
- /**
- * Answer a new CompilationUnitVisitor using the given name environment and compiler options.
- * The environment and options will be in effect for the lifetime of the compiler.
- * When the compiler is run, compilation results are sent to the given requestor.
- *
- * @param environment org.eclipse.jdt.internal.compiler.api.env.INameEnvironment
- * Environment used by the compiler in order to resolve type and package
- * names. The name environment implements the actual connection of the compiler
- * to the outside world (e.g. in batch mode the name environment is performing
- * pure file accesses, reuse previous build state or connection to repositories).
- * Note: the name environment is responsible for implementing the actual classpath
- * rules.
- *
- * @param policy org.eclipse.jdt.internal.compiler.api.problem.IErrorHandlingPolicy
- * Configurable part for problem handling, allowing the compiler client to
- * specify the rules for handling problems (stop on first error or accumulate
- * them all) and at the same time perform some actions such as opening a dialog
- * in UI when compiling interactively.
- * @see org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies
- *
- * @param requestor org.eclipse.jdt.internal.compiler.api.ICompilerRequestor
- * Component which will receive and persist all compilation results and is intended
- * to consume them as they are produced. Typically, in a batch compiler, it is
- * responsible for writing out the actual .class files to the file system.
- * @see org.eclipse.jdt.internal.compiler.CompilationResult
- *
- * @param problemFactory org.eclipse.jdt.internal.compiler.api.problem.IProblemFactory
- * Factory used inside the compiler to create problem descriptors. It allows the
- * compiler client to supply its own representation of compilation problems in
- * order to avoid object conversions. Note that the factory is not supposed
- * to accumulate the created problems, the compiler will gather them all and hand
- * them back as part of the compilation unit result.
- */
- public CompilationUnitVisitor(
- INameEnvironment environment,
- IErrorHandlingPolicy policy,
- Map settings,
- ICompilerRequestor requestor,
- IProblemFactory problemFactory) {
-
- super(environment, policy, settings, requestor, problemFactory);
- }
-
- /**
- * Add additional source types
- */
- public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding, AccessRestriction accessRestriction) {
- CompilationResult result =
- new CompilationResult(sourceTypes[0].getFileName(), 1, 1, this.options.maxProblemsPerUnit);
- // need to hold onto this
- CompilationUnitDeclaration unit =
- SourceTypeConverter.buildCompilationUnit(
- sourceTypes,//sourceTypes[0] is always toplevel here
- SourceTypeConverter.FIELD_AND_METHOD // need field and methods
- | SourceTypeConverter.MEMBER_TYPE, // need member types
- // no need for field initialization
- this.lookupEnvironment.problemReporter,
- result);
-
- if (unit != null) {
- this.lookupEnvironment.buildTypeBindings(unit, accessRestriction);
- this.lookupEnvironment.completeTypeBindings(unit, true);
- }
- }
-
- /*
- * Low-level API performing the actual compilation
- */
- protected static IErrorHandlingPolicy getHandlingPolicy() {
-
- // passes the initial set of files to the batch oracle (to avoid finding more than once the same units when case insensitive match)
- return new IErrorHandlingPolicy() {
- public boolean stopOnFirstError() {
- return false;
- }
- public boolean proceedOnErrors() {
- return false; // stop if there are some errors
- }
- };
- }
-
- /*
- * Answer the component to which will be handed back compilation results from the compiler
- */
- protected static ICompilerRequestor getRequestor() {
- return new ICompilerRequestor() {
- public void acceptResult(CompilationResult compilationResult) {
- // nothing to do
- }
- };
- }
-
- public static void visit(
- ICompilationUnit unitElement,
- ASTVisitor visitor)
- throws JavaModelException {
-
- JavaProject project = (JavaProject) unitElement.getJavaProject();
- CompilationUnitVisitor compilationUnitVisitor =
- new CompilationUnitVisitor(
- project.newSearchableNameEnvironment(unitElement.getOwner()),
- getHandlingPolicy(),
- project.getOptions(true),
- getRequestor(),
- getProblemFactory(visitor));
-
- CompilationUnitDeclaration unit = null;
- try {
-
- PackageFragment packageFragment = (PackageFragment)unitElement.getAncestor(IJavaElement.PACKAGE_FRAGMENT);
- char[][] expectedPackageName = null;
- if (packageFragment != null){
- expectedPackageName = Util.toCharArrays(packageFragment.names);
- }
- unit =
- compilationUnitVisitor.resolve(
- new BasicCompilationUnit(
- unitElement.getSource().toCharArray(),
- expectedPackageName,
- unitElement.getElementName(),
- unitElement),
- true, // method verification
- false, // no flow analysis
- false); // no code generation
- if (unit != null) {
- unit.traverse(visitor, unit.scope);
- }
- } finally {
- if (unit != null) {
- unit.cleanUp();
- }
- }
- }
-
- protected static IProblemFactory getProblemFactory(final ASTVisitor visitor) {
-
- return new DefaultProblemFactory(Locale.getDefault()) {
- public IProblem createProblem(
- char[] originatingFileName,
- int problemId,
- String[] problemArguments,
- String[] messageArguments,
- int severity,
- int startPosition,
- int endPosition,
- int lineNumber) {
-
- IProblem problem =
- super.createProblem(
- originatingFileName,
- problemId,
- problemArguments,
- messageArguments,
- severity,
- startPosition,
- endPosition,
- lineNumber);
- visitor.acceptProblem(problem);
- return problem;
- }
- };
- }
-}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyElementsOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyElementsOperation.java
index c93e061..d1524eb 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyElementsOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyElementsOperation.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -15,6 +15,7 @@
import org.eclipse.core.runtime.IPath;
import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IImportDeclaration;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaModelStatus;
import org.eclipse.jdt.core.IJavaModelStatusConstants;
@@ -95,12 +96,13 @@
case IJavaElement.PACKAGE_DECLARATION :
return new CreatePackageDeclarationOperation(element.getElementName(), (ICompilationUnit) dest);
case IJavaElement.IMPORT_DECLARATION :
- return new CreateImportOperation(element.getElementName(), (ICompilationUnit) dest);
+ IImportDeclaration importDeclaration = (IImportDeclaration) element;
+ return new CreateImportOperation(element.getElementName(), (ICompilationUnit) dest, importDeclaration.getFlags());
case IJavaElement.TYPE :
if (isRenamingMainType(element, dest)) {
IPath path = element.getPath();
String extension = path.getFileExtension();
- return new RenameResourceElementsOperation(new IJavaElement[] {dest}, new IJavaElement[] {dest.getParent()}, new String[]{getNewNameFor(element) + '.' + extension}, this.force); //$NON-NLS-1$
+ return new RenameResourceElementsOperation(new IJavaElement[] {dest}, new IJavaElement[] {dest.getParent()}, new String[]{getNewNameFor(element) + '.' + extension}, this.force);
} else {
String source = getSourceFor(element);
String lineSeparator = org.eclipse.jdt.internal.core.util.Util.getLineSeparator(source, element.getJavaProject());
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyPackageFragmentRootOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyPackageFragmentRootOperation.java
index d0698df..cfec9ba 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyPackageFragmentRootOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyPackageFragmentRootOperation.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -11,15 +11,10 @@
package org.eclipse.jdt.internal.core;
import org.eclipse.core.resources.*;
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.AssertionFailedException;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jdt.core.*;
-import org.eclipse.jdt.core.IClasspathEntry;
-import org.eclipse.jdt.core.IJavaModelStatus;
-import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.core.util.Messages;
public class CopyPackageFragmentRootOperation extends JavaModelOperation {
@@ -129,7 +124,7 @@
throw new JavaModelException(e);
}
}
- this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
+ setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
}
protected void addEntryToClasspath(IClasspathEntry rootEntry, IWorkspaceRoot workspaceRoot) throws JavaModelException {
@@ -193,7 +188,7 @@
case IClasspathEntry.CPE_LIBRARY:
try {
return JavaCore.newLibraryEntry(this.destination, entry.getSourceAttachmentPath(), entry.getSourceAttachmentRootPath(), entry.getAccessRules(), entry.getExtraAttributes(), entry.isExported());
- } catch (Assert.AssertionFailedException e) {
+ } catch (AssertionFailedException e) {
IJavaModelStatus status = new JavaModelStatus(IJavaModelStatusConstants.INVALID_PATH, e.getMessage());
throw new JavaModelException(status);
}
@@ -204,7 +199,7 @@
case IClasspathEntry.CPE_VARIABLE:
try {
return JavaCore.newVariableEntry(entry.getPath(), entry.getSourceAttachmentPath(), entry.getSourceAttachmentRootPath(), entry.getAccessRules(), entry.getExtraAttributes(), entry.isExported());
- } catch (Assert.AssertionFailedException e) {
+ } catch (AssertionFailedException e) {
IJavaModelStatus status = new JavaModelStatus(IJavaModelStatusConstants.INVALID_PATH, e.getMessage());
throw new JavaModelException(status);
}
@@ -249,7 +244,7 @@
}
}
if (this.sibling != null && !foundSibling) {
- return new JavaModelStatus(IJavaModelStatusConstants.INVALID_SIBLING, this.sibling == null ? "null" : this.sibling.toString()); //$NON-NLS-1$
+ return new JavaModelStatus(IJavaModelStatusConstants.INVALID_SIBLING, this.sibling.toString());
}
if (foundExistingEntry && (this.updateModelFlags & IPackageFragmentRoot.REPLACE) == 0) {
return new JavaModelStatus(
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyResourceElementsOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyResourceElementsOperation.java
index cc3c386..6eca474 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyResourceElementsOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyResourceElementsOperation.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -247,27 +247,31 @@
org.eclipse.jdt.internal.core.CompilationUnit destCU = new org.eclipse.jdt.internal.core.CompilationUnit(dest, destName, DefaultWorkingCopyOwner.PRIMARY);
if (!destFile.equals(sourceResource)) {
try {
- if (destFile.exists()) {
- if (this.force) {
- // we can remove it
- deleteResource(destFile, IResource.KEEP_HISTORY);
- destCU.close(); // ensure the in-memory buffer for the dest CU is closed
- } else {
- // abort
- throw new JavaModelException(new JavaModelStatus(
- IJavaModelStatusConstants.NAME_COLLISION,
- Messages.bind(Messages.status_nameCollision, destFile.getFullPath().toString())));
+ if (!destCU.isWorkingCopy()) {
+ if (destFile.exists()) {
+ if (this.force) {
+ // we can remove it
+ deleteResource(destFile, IResource.KEEP_HISTORY);
+ destCU.close(); // ensure the in-memory buffer for the dest CU is closed
+ } else {
+ // abort
+ throw new JavaModelException(new JavaModelStatus(
+ IJavaModelStatusConstants.NAME_COLLISION,
+ Messages.bind(Messages.status_nameCollision, destFile.getFullPath().toString())));
+ }
}
- }
- int flags = this.force ? IResource.FORCE : IResource.NONE;
- if (this.isMove()) {
- flags |= IResource.KEEP_HISTORY;
- sourceResource.move(destFile.getFullPath(), flags, getSubProgressMonitor(1));
+ int flags = this.force ? IResource.FORCE : IResource.NONE;
+ if (this.isMove()) {
+ flags |= IResource.KEEP_HISTORY;
+ sourceResource.move(destFile.getFullPath(), flags, getSubProgressMonitor(1));
+ } else {
+ if (rewrite != null) flags |= IResource.KEEP_HISTORY;
+ sourceResource.copy(destFile.getFullPath(), flags, getSubProgressMonitor(1));
+ }
+ setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
} else {
- if (rewrite != null) flags |= IResource.KEEP_HISTORY;
- sourceResource.copy(destFile.getFullPath(), flags, getSubProgressMonitor(1));
+ destCU.getBuffer().setContents(source.getBuffer().getContents());
}
- this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
} catch (JavaModelException e) {
throw e;
} catch (CoreException e) {
@@ -304,13 +308,8 @@
// update new resource content
// in case we do a saveas on the same resource we have to simply update the contents
// see http://dev.eclipse.org/bugs/show_bug.cgi?id=9351
- try {
- if (rewrite != null){
- saveContent(dest, destName, rewrite, sourceEncoding, destFile);
- }
- } catch (CoreException e) {
- if (e instanceof JavaModelException) throw (JavaModelException) e;
- throw new JavaModelException(e);
+ if (rewrite != null){
+ saveContent(dest, destName, rewrite, sourceEncoding, destFile);
}
}
}
@@ -405,7 +404,7 @@
if (sourceIsReadOnly) {
Util.setReadOnly(srcFolder, true);
}
- this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
+ setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
} else {
// process the leaf resources
if (resources.length > 0) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateCompilationUnitOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateCompilationUnitOperation.java
index f05a7d7..f84a048 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateCompilationUnitOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateCompilationUnitOperation.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -15,9 +15,6 @@
import java.io.InputStream;
import org.eclipse.core.resources.*;
-import org.eclipse.core.resources.IContainer;
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
@@ -29,9 +26,10 @@
import org.eclipse.jdt.core.IJavaElementDelta;
import org.eclipse.jdt.core.IJavaModelStatus;
import org.eclipse.jdt.core.IJavaModelStatusConstants;
+import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.JavaConventions;
-//import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.core.util.Messages;
import org.eclipse.jdt.internal.core.util.Util;
@@ -163,7 +161,8 @@
if (getParentElement() == null) {
return new JavaModelStatus(IJavaModelStatusConstants.NO_ELEMENTS_TO_PROCESS);
}
- if (JavaConventions.validateCompilationUnitName(fName).getSeverity() == IStatus.ERROR) {
+ IJavaProject project = getParentElement().getJavaProject();
+ if (JavaConventions.validateCompilationUnitName(fName, project.getOption(JavaCore.COMPILER_SOURCE, true), project.getOption(JavaCore.COMPILER_COMPLIANCE, true)).getSeverity() == IStatus.ERROR) {
return new JavaModelStatus(IJavaModelStatusConstants.INVALID_NAME, fName);
}
if (fSource == null) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateElementInCUOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateElementInCUOperation.java
index c996a59..acd4b72 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateElementInCUOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateElementInCUOperation.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,6 +10,8 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core;
+import java.util.Map;
+
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
@@ -91,8 +93,8 @@
super(null, new IJavaElement[]{parentElement});
initializeDefaultPosition();
}
- protected void apply(ASTRewrite rewriter, IDocument document) throws JavaModelException {
- TextEdit edits = rewriter.rewriteAST(document, null);
+ protected void apply(ASTRewrite rewriter, IDocument document, Map options) throws JavaModelException {
+ TextEdit edits = rewriter.rewriteAST(document, options);
try {
edits.apply(document);
} catch (BadLocationException e) {
@@ -140,7 +142,7 @@
unit.save(null, false);
boolean isWorkingCopy = unit.isWorkingCopy();
if (!isWorkingCopy)
- this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
+ setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
worked(1);
resultElements = generateResultHandles();
if (!isWorkingCopy // if unit is working copy, then save will have already fired the delta
@@ -182,7 +184,7 @@
if (parent == null)
parent = this.cuAST;
insertASTNode(rewriter, parent, child);
- apply(rewriter, document);
+ apply(rewriter, document, cu.getJavaProject().getOptions(true));
}
worked(1);
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateFieldOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateFieldOperation.java
index b47da45..5eaecce 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateFieldOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateFieldOperation.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,6 +10,8 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core;
+import java.util.Iterator;
+
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IJavaElement;
@@ -64,6 +66,22 @@
public String getMainTaskName(){
return Messages.operation_createFieldProgress;
}
+private VariableDeclarationFragment getFragment(ASTNode node) {
+ Iterator fragments = ((FieldDeclaration) node).fragments().iterator();
+ if (this.anchorElement != null) {
+ VariableDeclarationFragment fragment = null;
+ String fragmentName = this.anchorElement.getElementName();
+ while (fragments.hasNext()) {
+ fragment = (VariableDeclarationFragment) fragments.next();
+ if (fragment.getName().getIdentifier().equals(fragmentName)) {
+ return fragment;
+ }
+ }
+ return fragment;
+ } else {
+ return (VariableDeclarationFragment) fragments.next();
+ }
+}
/**
* By default the new field is positioned after the last existing field
* declaration, or as the first member in the type if there are no
@@ -109,11 +127,11 @@
return JavaModelStatus.VERIFIED_OK;
}
private String getASTNodeName() {
- VariableDeclarationFragment fragment = (VariableDeclarationFragment) ((FieldDeclaration) this.createdNode).fragments().iterator().next();
- return fragment.getName().getIdentifier();
+ if (this.alteredName != null) return this.alteredName;
+ return getFragment(this.createdNode).getName().getIdentifier();
}
protected SimpleName rename(ASTNode node, SimpleName newName) {
- VariableDeclarationFragment fragment = (VariableDeclarationFragment) ((FieldDeclaration) node).fragments().iterator().next();
+ VariableDeclarationFragment fragment = getFragment(node);
SimpleName oldName = fragment.getName();
fragment.setName(newName);
return oldName;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateImportOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateImportOperation.java
index 44cc371..362fb57 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateImportOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateImportOperation.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -13,13 +13,16 @@
import java.util.Iterator;
import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IImportDeclaration;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaModelStatus;
import org.eclipse.jdt.core.IJavaModelStatusConstants;
+import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaConventions;
+import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.dom.AST;
@@ -52,16 +55,23 @@
*/
public class CreateImportOperation extends CreateElementInCUOperation {
- /**
+ /*
* The name of the import to be created.
*/
protected String importName;
+
+ /*
+ * The flags of the import to be created (either Flags#AccDefault or Flags#AccStatic)
+ */
+ protected int flags;
+
/**
* When executed, this operation will add an import to the given compilation unit.
*/
-public CreateImportOperation(String importName, ICompilationUnit parentElement) {
+public CreateImportOperation(String importName, ICompilationUnit parentElement, int flags) {
super(parentElement);
this.importName = importName;
+ this.flags = flags;
}
protected StructuralPropertyDescriptor getChildPropertyDescriptor(ASTNode parent) {
return CompilationUnit.IMPORTS_PROPERTY;
@@ -69,10 +79,16 @@
protected ASTNode generateElementAST(ASTRewrite rewriter, IDocument document, ICompilationUnit cu) throws JavaModelException {
// ensure no duplicate
Iterator imports = this.cuAST.imports().iterator();
+ boolean onDemand = this.importName.endsWith(".*"); //$NON-NLS-1$
+ String importActualName = this.importName;
+ if (onDemand) {
+ importActualName = this.importName.substring(0, this.importName.length() - 2);
+ }
while (imports.hasNext()) {
ImportDeclaration importDeclaration = (ImportDeclaration) imports.next();
- if (this.importName.equals(importDeclaration.getName().getFullyQualifiedName())) {
- //no new import was generated
+ if (importActualName.equals(importDeclaration.getName().getFullyQualifiedName())
+ && (onDemand == importDeclaration.isOnDemand())
+ && (Flags.isStatic(this.flags) == importDeclaration.isStatic())) {
this.creationOccurred = false;
return null;
}
@@ -80,9 +96,9 @@
AST ast = this.cuAST.getAST();
ImportDeclaration importDeclaration = ast.newImportDeclaration();
+ importDeclaration.setStatic(Flags.isStatic(this.flags));
// split import name into individual fragments, checking for on demand imports
- boolean onDemand = this.importName.endsWith("*"); //$NON-NLS-1$
- char[][] charFragments = CharOperation.splitOn('.', this.importName.toCharArray(), 0, onDemand ? this.importName.length()-2 : this.importName.length());
+ char[][] charFragments = CharOperation.splitOn('.', importActualName.toCharArray(), 0, importActualName.length());
int length = charFragments.length;
String[] strFragments = new String[length];
for (int i = 0; i < length; i++) {
@@ -151,7 +167,8 @@
if (!status.isOK()) {
return status;
}
- if (JavaConventions.validateImportDeclaration(this.importName).getSeverity() == IStatus.ERROR) {
+ IJavaProject project = getParentElement().getJavaProject();
+ if (JavaConventions.validateImportDeclaration(this.importName, project.getOption(JavaCore.COMPILER_SOURCE, true), project.getOption(JavaCore.COMPILER_COMPLIANCE, true)).getSeverity() == IStatus.ERROR) {
return new JavaModelStatus(IJavaModelStatusConstants.INVALID_NAME, this.importName);
}
return JavaModelStatus.VERIFIED_OK;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreatePackageDeclarationOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreatePackageDeclarationOperation.java
index 9265806..af4fd26 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreatePackageDeclarationOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreatePackageDeclarationOperation.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -16,8 +16,10 @@
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaModelStatus;
import org.eclipse.jdt.core.IJavaModelStatusConstants;
+import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaConventions;
+import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
@@ -120,7 +122,8 @@
if (!status.isOK()) {
return status;
}
- if (JavaConventions.validatePackageName(this.name).getSeverity() == IStatus.ERROR) {
+ IJavaProject project = getParentElement().getJavaProject();
+ if (JavaConventions.validatePackageName(this.name, project.getOption(JavaCore.COMPILER_SOURCE, true), project.getOption(JavaCore.COMPILER_COMPLIANCE, true)).getSeverity() == IStatus.ERROR) {
return new JavaModelStatus(IJavaModelStatusConstants.INVALID_NAME, this.name);
}
return JavaModelStatus.VERIFIED_OK;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreatePackageFragmentOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreatePackageFragmentOperation.java
index fa757f5..d186a90 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreatePackageFragmentOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreatePackageFragmentOperation.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -19,9 +19,11 @@
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaModelStatus;
import org.eclipse.jdt.core.IJavaModelStatusConstants;
+import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaConventions;
+import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.core.util.Messages;
@@ -67,43 +69,46 @@
* @exception JavaModelException if the operation is unable to complete
*/
protected void executeOperation() throws JavaModelException {
- JavaElementDelta delta = null;
- PackageFragmentRoot root = (PackageFragmentRoot) getParentElement();
- beginTask(Messages.operation_createPackageFragmentProgress, this.pkgName.length);
- IContainer parentFolder = (IContainer) root.getResource();
- String[] sideEffectPackageName = CharOperation.NO_STRINGS;
- ArrayList results = new ArrayList(this.pkgName.length);
- char[][] inclusionPatterns = root.fullInclusionPatternChars();
- char[][] exclusionPatterns = root.fullExclusionPatternChars();
- int i;
- for (i = 0; i < this.pkgName.length; i++) {
- String subFolderName = this.pkgName[i];
- sideEffectPackageName = Util.arrayConcat(sideEffectPackageName, subFolderName);
- IResource subFolder = parentFolder.findMember(subFolderName);
- if (subFolder == null) {
- createFolder(parentFolder, subFolderName, force);
- parentFolder = parentFolder.getFolder(new Path(subFolderName));
- IPackageFragment addedFrag = root.getPackageFragment(sideEffectPackageName);
- if (!Util.isExcluded(parentFolder, inclusionPatterns, exclusionPatterns)) {
- if (delta == null) {
- delta = newJavaElementDelta();
+ try {
+ JavaElementDelta delta = null;
+ PackageFragmentRoot root = (PackageFragmentRoot) getParentElement();
+ beginTask(Messages.operation_createPackageFragmentProgress, this.pkgName.length);
+ IContainer parentFolder = (IContainer) root.getResource();
+ String[] sideEffectPackageName = CharOperation.NO_STRINGS;
+ ArrayList results = new ArrayList(this.pkgName.length);
+ char[][] inclusionPatterns = root.fullInclusionPatternChars();
+ char[][] exclusionPatterns = root.fullExclusionPatternChars();
+ int i;
+ for (i = 0; i < this.pkgName.length; i++) {
+ String subFolderName = this.pkgName[i];
+ sideEffectPackageName = Util.arrayConcat(sideEffectPackageName, subFolderName);
+ IResource subFolder = parentFolder.findMember(subFolderName);
+ if (subFolder == null) {
+ createFolder(parentFolder, subFolderName, force);
+ parentFolder = parentFolder.getFolder(new Path(subFolderName));
+ IPackageFragment addedFrag = root.getPackageFragment(sideEffectPackageName);
+ if (!Util.isExcluded(parentFolder, inclusionPatterns, exclusionPatterns)) {
+ if (delta == null) {
+ delta = newJavaElementDelta();
+ }
+ delta.added(addedFrag);
}
- delta.added(addedFrag);
+ results.add(addedFrag);
+ } else {
+ parentFolder = (IContainer) subFolder;
}
- results.add(addedFrag);
- } else {
- parentFolder = (IContainer) subFolder;
+ worked(1);
}
- worked(1);
- }
- if (results.size() > 0) {
- this.resultElements = new IJavaElement[results.size()];
- results.toArray(this.resultElements);
- if (delta != null) {
- addDelta(delta);
+ if (results.size() > 0) {
+ this.resultElements = new IJavaElement[results.size()];
+ results.toArray(this.resultElements);
+ if (delta != null) {
+ addDelta(delta);
+ }
}
+ } finally {
+ done();
}
- done();
}
/**
* Possible failures: <ul>
@@ -120,12 +125,14 @@
* @see JavaConventions
*/
public IJavaModelStatus verify() {
- if (getParentElement() == null) {
+ IJavaElement parentElement = getParentElement();
+ if (parentElement == null) {
return new JavaModelStatus(IJavaModelStatusConstants.NO_ELEMENTS_TO_PROCESS);
}
String packageName = this.pkgName == null ? null : Util.concatWith(this.pkgName, '.');
- if (this.pkgName == null || (this.pkgName.length > 0 && JavaConventions.validatePackageName(packageName).getSeverity() == IStatus.ERROR)) {
+ IJavaProject project = parentElement.getJavaProject();
+ if (this.pkgName == null || (this.pkgName.length > 0 && JavaConventions.validatePackageName(packageName, project.getOption(JavaCore.COMPILER_SOURCE, true), project.getOption(JavaCore.COMPILER_COMPLIANCE, true)).getSeverity() == IStatus.ERROR)) {
return new JavaModelStatus(IJavaModelStatusConstants.INVALID_NAME, packageName);
}
IPackageFragmentRoot root = (IPackageFragmentRoot) getParentElement();
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateTypeMemberOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateTypeMemberOperation.java
index bdf6a41..d5dc7fd 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateTypeMemberOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateTypeMemberOperation.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -30,7 +30,8 @@
import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
-import org.eclipse.jdt.internal.core.dom.rewrite.Indents;
+import org.eclipse.jdt.core.formatter.IndentManipulation;
+import org.eclipse.jdt.internal.compiler.parser.ScannerHelper;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.TextUtilities;
@@ -104,7 +105,7 @@
newSource.append(this.alteredName);
newSource.append(createdNodeSource.substring(nameEnd));
} else {
- // syntacticaly incorrect source
+ // syntactically incorrect source
int createdNodeStart = this.createdNode.getStartPosition();
int createdNodeEnd = createdNodeStart + this.createdNode.getLength();
newSource.append(createdNodeSource.substring(createdNodeStart, nameStart));
@@ -122,20 +123,20 @@
private String removeIndentAndNewLines(String code, IDocument document, ICompilationUnit cu) {
IJavaProject project = cu.getJavaProject();
Map options = project.getOptions(true/*inherit JavaCore options*/);
- int tabWidth = Indents.getTabWidth(options);
- int indentWidth = Indents.getIndentWidth(options, tabWidth);
- int indent = Indents.computeIndentUnits(code, tabWidth, indentWidth);
+ int tabWidth = IndentManipulation.getTabWidth(options);
+ int indentWidth = IndentManipulation.getIndentWidth(options);
+ int indent = IndentManipulation.measureIndentUnits(code, tabWidth, indentWidth);
int firstNonWhiteSpace = -1;
int length = code.length();
while (firstNonWhiteSpace < length-1)
- if (!Character.isWhitespace(code.charAt(++firstNonWhiteSpace)))
+ if (!ScannerHelper.isWhitespace(code.charAt(++firstNonWhiteSpace)))
break;
int lastNonWhiteSpace = length;
while (lastNonWhiteSpace > 0)
- if (!Character.isWhitespace(code.charAt(--lastNonWhiteSpace)))
+ if (!ScannerHelper.isWhitespace(code.charAt(--lastNonWhiteSpace)))
break;
String lineDelimiter = TextUtilities.getDefaultLineDelimiter(document);
- return Indents.changeIndent(code.substring(firstNonWhiteSpace, lastNonWhiteSpace+1), indent, tabWidth, indentWidth, "", lineDelimiter); //$NON-NLS-1$
+ return IndentManipulation.changeIndent(code.substring(firstNonWhiteSpace, lastNonWhiteSpace+1), indent, tabWidth, indentWidth, "", lineDelimiter); //$NON-NLS-1$
}
/*
* Renames the given node to the given name.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DefaultWorkingCopyOwner.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DefaultWorkingCopyOwner.java
index f9c8872..ff17445 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DefaultWorkingCopyOwner.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DefaultWorkingCopyOwner.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -28,9 +28,6 @@
// only one instance can be created
}
- /**
- * @deprecated Marked deprecated as it is using deprecated code
- */
public IBuffer createBuffer(ICompilationUnit workingCopy) {
if (this.primaryBufferProvider != null) return this.primaryBufferProvider.createBuffer(workingCopy);
return super.createBuffer(workingCopy);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeleteElementsOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeleteElementsOperation.java
index c4c99a7..2bcc349 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeleteElementsOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeleteElementsOperation.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -16,6 +16,7 @@
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
@@ -164,7 +165,7 @@
cu.save(getSubProgressMonitor(1), force);
if (!cu.isWorkingCopy()) { // if unit is working copy, then save will have already fired the delta
addDelta(delta);
- this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
+ setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
}
}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeletePackageFragmentRootOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeletePackageFragmentRootOperation.java
index 966bd67..c6be226 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeletePackageFragmentRootOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeletePackageFragmentRootOperation.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,6 +10,9 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core;
+import java.util.HashMap;
+import java.util.Map;
+
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
@@ -35,18 +38,23 @@
IPackageFragmentRoot root = (IPackageFragmentRoot)this.getElementToProcess();
IClasspathEntry rootEntry = root.getRawClasspathEntry();
+ // remember olds roots
+ DeltaProcessor deltaProcessor = JavaModelManager.getJavaModelManager().getDeltaProcessor();
+ if (deltaProcessor.oldRoots == null)
+ deltaProcessor.oldRoots = new HashMap();
+
+ // update classpath if needed
+ if ((updateModelFlags & IPackageFragmentRoot.ORIGINATING_PROJECT_CLASSPATH) != 0) {
+ updateProjectClasspath(rootEntry.getPath(), root.getJavaProject(), deltaProcessor.oldRoots);
+ }
+ if ((updateModelFlags & IPackageFragmentRoot.OTHER_REFERRING_PROJECTS_CLASSPATH) != 0) {
+ updateReferringProjectClasspaths(rootEntry.getPath(), root.getJavaProject(), deltaProcessor.oldRoots);
+ }
+
// delete resource
if (!root.isExternal() && (this.updateModelFlags & IPackageFragmentRoot.NO_RESOURCE_MODIFICATION) == 0) {
deleteResource(root, rootEntry);
}
-
- // update classpath if needed
- if ((this.updateModelFlags & IPackageFragmentRoot.ORIGINATING_PROJECT_CLASSPATH) != 0) {
- updateProjectClasspath(rootEntry.getPath(), root.getJavaProject());
- }
- if ((this.updateModelFlags & IPackageFragmentRoot.OTHER_REFERRING_PROJECTS_CLASSPATH) != 0) {
- updateReferringProjectClasspaths(rootEntry.getPath(), root.getJavaProject());
- }
}
protected void deleteResource(
@@ -87,28 +95,30 @@
throw new JavaModelException(e);
}
}
- this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
+ setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
}
/*
* Deletes the classpath entries equals to the given rootPath from all Java projects.
*/
- protected void updateReferringProjectClasspaths(IPath rootPath, IJavaProject projectOfRoot) throws JavaModelException {
+ protected void updateReferringProjectClasspaths(IPath rootPath, IJavaProject projectOfRoot, Map oldRoots) throws JavaModelException {
IJavaModel model = this.getJavaModel();
IJavaProject[] projects = model.getJavaProjects();
for (int i = 0, length = projects.length; i < length; i++) {
IJavaProject project = projects[i];
if (project.equals(projectOfRoot)) continue;
- updateProjectClasspath(rootPath, project);
+ updateProjectClasspath(rootPath, project, oldRoots);
}
}
/*
* Deletes the classpath entries equals to the given rootPath from the given project.
*/
- protected void updateProjectClasspath(IPath rootPath, IJavaProject project)
- throws JavaModelException {
+ protected void updateProjectClasspath(IPath rootPath, IJavaProject project, Map oldRoots) throws JavaModelException {
+ // remember old roots
+ oldRoots.put(project, project.getPackageFragmentRoots());
+
IClasspathEntry[] classpath = project.getRawClasspath();
IClasspathEntry[] newClasspath = null;
int cpLength = classpath.length;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeleteResourceElementsOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeleteResourceElementsOperation.java
index b036daf..7d0c7ae 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeleteResourceElementsOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeleteResourceElementsOperation.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessingState.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessingState.java
index 607b963..19f50c1 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessingState.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessingState.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -41,6 +41,7 @@
* Collection of pre Java resource change listeners
*/
public IResourceChangeListener[] preResourceChangeListeners = new IResourceChangeListener[1];
+ public int[] preResourceChangeEventMasks = new int[1];
public int preResourceChangeListenerCount = 0;
/*
@@ -48,18 +49,18 @@
*/
private ThreadLocal deltaProcessors = new ThreadLocal();
- /* A table from IPath (from a classpath entry) to RootInfo */
+ /* A table from IPath (from a classpath entry) to DeltaProcessor.RootInfo */
public HashMap roots = new HashMap();
- /* A table from IPath (from a classpath entry) to ArrayList of RootInfo
+ /* A table from IPath (from a classpath entry) to ArrayList of DeltaProcessor.RootInfo
* Used when an IPath corresponds to more than one root */
public HashMap otherRoots = new HashMap();
- /* A table from IPath (from a classpath entry) to RootInfo
+ /* A table from IPath (from a classpath entry) to DeltaProcessor.RootInfo
* from the last time the delta processor was invoked. */
public HashMap oldRoots = new HashMap();
- /* A table from IPath (from a classpath entry) to ArrayList of RootInfo
+ /* A table from IPath (from a classpath entry) to ArrayList of DeltaProcessor.RootInfo
* from the last time the delta processor was invoked.
* Used when an IPath corresponds to more than one root */
public HashMap oldOtherRoots = new HashMap();
@@ -76,104 +77,34 @@
/* Threads that are currently running initializeRoots() */
private Set initializingThreads = Collections.synchronizedSet(new HashSet());
+ /* A table from file system absoulte path (String) to timestamp (Long) */
public Hashtable externalTimeStamps;
- public HashMap projectUpdates = new HashMap();
+ /* A table from JavaProject to ClasspathValidation */
+ private HashMap classpathValidations = new HashMap();
+
+ /* A table from JavaProject to ProjectReferenceChange */
+ private HashMap projectReferenceChanges= new HashMap();
- public static class ProjectUpdateInfo {
- JavaProject project;
- IClasspathEntry[] oldResolvedPath;
- IClasspathEntry[] newResolvedPath;
- IClasspathEntry[] newRawPath;
-
- /**
- * Update projects references so that the build order is consistent with the classpath
- */
- public void updateProjectReferencesIfNecessary() throws JavaModelException {
-
- String[] oldRequired = this.project.projectPrerequisites(this.oldResolvedPath);
-
- if (this.newResolvedPath == null) {
- this.newResolvedPath = this.project.getResolvedClasspath(this.newRawPath, null, true, true, null/*no reverse map*/);
- }
- String[] newRequired = this.project.projectPrerequisites(this.newResolvedPath);
- try {
- IProject projectResource = this.project.getProject();
- IProjectDescription description = projectResource.getDescription();
-
- IProject[] projectReferences = description.getDynamicReferences();
-
- HashSet oldReferences = new HashSet(projectReferences.length);
- for (int i = 0; i < projectReferences.length; i++){
- String projectName = projectReferences[i].getName();
- oldReferences.add(projectName);
- }
- HashSet newReferences = (HashSet)oldReferences.clone();
-
- for (int i = 0; i < oldRequired.length; i++){
- String projectName = oldRequired[i];
- newReferences.remove(projectName);
- }
- for (int i = 0; i < newRequired.length; i++){
- String projectName = newRequired[i];
- newReferences.add(projectName);
- }
-
- Iterator iter;
- int newSize = newReferences.size();
-
- checkIdentity: {
- if (oldReferences.size() == newSize){
- iter = newReferences.iterator();
- while (iter.hasNext()){
- if (!oldReferences.contains(iter.next())){
- break checkIdentity;
- }
- }
- return;
- }
- }
- String[] requiredProjectNames = new String[newSize];
- int index = 0;
- iter = newReferences.iterator();
- while (iter.hasNext()){
- requiredProjectNames[index++] = (String)iter.next();
- }
- Util.sort(requiredProjectNames); // ensure that if changed, the order is consistent
-
- IProject[] requiredProjectArray = new IProject[newSize];
- IWorkspaceRoot wksRoot = projectResource.getWorkspace().getRoot();
- for (int i = 0; i < newSize; i++){
- requiredProjectArray[i] = wksRoot.getProject(requiredProjectNames[i]);
- }
- description.setDynamicReferences(requiredProjectArray);
- projectResource.setDescription(description, null);
-
- } catch(CoreException e){
- throw new JavaModelException(e);
- }
- }
- }
-
/**
* Workaround for bug 15168 circular errors not reported
* This is a cache of the projects before any project addition/deletion has started.
*/
- public IJavaProject[] modelProjectsCache;
+ private HashSet javaProjectNamesCache;
/*
* Need to clone defensively the listener information, in case some listener is reacting to some notification iteration by adding/changing/removing
* any of the other (for example, if it deregisters itself).
*/
- public void addElementChangedListener(IElementChangedListener listener, int eventMask) {
+ public synchronized void addElementChangedListener(IElementChangedListener listener, int eventMask) {
for (int i = 0; i < this.elementChangedListenerCount; i++){
- if (this.elementChangedListeners[i].equals(listener)){
+ if (this.elementChangedListeners[i] == listener){
// only clone the masks, since we could be in the middle of notifications and one listener decide to change
// any event mask of another listeners (yet not notified).
int cloneLength = this.elementChangedListenerMasks.length;
System.arraycopy(this.elementChangedListenerMasks, 0, this.elementChangedListenerMasks = new int[cloneLength], 0, cloneLength);
- this.elementChangedListenerMasks[i] = eventMask; // could be different
+ this.elementChangedListenerMasks[i] |= eventMask; // could be different
return;
}
}
@@ -188,18 +119,21 @@
this.elementChangedListenerCount++;
}
- public void addPreResourceChangedListener(IResourceChangeListener listener) {
+ public synchronized void addPreResourceChangedListener(IResourceChangeListener listener, int eventMask) {
for (int i = 0; i < this.preResourceChangeListenerCount; i++){
- if (this.preResourceChangeListeners[i].equals(listener)) {
+ if (this.preResourceChangeListeners[i] == listener) {
+ this.preResourceChangeEventMasks[i] |= eventMask;
return;
}
}
// may need to grow, no need to clone, since iterators will have cached original arrays and max boundary and we only add to the end.
int length;
- if ((length = this.preResourceChangeListeners.length) == this.preResourceChangeListenerCount){
+ if ((length = this.preResourceChangeListeners.length) == this.preResourceChangeListenerCount) {
System.arraycopy(this.preResourceChangeListeners, 0, this.preResourceChangeListeners = new IResourceChangeListener[length*2], 0, length);
+ System.arraycopy(this.preResourceChangeEventMasks, 0, this.preResourceChangeEventMasks = new int[length*2], 0, length);
}
this.preResourceChangeListeners[this.preResourceChangeListenerCount] = listener;
+ this.preResourceChangeEventMasks[this.preResourceChangeListenerCount] = eventMask;
this.preResourceChangeListenerCount++;
}
@@ -211,18 +145,21 @@
return deltaProcessor;
}
- public void performClasspathResourceChange(JavaProject project, IClasspathEntry[] oldResolvedPath, IClasspathEntry[] newResolvedPath, IClasspathEntry[] newRawPath, boolean canChangeResources) throws JavaModelException {
- ProjectUpdateInfo info = new ProjectUpdateInfo();
- info.project = project;
- info.oldResolvedPath = oldResolvedPath;
- info.newResolvedPath = newResolvedPath;
- info.newRawPath = newRawPath;
- if (canChangeResources) {
- this.projectUpdates.remove(project); // remove possibly awaiting one
- info.updateProjectReferencesIfNecessary();
- return;
+ public synchronized ClasspathValidation addClasspathValidation(JavaProject project) {
+ ClasspathValidation validation = (ClasspathValidation) this.classpathValidations.get(project);
+ if (validation == null) {
+ validation = new ClasspathValidation(project);
+ this.classpathValidations.put(project, validation);
}
- this.recordProjectUpdate(info);
+ return validation;
+ }
+
+ public synchronized void addProjectReferenceChange(JavaProject project, IClasspathEntry[] oldResolvedClasspath) {
+ ProjectReferenceChange change = (ProjectReferenceChange) this.projectReferenceChanges.get(project);
+ if (change == null) {
+ change = new ProjectReferenceChange(project, oldResolvedClasspath);
+ this.projectReferenceChanges.put(project, change);
+ }
}
public void initializeRoots() {
@@ -262,7 +199,7 @@
JavaProject project = (JavaProject) projects[i];
IClasspathEntry[] classpath;
try {
- classpath = project.getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/);
+ classpath = project.getResolvedClasspath();
} catch (JavaModelException e) {
// continue with next project
continue;
@@ -298,12 +235,11 @@
// source attachment path
if (entry.getEntryKind() != IClasspathEntry.CPE_LIBRARY) continue;
- QualifiedName qName = new QualifiedName(JavaCore.PLUGIN_ID, "sourceattachment: " + path.toOSString()); //$NON-NLS-1$;
String propertyString = null;
try {
- propertyString = ResourcesPlugin.getWorkspace().getRoot().getPersistentProperty(qName);
- } catch (CoreException e) {
- continue;
+ propertyString = Util.getSourceAttachmentProperty(path);
+ } catch (JavaModelException e) {
+ e.printStackTrace();
}
IPath sourceAttachmentPath;
if (propertyString != null) {
@@ -336,31 +272,29 @@
}
}
- public synchronized void recordProjectUpdate(ProjectUpdateInfo newInfo) {
-
- JavaProject project = newInfo.project;
- ProjectUpdateInfo oldInfo = (ProjectUpdateInfo) this.projectUpdates.get(project);
- if (oldInfo != null) { // refresh new classpath information
- oldInfo.newRawPath = newInfo.newRawPath;
- oldInfo.newResolvedPath = newInfo.newResolvedPath;
- } else {
- this.projectUpdates.put(project, newInfo);
- }
- }
- public synchronized ProjectUpdateInfo[] removeAllProjectUpdates() {
- int length = this.projectUpdates.size();
+ public synchronized ClasspathValidation[] removeClasspathValidations() {
+ int length = this.classpathValidations.size();
if (length == 0) return null;
- ProjectUpdateInfo[] updates = new ProjectUpdateInfo[length];
- this.projectUpdates.values().toArray(updates);
- this.projectUpdates.clear();
+ ClasspathValidation[] validations = new ClasspathValidation[length];
+ this.classpathValidations.values().toArray(validations);
+ this.classpathValidations.clear();
+ return validations;
+ }
+
+ public synchronized ProjectReferenceChange[] removeProjectReferenceChanges() {
+ int length = this.projectReferenceChanges.size();
+ if (length == 0) return null;
+ ProjectReferenceChange[] updates = new ProjectReferenceChange[length];
+ this.projectReferenceChanges.values().toArray(updates);
+ this.projectReferenceChanges.clear();
return updates;
}
- public void removeElementChangedListener(IElementChangedListener listener) {
+ public synchronized void removeElementChangedListener(IElementChangedListener listener) {
for (int i = 0; i < this.elementChangedListenerCount; i++){
- if (this.elementChangedListeners[i].equals(listener)){
+ if (this.elementChangedListeners[i] == listener){
// need to clone defensively since we might be in the middle of listener notifications (#fire)
int length = this.elementChangedListeners.length;
@@ -386,26 +320,30 @@
}
}
- public void removePreResourceChangedListener(IResourceChangeListener listener) {
+ public synchronized void removePreResourceChangedListener(IResourceChangeListener listener) {
for (int i = 0; i < this.preResourceChangeListenerCount; i++){
- if (this.preResourceChangeListeners[i].equals(listener)){
+ if (this.preResourceChangeListeners[i] == listener){
// need to clone defensively since we might be in the middle of listener notifications (#fire)
int length = this.preResourceChangeListeners.length;
IResourceChangeListener[] newListeners = new IResourceChangeListener[length];
+ int[] newEventMasks = new int[length];
System.arraycopy(this.preResourceChangeListeners, 0, newListeners, 0, i);
+ System.arraycopy(this.preResourceChangeEventMasks, 0, newEventMasks, 0, i);
// copy trailing listeners
int trailingLength = this.preResourceChangeListenerCount - i - 1;
- if (trailingLength > 0){
+ if (trailingLength > 0) {
System.arraycopy(this.preResourceChangeListeners, i+1, newListeners, i, trailingLength);
+ System.arraycopy(this.preResourceChangeEventMasks, i+1, newEventMasks, i, trailingLength);
}
// update manager listener state (#fire need to iterate over original listeners through a local variable to hold onto
// the original ones)
this.preResourceChangeListeners = newListeners;
+ this.preResourceChangeEventMasks = newEventMasks;
this.preResourceChangeListenerCount--;
return;
}
@@ -413,12 +351,11 @@
}
public void resourceChanged(final IResourceChangeEvent event) {
- boolean isPostChange = event.getType() == IResourceChangeEvent.POST_CHANGE;
- if (isPostChange) {
- for (int i = 0; i < this.preResourceChangeListenerCount; i++) {
- // wrap callbacks with Safe runnable for subsequent listeners to be called when some are causing grief
- final IResourceChangeListener listener = this.preResourceChangeListeners[i];
- Platform.run(new ISafeRunnable() {
+ for (int i = 0; i < this.preResourceChangeListenerCount; i++) {
+ // wrap callbacks with Safe runnable for subsequent listeners to be called when some are causing grief
+ final IResourceChangeListener listener = this.preResourceChangeListeners[i];
+ if ((this.preResourceChangeEventMasks[i] & event.getType()) != 0)
+ SafeRunner.run(new ISafeRunnable() {
public void handleException(Throwable exception) {
Util.log(exception, "Exception occurred in listener of pre Java resource change notification"); //$NON-NLS-1$
}
@@ -426,13 +363,12 @@
listener.resourceChanged(event);
}
});
- }
}
try {
getDeltaProcessor().resourceChanged(event);
} finally {
// TODO (jerome) see 47631, may want to get rid of following so as to reuse delta processor ?
- if (isPostChange) {
+ if (event.getType() == IResourceChangeEvent.POST_CHANGE) {
this.deltaProcessors.set(null);
}
}
@@ -469,6 +405,39 @@
return this.externalTimeStamps;
}
+ public IJavaProject findJavaProject(String name) {
+ if (getOldJavaProjecNames().contains(name))
+ return JavaModelManager.getJavaModelManager().getJavaModel().getJavaProject(name);
+ return null;
+ }
+
+ /*
+ * Workaround for bug 15168 circular errors not reported
+ * Returns the list of java projects before resource delta processing
+ * has started.
+ */
+ public synchronized HashSet getOldJavaProjecNames() {
+ if (this.javaProjectNamesCache == null) {
+ HashSet result = new HashSet();
+ IJavaProject[] projects;
+ try {
+ projects = JavaModelManager.getJavaModelManager().getJavaModel().getJavaProjects();
+ } catch (JavaModelException e) {
+ return this.javaProjectNamesCache;
+ }
+ for (int i = 0, length = projects.length; i < length; i++) {
+ IJavaProject project = projects[i];
+ result.add(project.getElementName());
+ }
+ return this.javaProjectNamesCache = result;
+ }
+ return this.javaProjectNamesCache;
+ }
+
+ public synchronized void resetOldJavaProjectNames() {
+ this.javaProjectNamesCache = null;
+ }
+
private File getTimeStampsFile() {
return JavaCore.getPlugin().getStateLocation().append("externalLibsTimeStamps").toFile(); //$NON-NLS-1$
}
@@ -480,11 +449,12 @@
try {
out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(timestamps)));
out.writeInt(this.externalTimeStamps.size());
- Iterator keys = this.externalTimeStamps.keySet().iterator();
- while (keys.hasNext()) {
- IPath key = (IPath) keys.next();
+ Iterator entries = this.externalTimeStamps.entrySet().iterator();
+ while (entries.hasNext()) {
+ Map.Entry entry = (Map.Entry) entries.next();
+ IPath key = (IPath) entry.getKey();
out.writeUTF(key.toPortableString());
- Long timestamp = (Long) this.externalTimeStamps.get(key);
+ Long timestamp = (Long) entry.getValue();
out.writeLong(timestamp.longValue());
}
} catch (IOException e) {
@@ -514,15 +484,19 @@
updatedRoots = this.roots;
otherUpdatedRoots = this.otherRoots;
}
- Iterator iterator = updatedRoots.keySet().iterator();
+ int containerSegmentCount = containerPath.segmentCount();
+ boolean containerIsProject = containerSegmentCount == 1;
+ Iterator iterator = updatedRoots.entrySet().iterator();
while (iterator.hasNext()) {
- IPath path = (IPath)iterator.next();
+ Map.Entry entry = (Map.Entry) iterator.next();
+ IPath path = (IPath) entry.getKey();
if (containerPath.isPrefixOf(path) && !containerPath.equals(path)) {
- IResourceDelta rootDelta = containerDelta.findMember(path.removeFirstSegments(1));
+ IResourceDelta rootDelta = containerDelta.findMember(path.removeFirstSegments(containerSegmentCount));
if (rootDelta == null) continue;
- DeltaProcessor.RootInfo rootInfo = (DeltaProcessor.RootInfo)updatedRoots.get(path);
+ DeltaProcessor.RootInfo rootInfo = (DeltaProcessor.RootInfo) entry.getValue();
- if (!rootInfo.project.getPath().isPrefixOf(path)) { // only consider roots that are not included in the container
+ if (!containerIsProject
+ || !rootInfo.project.getPath().isPrefixOf(path)) { // only consider folder roots that are not included in the container
deltaProcessor.updateCurrentDeltaAndIndex(rootDelta, IJavaElement.PACKAGE_FRAGMENT_ROOT, rootInfo);
}
@@ -531,7 +505,8 @@
Iterator otherProjects = rootList.iterator();
while (otherProjects.hasNext()) {
rootInfo = (DeltaProcessor.RootInfo)otherProjects.next();
- if (!rootInfo.project.getPath().isPrefixOf(path)) { // only consider roots that are not included in the container
+ if (!containerIsProject
+ || !rootInfo.project.getPath().isPrefixOf(path)) { // only consider folder roots that are not included in the container
deltaProcessor.updateCurrentDeltaAndIndex(rootDelta, IJavaElement.PACKAGE_FRAGMENT_ROOT, rootInfo);
}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java
index 3b0356c..9965ee6 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -20,13 +20,13 @@
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
-import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.*;
import org.eclipse.jdt.core.*;
import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.SourceElementParser;
import org.eclipse.jdt.internal.core.builder.JavaBuilder;
import org.eclipse.jdt.internal.core.hierarchy.TypeHierarchy;
import org.eclipse.jdt.internal.core.search.AbstractSearchScope;
@@ -39,6 +39,20 @@
* <code>IResourceDelta</code>s into <code>IJavaElementDelta</code>s.
* It also does some processing on the <code>JavaElement</code>s involved
* (e.g. closing them or updating classpaths).
+ * <p>
+ * High level summary of what the delta processor does:
+ * <ul>
+ * <li>reacts to resource deltas</li>
+ * <li>fires corresponding Java element deltas</li>
+ * <li>deltas also contain non-Java resources changes</li>
+ * <li>updates the model to reflect the Java element changes</li>
+ * <li>notifies type hierarchies of the changes</li>
+ * <li>triggers indexing of the changed elements</li>
+ * <li>refresh external archives (delta, model update, indexing)</li>
+ * <li>is thread safe (one delta processor instance per thread, see DeltaProcessingState#resourceChanged(...))</li>
+ * <li>handles .classpath changes (updates package fragment roots, update project references, validate classpath (.classpath format,
+ * resolved classpath, cycles))</li>
+ * </ul>
*/
public class DeltaProcessor {
@@ -218,7 +232,7 @@
private final ModelUpdater modelUpdater = new ModelUpdater();
/* A set of IJavaProject whose caches need to be reset */
- private HashSet projectCachesToReset = new HashSet();
+ public HashSet projectCachesToReset = new HashSet();
/*
* A list of IJavaElement used as a scope for external archives refresh during POST_CHANGE.
@@ -229,7 +243,7 @@
/* A table from IJavaProject to an array of IPackageFragmentRoot.
* This table contains the pkg fragment roots of the project that are being deleted.
*/
- public Map removedRoots;
+ public Map oldRoots;
/* A set of IJavaProject whose package fragment roots need to be refreshed */
private HashSet rootsToRefresh = new HashSet();
@@ -238,11 +252,37 @@
* Type of event that should be processed no matter what the real event type is.
*/
public int overridenEventType = -1;
-
+
+ /*
+ * Cache SourceElementParser for the project being visited
+ */
+ private SourceElementParser sourceElementParserCache;
+
+ /*
+ * Map from IProject to ClasspathChange
+ */
+ public HashMap classpathChanges = new HashMap();
+
public DeltaProcessor(DeltaProcessingState state, JavaModelManager manager) {
this.state = state;
this.manager = manager;
}
+
+ public ClasspathChange addClasspathChange(IProject project, IClasspathEntry[] oldRawClasspath, IPath oldOutputLocation, IClasspathEntry[] oldResolvedClasspath) {
+ ClasspathChange change = (ClasspathChange) this.classpathChanges.get(project);
+ if (change == null) {
+ change = new ClasspathChange((JavaProject) this.manager.getJavaModel().getJavaProject(project), oldRawClasspath, oldOutputLocation, oldResolvedClasspath);
+ this.classpathChanges.put(project, change);
+ } else {
+ if (change.oldRawClasspath == null)
+ change.oldRawClasspath = oldRawClasspath;
+ if (change.oldOutputLocation == null)
+ change.oldOutputLocation = oldOutputLocation;
+ if (change.oldResolvedClasspath == null)
+ change.oldResolvedClasspath = oldResolvedClasspath;
+ }
+ return change;
+ }
/*
* Adds the dependents of the given project to the list of the projects
@@ -294,25 +334,28 @@
* Also triggers index updates
*/
public void checkExternalArchiveChanges(IJavaElement[] elementsToRefresh, IProgressMonitor monitor) throws JavaModelException {
+ if (monitor != null && monitor.isCanceled())
+ throw new OperationCanceledException();
try {
+ if (monitor != null) monitor.beginTask("", 1); //$NON-NLS-1$
+
for (int i = 0, length = elementsToRefresh.length; i < length; i++) {
this.addForRefresh(elementsToRefresh[i]);
}
boolean hasDelta = this.createExternalArchiveDelta(monitor);
- if (monitor != null && monitor.isCanceled()) return;
if (hasDelta){
// force classpath marker refresh of affected projects
JavaModel.flushExternalFileCache();
+
+ // flush jar type cache
+ JavaModelManager.getJavaModelManager().resetJarTypeCache();
+
IJavaElementDelta[] projectDeltas = this.currentDelta.getAffectedChildren();
final int length = projectDeltas.length;
final IProject[] projectsToTouch = new IProject[length];
for (int i = 0; i < length; i++) {
IJavaElementDelta delta = projectDeltas[i];
JavaProject javaProject = (JavaProject)delta.getElement();
- javaProject.getResolvedClasspath(
- true/*ignoreUnresolvedEntry*/,
- true/*generateMarkerOnError*/,
- false/*don't returnResolutionInProgress*/);
projectsToTouch[i] = javaProject.getProject();
}
@@ -355,19 +398,13 @@
*/
private void checkProjectsBeingAddedOrRemoved(IResourceDelta delta) {
IResource resource = delta.getResource();
- boolean processChildren = false;
-
+ IResourceDelta[] children = null;
+
switch (resource.getType()) {
case IResource.ROOT :
// workaround for bug 15168 circular errors not reported
- if (this.state.modelProjectsCache == null) {
- try {
- this.state.modelProjectsCache = this.manager.getJavaModel().getJavaProjects();
- } catch (JavaModelException e) {
- // java model doesn't exist: never happens
- }
- }
- processChildren = true;
+ this.state.getOldJavaProjecNames(); // force list to be computed
+ children = delta.getAffectedChildren();
break;
case IResource.PROJECT :
// NB: No need to check project's nature as if the project is not a java project:
@@ -380,12 +417,16 @@
this.manager.batchContainerInitializations = true;
// remember project and its dependents
- this.addToRootsToRefreshWithDependents(javaProject);
+ addToRootsToRefreshWithDependents(javaProject);
// workaround for bug 15168 circular errors not reported
if (JavaProject.hasJavaNature(project)) {
- this.addToParentInfo(javaProject);
+ addToParentInfo(javaProject);
+ readRawClasspath(javaProject);
+ // ensure project references are updated (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=121569)
+ checkProjectReferenceChange(project, javaProject);
}
+
this.state.rootsAreStale = true;
break;
@@ -394,12 +435,15 @@
this.manager.batchContainerInitializations = true;
// project opened or closed: remember project and its dependents
- this.addToRootsToRefreshWithDependents(javaProject);
+ addToRootsToRefreshWithDependents(javaProject);
// workaround for bug 15168 circular errors not reported
if (project.isOpen()) {
if (JavaProject.hasJavaNature(project)) {
- this.addToParentInfo(javaProject);
+ addToParentInfo(javaProject);
+ readRawClasspath(javaProject);
+ // ensure project references are updated
+ checkProjectReferenceChange(project, javaProject);
}
} else {
try {
@@ -409,12 +453,13 @@
}
this.removeFromParentInfo(javaProject);
this.manager.removePerProjectInfo(javaProject);
+ this.manager.containerRemove(javaProject);
}
this.state.rootsAreStale = true;
} else if ((delta.getFlags() & IResourceDelta.DESCRIPTION) != 0) {
- boolean wasJavaProject = this.manager.getJavaModel().findJavaProject(project) != null;
+ boolean wasJavaProject = this.state.findJavaProject(project.getName()) != null;
boolean isJavaProject = JavaProject.hasJavaNature(project);
- if (wasJavaProject != isJavaProject) {
+ if (wasJavaProject != isJavaProject) {
this.manager.batchContainerInitializations = true;
// java nature added or removed: remember project and its dependents
@@ -423,9 +468,14 @@
// workaround for bug 15168 circular errors not reported
if (isJavaProject) {
this.addToParentInfo(javaProject);
+ readRawClasspath(javaProject);
+ // ensure project references are updated (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=172666)
+ checkProjectReferenceChange(project, javaProject);
} else {
// remove classpath cache so that initializeRoots() will not consider the project has a classpath
- this.manager.removePerProjectInfo((JavaProject)JavaCore.create(project));
+ this.manager.removePerProjectInfo(javaProject);
+ // remove container cache for this project
+ this.manager.containerRemove(javaProject);
// close project
try {
javaProject.close();
@@ -439,7 +489,7 @@
// in case the project was removed then added then changed (see bug 19799)
if (isJavaProject) { // need nature check - 18698
this.addToParentInfo(javaProject);
- processChildren = true;
+ children = delta.getAffectedChildren();
}
}
} else {
@@ -447,16 +497,19 @@
// in case the project was removed then added then changed
if (JavaProject.hasJavaNature(project)) { // need nature check - 18698
this.addToParentInfo(javaProject);
- processChildren = true;
+ children = delta.getAffectedChildren();
}
}
break;
-
+
case IResourceDelta.REMOVED :
this.manager.batchContainerInitializations = true;
-
+
// remove classpath cache so that initializeRoots() will not consider the project has a classpath
- this.manager.removePerProjectInfo((JavaProject)JavaCore.create(resource));
+ this.manager.removePerProjectInfo(javaProject);
+ // remove container cache for this project
+ this.manager.containerRemove(javaProject);
+
this.state.rootsAreStale = true;
break;
}
@@ -470,19 +523,54 @@
/* classpath file change */
if (file.getName().equals(JavaProject.CLASSPATH_FILENAME)) {
this.manager.batchContainerInitializations = true;
- reconcileClasspathFileUpdate(delta, (JavaProject)JavaCore.create(file.getProject()));
+ switch (delta.getKind()) {
+ case IResourceDelta.CHANGED :
+ int flags = delta.getFlags();
+ if ((flags & IResourceDelta.CONTENT) == 0 // only consider content change
+ && (flags & IResourceDelta.ENCODING) == 0 // and encoding change
+ && (flags & IResourceDelta.MOVED_FROM) == 0) {// and also move and overide scenario (see http://dev.eclipse.org/bugs/show_bug.cgi?id=21420)
+ break;
+ }
+ // fall through
+ case IResourceDelta.ADDED :
+ javaProject = (JavaProject)JavaCore.create(file.getProject());
+
+ // force to (re)read the .classpath file
+ try {
+ javaProject.getPerProjectInfo().readAndCacheClasspath(javaProject);
+ } catch (JavaModelException e) {
+ // project doesn't exist
+ return;
+ }
+ break;
+ }
this.state.rootsAreStale = true;
}
break;
}
- if (processChildren) {
- IResourceDelta[] children = delta.getAffectedChildren();
+ if (children != null) {
for (int i = 0; i < children.length; i++) {
checkProjectsBeingAddedOrRemoved(children[i]);
}
}
}
+
+ private void checkProjectReferenceChange(IProject project, JavaProject javaProject) {
+ ClasspathChange change = (ClasspathChange) this.classpathChanges.get(project);
+ this.state.addProjectReferenceChange(javaProject, change == null ? null : change.oldResolvedClasspath);
+ }
+
+ private void readRawClasspath(JavaProject javaProject) {
+ try {
+ // force to (re)read the .classpath file
+ javaProject.getPerProjectInfo().readAndCacheClasspath(javaProject);
+ } catch (JavaModelException e) {
+ if (VERBOSE) {
+ e.printStackTrace();
+ }
+ }
+ }
private void checkSourceAttachmentChange(IResourceDelta delta, IResource res) {
IPath rootPath = (IPath)this.state.sourceAttachments.get(res.getFullPath());
if (rootPath != null) {
@@ -551,6 +639,9 @@
int flags = IJavaElementDelta.F_CONTENT;
if (element instanceof JarPackageFragmentRoot){
flags |= IJavaElementDelta.F_ARCHIVE_CONTENT_CHANGED;
+ // need also to reset project cache otherwise it will be out-of-date
+ // see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=162621
+ this.projectCachesToReset.add(element.getJavaProject());
}
if (isPrimary) {
flags |= IJavaElementDelta.F_PRIMARY_RESOURCE;
@@ -592,7 +683,7 @@
} else {
// java project may have been been closed or removed (look for
// element amongst old java project s list).
- element = (Openable) this.manager.getJavaModel().findJavaProject(proj);
+ element = this.state.findJavaProject(proj.getName());
}
}
break;
@@ -701,14 +792,14 @@
archivePathsToRefresh.add(element.getPath());
break;
case IJavaElement.JAVA_PROJECT :
- JavaProject project = (JavaProject) element;
- if (!JavaProject.hasJavaNature(project.getProject())) {
+ JavaProject javaProject = (JavaProject) element;
+ if (!JavaProject.hasJavaNature(javaProject.getProject())) {
// project is not accessible or has lost its Java nature
break;
}
IClasspathEntry[] classpath;
try {
- classpath = project.getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/);
+ classpath = javaProject.getResolvedClasspath();
for (int j = 0, cpLength = classpath.length; j < cpLength; j++){
if (classpath[j].getEntryKind() == IClasspathEntry.CPE_LIBRARY){
archivePathsToRefresh.add(classpath[j].getPath());
@@ -719,21 +810,17 @@
}
break;
case IJavaElement.JAVA_MODEL :
- IJavaProject[] projects;
- try {
- projects = this.manager.getJavaModel().getOldJavaProjectsList();
- } catch (JavaModelException e1) {
- // cannot retrieve old projects list -> ignore
- continue;
- }
- for (int j = 0, projectsLength = projects.length; j < projectsLength; j++){
- project = (JavaProject) projects[j];
- if (!JavaProject.hasJavaNature(project.getProject())) {
+ Iterator projectNames = this.state.getOldJavaProjecNames().iterator();
+ while (projectNames.hasNext()) {
+ String projectName = (String) projectNames.next();
+ IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
+ if (!JavaProject.hasJavaNature(project)) {
// project is not accessible or has lost its Java nature
continue;
}
+ javaProject = (JavaProject) JavaCore.create(project);
try {
- classpath = project.getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/);
+ classpath = javaProject.getResolvedClasspath();
} catch (JavaModelException e2) {
// project doesn't exist -> ignore
continue;
@@ -749,26 +836,22 @@
}
// perform refresh
- IJavaProject[] projects;
- try {
- projects = this.manager.getJavaModel().getOldJavaProjectsList();
- } catch (JavaModelException e) {
- // cannot retrieve old projects list -> give up
- return false;
- }
+ Iterator projectNames = this.state.getOldJavaProjecNames().iterator();
IWorkspaceRoot wksRoot = ResourcesPlugin.getWorkspace().getRoot();
- for (int i = 0, length = projects.length; i < length; i++) {
+ while (projectNames.hasNext()) {
if (monitor != null && monitor.isCanceled()) break;
- JavaProject project = (JavaProject) projects[i];
- if (!JavaProject.hasJavaNature(project.getProject())) {
+ String projectName = (String) projectNames.next();
+ IProject project = wksRoot.getProject(projectName);
+ if (!JavaProject.hasJavaNature(project)) {
// project is not accessible or has lost its Java nature
continue;
}
+ JavaProject javaProject = (JavaProject) JavaCore.create(project);
IClasspathEntry[] entries;
try {
- entries = project.getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/);
+ entries = javaProject.getResolvedClasspath();
} catch (JavaModelException e1) {
// project does not exist -> ignore
continue;
@@ -836,25 +919,27 @@
status = (String)externalArchivesStatus.get(entryPath);
if (status != null){
if (status == EXTERNAL_JAR_ADDED){
- PackageFragmentRoot root = (PackageFragmentRoot)project.getPackageFragmentRoot(entryPath.toString());
+ PackageFragmentRoot root = (PackageFragmentRoot) javaProject.getPackageFragmentRoot(entryPath.toString());
if (VERBOSE){
System.out.println("- External JAR ADDED, affecting root: "+root.getElementName()); //$NON-NLS-1$
}
elementAdded(root, null, null);
+ this.state.addClasspathValidation(javaProject); // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=185733
hasDelta = true;
} else if (status == EXTERNAL_JAR_CHANGED) {
- PackageFragmentRoot root = (PackageFragmentRoot)project.getPackageFragmentRoot(entryPath.toString());
+ PackageFragmentRoot root = (PackageFragmentRoot) javaProject.getPackageFragmentRoot(entryPath.toString());
if (VERBOSE){
System.out.println("- External JAR CHANGED, affecting root: "+root.getElementName()); //$NON-NLS-1$
}
contentChanged(root);
hasDelta = true;
} else if (status == EXTERNAL_JAR_REMOVED) {
- PackageFragmentRoot root = (PackageFragmentRoot)project.getPackageFragmentRoot(entryPath.toString());
+ PackageFragmentRoot root = (PackageFragmentRoot) javaProject.getPackageFragmentRoot(entryPath.toString());
if (VERBOSE){
System.out.println("- External JAR REMOVED, affecting root: "+root.getElementName()); //$NON-NLS-1$
}
elementRemoved(root, null, null);
+ this.state.addClasspathValidation(javaProject); // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=185733
hasDelta = true;
}
}
@@ -882,17 +967,17 @@
JavaProject javaProject = (JavaProject)JavaCore.create(project);
// remember roots of this project
- if (this.removedRoots == null) {
- this.removedRoots = new HashMap();
+ if (this.oldRoots == null) {
+ this.oldRoots = new HashMap();
}
if (javaProject.isOpen()) {
- this.removedRoots.put(javaProject, javaProject.getPackageFragmentRoots());
+ this.oldRoots.put(javaProject, javaProject.getPackageFragmentRoots());
} else {
// compute roots without opening project
- this.removedRoots.put(
+ this.oldRoots.put(
javaProject,
javaProject.computePackageFragmentRoots(
- javaProject.getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/),
+ javaProject.getResolvedClasspath(),
false,
null /*no reverse map*/));
}
@@ -900,9 +985,8 @@
javaProject.close();
// workaround for bug 15168 circular errors not reported
- if (this.state.modelProjectsCache == null) {
- this.state.modelProjectsCache = this.manager.getJavaModel().getJavaProjects();
- }
+ this.state.getOldJavaProjecNames(); // foce list to be computed
+
this.removeFromParentInfo(javaProject);
// remove preferences from per project info
@@ -933,6 +1017,17 @@
Openable movedFromElement = (Openable)element.getJavaModel().getJavaProject(delta.getMovedFromPath().lastSegment());
currentDelta().movedTo(element, movedFromElement);
} else {
+ // Force the project to be closed as it might have been opened
+ // before the resource modification came in and it might have a new child
+ // For example, in an IWorkspaceRunnable:
+ // 1. create a Java project P (where P=src)
+ // 2. open project P
+ // 3. add folder f in P's pkg fragment root
+ // When the resource delta comes in, only the addition of P is notified,
+ // but the pkg fragment root of project P is already opened, thus its children are not recomputed
+ // and it appears to contain only the default package.
+ close(element);
+
currentDelta().added(element);
}
this.state.updateRoots(element.getPath(), delta, this);
@@ -1152,17 +1247,26 @@
return NON_JAVA_RESOURCE;
}
if (res.getType() == IResource.FOLDER) {
- if (Util.isValidFolderNameForPackage(res.getName())) {
+ if (parentType == NON_JAVA_RESOURCE && !Util.isExcluded(res.getParent(), rootInfo.inclusionPatterns, rootInfo.exclusionPatterns)) {
+ // parent is a non-Java resource because it doesn't have a valid package name (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=130982)
+ return NON_JAVA_RESOURCE;
+ }
+ String sourceLevel = rootInfo.project == null ? null : rootInfo.project.getOption(JavaCore.COMPILER_SOURCE, true);
+ String complianceLevel = rootInfo.project == null ? null : rootInfo.project.getOption(JavaCore.COMPILER_COMPLIANCE, true);
+ if (Util.isValidFolderNameForPackage(res.getName(), sourceLevel, complianceLevel)) {
return IJavaElement.PACKAGE_FRAGMENT;
}
return NON_JAVA_RESOURCE;
}
String fileName = res.getName();
- if (Util.isValidCompilationUnitName(fileName)) {
+ String sourceLevel = rootInfo.project == null ? null : rootInfo.project.getOption(JavaCore.COMPILER_SOURCE, true);
+ String complianceLevel = rootInfo.project == null ? null : rootInfo.project.getOption(JavaCore.COMPILER_COMPLIANCE, true);
+ if (Util.isValidCompilationUnitName(fileName, sourceLevel, complianceLevel)) {
return IJavaElement.COMPILATION_UNIT;
- } else if (Util.isValidClassFileName(fileName)) {
+ } else if (Util.isValidClassFileName(fileName, sourceLevel, complianceLevel)) {
return IJavaElement.CLASS_FILE;
- } else if (this.rootInfo(res.getFullPath(), kind) != null) {
+ } else if ((rootInfo = this.rootInfo(res.getFullPath(), kind)) != null
+ && rootInfo.project.getProject().getFullPath().isPrefixOf(res.getFullPath()) /*ensure root is a root of its project (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=185310) */) {
// case of proj=src=bin and resource is a jar file on the classpath
return IJavaElement.PACKAGE_FRAGMENT_ROOT;
} else {
@@ -1179,16 +1283,11 @@
public void flush() {
this.javaModelDeltas = new ArrayList();
}
- /* Returns the list of Java projects in the workspace.
- *
- */
- IJavaProject[] getJavaProjects() {
- try {
- return this.manager.getJavaModel().getJavaProjects();
- } catch (JavaModelException e) {
- // java model doesn't exist
- return new IJavaProject[0];
- }
+
+ private SourceElementParser getSourceElementParser(Openable element) {
+ if (this.sourceElementParserCache == null)
+ this.sourceElementParserCache = this.manager.indexManager.getSourceElementParser(element.getJavaProject(), null/*requestor will be set by indexer*/);
+ return this.sourceElementParserCache;
}
/*
* Finds the root info this path is included in.
@@ -1236,9 +1335,14 @@
// Important: if any listener reacts to notification by updating the listeners list or mask, these lists will
// be duplicated, so it is necessary to remember original lists in a variable (since field values may change under us)
- IElementChangedListener[] listeners = this.state.elementChangedListeners;
- int[] listenerMask = this.state.elementChangedListenerMasks;
- int listenerCount = this.state.elementChangedListenerCount;
+ IElementChangedListener[] listeners;
+ int[] listenerMask;
+ int listenerCount;
+ synchronized (this.state) {
+ listeners = this.state.elementChangedListeners;
+ listenerMask = this.state.elementChangedListenerMasks;
+ listenerCount = this.state.elementChangedListenerCount;
+ }
switch (eventType) {
case DEFAULT_CHANGE_EVENT:
@@ -1267,6 +1371,9 @@
// flush now so as to keep listener reactions to post their own deltas for subsequent iteration
this.flush();
+ // mark the operation stack has not modifying resources since resource deltas are being fired
+ JavaModelOperation.setAttribute(JavaModelOperation.HAS_MODIFIED_RESOURCE_ATTR, null);
+
notifyListeners(deltaToNotify, ElementChangedEvent.POST_CHANGE, listeners, listenerMask, listenerCount);
}
}
@@ -1341,8 +1448,11 @@
* Returns whether the given resource is in one of the given output folders and if
* it is filtered out from this output folder.
*/
- private boolean isResFilteredFromOutput(OutputsInfo info, IResource res, int elementType) {
+ private boolean isResFilteredFromOutput(RootInfo rootInfo, OutputsInfo info, IResource res, int elementType) {
if (info != null) {
+ JavaProject javaProject = null;
+ String sourceLevel = null;
+ String complianceLevel = null;
IPath resPath = res.getFullPath();
for (int i = 0; i < info.outputCount; i++) {
if (info.paths[i].isPrefixOf(resPath)) {
@@ -1353,10 +1463,20 @@
}
// case of .class file under project and no source folder
// proj=bin
- if (elementType == IJavaElement.JAVA_PROJECT
- && res instanceof IFile
- && Util.isValidClassFileName(res.getName())) {
- return true;
+ if (elementType == IJavaElement.JAVA_PROJECT && res instanceof IFile) {
+ if (sourceLevel == null) {
+ // Get java project to use its source and compliance levels
+ javaProject = rootInfo == null ?
+ (JavaProject)this.createElement(res.getProject(), IJavaElement.JAVA_PROJECT, null) :
+ rootInfo.project;
+ if (javaProject != null) {
+ sourceLevel = javaProject.getOption(JavaCore.COMPILER_SOURCE, true);
+ complianceLevel = javaProject.getOption(JavaCore.COMPILER_COMPLIANCE, true);
+ }
+ }
+ if (Util.isValidClassFileName(res.getName(), sourceLevel, complianceLevel)) {
+ return true;
+ }
}
} else {
return true;
@@ -1419,7 +1539,7 @@
start = System.currentTimeMillis();
}
// wrap callbacks with Safe runnable for subsequent listeners to be called when some are causing grief
- Platform.run(new ISafeRunnable() {
+ SafeRunner.run(new ISafeRunnable() {
public void handleException(Throwable exception) {
Util.log(exception, "Exception occurred in listener of Java element change notification"); //$NON-NLS-1$
}
@@ -1447,7 +1567,7 @@
if (!(listener instanceof TypeHierarchy)) continue;
// wrap callbacks with Safe runnable for subsequent listeners to be called when some are causing grief
- Platform.run(new ISafeRunnable() {
+ SafeRunner.run(new ISafeRunnable() {
public void handleException(Throwable exception) {
Util.log(exception, "Exception occurred in listener of Java element change notification"); //$NON-NLS-1$
}
@@ -1530,7 +1650,7 @@
if (proj.getProject().getFullPath().equals(projectOutput)){ // case of proj==bin==src
return new OutputsInfo(new IPath[] {projectOutput}, new int[] {SOURCE}, 1);
}
- IClasspathEntry[] classpath = proj.getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/);
+ IClasspathEntry[] classpath = proj.getResolvedClasspath();
IPath[] outputs = new IPath[classpath.length+1];
int[] traverseModes = new int[classpath.length+1];
int outputCount = 1;
@@ -1620,7 +1740,7 @@
RootInfo rootInfo = null;
int elementType;
IProject proj = (IProject)res;
- boolean wasJavaProject = this.manager.getJavaModel().findJavaProject(proj) != null;
+ boolean wasJavaProject = this.state.findJavaProject(proj.getName()) != null;
boolean isJavaProject = JavaProject.hasJavaNature(proj);
if (!wasJavaProject && !isJavaProject) {
elementType = NON_JAVA_RESOURCE;
@@ -1658,52 +1778,15 @@
}
}
/*
- * Update the JavaModel according to a .classpath file change. The file can have changed as a result of a previous
- * call to JavaProject#setRawClasspath or as a result of some user update (through repository)
- */
- private void reconcileClasspathFileUpdate(IResourceDelta delta, JavaProject project) {
-
- switch (delta.getKind()) {
- case IResourceDelta.REMOVED : // recreate one based on in-memory classpath
-// try {
-// JavaModelManager.PerProjectInfo info = project.getPerProjectInfo();
-// if (info.rawClasspath != null) { // if there is an in-memory classpath
-// project.saveClasspath(info.rawClasspath, info.outputLocation);
-// }
-// } catch (JavaModelException e) {
-// if (project.getProject().isAccessible()) {
-// Util.log(e, "Could not save classpath for "+ project.getPath()); //$NON-NLS-1$
-// }
-// }
- break;
- case IResourceDelta.CHANGED :
- int flags = delta.getFlags();
- if ((flags & IResourceDelta.CONTENT) == 0 // only consider content change
- && (flags & IResourceDelta.ENCODING) == 0 // and encoding change
- && (flags & IResourceDelta.MOVED_FROM) == 0) {// and also move and overide scenario (see http://dev.eclipse.org/bugs/show_bug.cgi?id=21420)
- break;
- }
- // fall through
- case IResourceDelta.ADDED :
- try {
- project.forceClasspathReload(null);
- } catch (RuntimeException e) {
- if (VERBOSE) {
- e.printStackTrace();
- }
- } catch (JavaModelException e) {
- if (VERBOSE) {
- e.printStackTrace();
- }
- }
- }
- }
-
- /*
* Traverse the set of projects which have changed namespace, and reset their
* caches and their dependents
*/
- private void resetProjectCaches() {
+ public void resetProjectCaches() {
+ if (this.projectCachesToReset.size() == 0)
+ return;
+
+ JavaModelManager.getJavaModelManager().resetJarTypeCache();
+
Iterator iterator = this.projectCachesToReset.iterator();
HashMap projectDepencies = this.state.projectDependencies;
HashSet affectedDependents = new HashSet();
@@ -1762,76 +1845,130 @@
* @see IResource
*/
public void resourceChanged(IResourceChangeEvent event) {
-
- if (event.getSource() instanceof IWorkspace) {
- int eventType = this.overridenEventType == -1 ? event.getType() : this.overridenEventType;
- IResource resource = event.getResource();
- IResourceDelta delta = event.getDelta();
-
- switch(eventType){
- case IResourceChangeEvent.PRE_DELETE :
- try {
- if(resource.getType() == IResource.PROJECT
- && ((IProject) resource).hasNature(JavaCore.NATURE_ID)) {
-
- deleting((IProject)resource);
- }
- } catch(CoreException e){
- // project doesn't exist or is not open: ignore
- }
- return;
-
- case IResourceChangeEvent.POST_CHANGE :
- if (isAffectedBy(delta)) { // avoid populating for SYNC or MARKER deltas
- try {
- try {
- stopDeltas();
- checkProjectsBeingAddedOrRemoved(delta);
- if (this.refreshedElements != null) {
- createExternalArchiveDelta(null);
- }
- IJavaElementDelta translatedDelta = processResourceDelta(delta);
- if (translatedDelta != null) {
- registerJavaModelDelta(translatedDelta);
- }
- } finally {
- startDeltas();
- }
- notifyTypeHierarchies(this.state.elementChangedListeners, this.state.elementChangedListenerCount);
- fire(null, ElementChangedEvent.POST_CHANGE);
- } finally {
- // workaround for bug 15168 circular errors not reported
- this.state.modelProjectsCache = null;
- this.removedRoots = null;
- }
- }
- return;
-
- case IResourceChangeEvent.PRE_BUILD :
- DeltaProcessingState.ProjectUpdateInfo[] updates = this.state.removeAllProjectUpdates();
- if (updates != null) {
- for (int i = 0, length = updates.length; i < length; i++) {
- try {
- updates[i].updateProjectReferencesIfNecessary();
- } catch(JavaModelException e) {
- // do nothing
- }
- }
- }
- // this.processPostChange = false;
- if(isAffectedBy(delta)) { // avoid populating for SYNC or MARKER deltas
- updateClasspathMarkers(delta);
- JavaBuilder.buildStarting();
- }
- // does not fire any deltas
- return;
- case IResourceChangeEvent.POST_BUILD :
- JavaBuilder.buildFinished();
- return;
- }
+ int eventType = this.overridenEventType == -1 ? event.getType() : this.overridenEventType;
+ IResource resource = event.getResource();
+ IResourceDelta delta = event.getDelta();
+
+ switch(eventType){
+ case IResourceChangeEvent.PRE_DELETE :
+ try {
+ if(resource.getType() == IResource.PROJECT
+ && ((IProject) resource).hasNature(JavaCore.NATURE_ID)) {
+
+ deleting((IProject)resource);
+ }
+ } catch(CoreException e){
+ // project doesn't exist or is not open: ignore
+ }
+ return;
+
+ case IResourceChangeEvent.POST_CHANGE :
+ if (isAffectedBy(delta)) { // avoid populating for SYNC or MARKER deltas
+ try {
+ try {
+ stopDeltas();
+ checkProjectsBeingAddedOrRemoved(delta);
+
+ // generate classpath change deltas
+ if (this.classpathChanges.size() > 0) {
+ boolean hasDelta = this.currentDelta != null;
+ JavaElementDelta javaDelta = currentDelta();
+ Iterator changes = this.classpathChanges.values().iterator();
+ while (changes.hasNext()) {
+ ClasspathChange change = (ClasspathChange) changes.next();
+ int result = change.generateDelta(javaDelta);
+ if ((result & ClasspathChange.HAS_DELTA) != 0) {
+ hasDelta = true;
+ change.requestIndexing();
+ this.state.addClasspathValidation(change.project);
+ }
+ if ((result & ClasspathChange.HAS_PROJECT_CHANGE) != 0) {
+ this.state.addProjectReferenceChange(change.project, change.oldResolvedClasspath);
+ }
+ }
+ this.classpathChanges.clear();
+ if (!hasDelta)
+ this.currentDelta = null;
+ }
+
+ // generate external archive change deltas
+ if (this.refreshedElements != null) {
+ createExternalArchiveDelta(null);
+ }
+
+ // generate Java deltas from resource changes
+ IJavaElementDelta translatedDelta = processResourceDelta(delta);
+ if (translatedDelta != null) {
+ registerJavaModelDelta(translatedDelta);
+ }
+ } finally {
+ this.sourceElementParserCache = null; // don't hold onto parser longer than necessary
+ startDeltas();
+ }
+ IElementChangedListener[] listeners;
+ int listenerCount;
+ synchronized (this.state) {
+ listeners = this.state.elementChangedListeners;
+ listenerCount = this.state.elementChangedListenerCount;
+ }
+ notifyTypeHierarchies(listeners, listenerCount);
+ fire(null, ElementChangedEvent.POST_CHANGE);
+ } finally {
+ // workaround for bug 15168 circular errors not reported
+ this.state.resetOldJavaProjectNames();
+ this.oldRoots = null;
+ }
+ }
+ return;
+
+ case IResourceChangeEvent.PRE_BUILD :
+ if(!isAffectedBy(delta))
+ return; // avoid populating for SYNC or MARKER deltas
+
+ // create classpath markers if necessary
+ boolean needCycleValidation = validateClasspaths(delta);
+ ClasspathValidation[] validations = this.state.removeClasspathValidations();
+ if (validations != null) {
+ for (int i = 0, length = validations.length; i < length; i++) {
+ ClasspathValidation validation = validations[i];
+ validation.validate();
+ }
+ }
+
+ // update project references if necessary
+ ProjectReferenceChange[] projectRefChanges = this.state.removeProjectReferenceChanges();
+ if (projectRefChanges != null) {
+ for (int i = 0, length = projectRefChanges.length; i < length; i++) {
+ try {
+ projectRefChanges[i].updateProjectReferencesIfNecessary();
+ } catch(JavaModelException e) {
+ // project doesn't exist any longer, continue with next one
+ }
+ }
+ }
+
+ if (needCycleValidation || projectRefChanges != null) {
+ // update all cycle markers since the project references changes may have affected cycles
+ try {
+ JavaProject.validateCycles(null);
+ } catch (JavaModelException e) {
+ // a project no longer exists
+ }
+ }
+
+ JavaModel.flushExternalFileCache();
+ JavaBuilder.buildStarting();
+
+ // does not fire any deltas
+ return;
+
+ case IResourceChangeEvent.POST_BUILD :
+ JavaBuilder.buildFinished();
+ return;
}
}
+
/*
* Returns the root info for the given path. Look in the old roots table if kind is REMOVED.
*/
@@ -1875,6 +2012,9 @@
// process current delta
boolean processChildren = true;
if (res instanceof IProject) {
+ // reset source element parser cache
+ this.sourceElementParserCache = null;
+
processChildren =
this.updateCurrentDeltaAndIndex(
delta,
@@ -1926,7 +2066,7 @@
);
// is childRes in the output folder and is it filtered out ?
- boolean isResFilteredFromOutput = this.isResFilteredFromOutput(outputsInfo, childRes, childType);
+ boolean isResFilteredFromOutput = this.isResFilteredFromOutput(rootInfo, outputsInfo, childRes, childType);
boolean isNestedRoot = rootInfo != null && childRootInfo != null;
if (!isResFilteredFromOutput
@@ -1969,7 +2109,11 @@
orphanChildren[i] = child;
}
} else {
- oneChildOnClasspath = true;
+ if (rootInfo == null && childRootInfo == null) {
+ // the non-java resource (or its parent folder) will be attached to the java project
+ if (orphanChildren == null) orphanChildren = new IResourceDelta[length];
+ orphanChildren[i] = child;
+ }
}
} else {
oneChildOnClasspath = true; // to avoid reporting child delta as non-java resource delta
@@ -2016,17 +2160,10 @@
} // else resource delta will be added by parent
}
- /*
- * Check whether .classpath files are affected by the given delta.
- * Creates/removes problem markers if needed.
- * Remember the affected projects in the given set.
- */
- private void updateClasspathMarkers(IResourceDelta delta, HashSet affectedProjects, Map preferredClasspaths, Map preferredOutputs) {
+ private void validateClasspaths(IResourceDelta delta, HashSet affectedProjects) {
IResource resource = delta.getResource();
boolean processChildren = false;
-
switch (resource.getType()) {
-
case IResource.ROOT :
if (delta.getKind() == IResourceDelta.CHANGED) {
processChildren = true;
@@ -2044,35 +2181,19 @@
case IResourceDelta.CHANGED:
processChildren = isJavaProject;
if ((delta.getFlags() & IResourceDelta.OPEN) != 0) {
- // project opened or closed: remember project and its dependents
- affectedProjects.add(project.getFullPath());
+ // project opened or closed
if (isJavaProject) {
JavaProject javaProject = (JavaProject)JavaCore.create(project);
- javaProject.updateClasspathMarkers(preferredClasspaths, preferredOutputs); // in case .classpath got modified while closed
+ this.state.addClasspathValidation(javaProject); // in case .classpath got modified while closed
}
+ affectedProjects.add(project.getFullPath());
} else if ((delta.getFlags() & IResourceDelta.DESCRIPTION) != 0) {
- boolean wasJavaProject = this.manager.getJavaModel().findJavaProject(project) != null;
- if (wasJavaProject && !isJavaProject) {
- // project no longer has Java nature, discard Java related obsolete markers
+ boolean wasJavaProject = this.state.findJavaProject(project.getName()) != null;
+ if (wasJavaProject != isJavaProject) {
+ // project gained or lost Java nature
+ JavaProject javaProject = (JavaProject)JavaCore.create(project);
+ this.state.addClasspathValidation(javaProject); // add/remove classpath markers
affectedProjects.add(project.getFullPath());
- // flush classpath markers
- JavaProject javaProject = (JavaProject)JavaCore.create(project);
- javaProject.
- flushClasspathProblemMarkers(
- true, // flush cycle markers
- true //flush classpath format markers
- );
-
- // remove problems and tasks created by the builder
- JavaBuilder.removeProblemsAndTasksFor(project);
- }
- } else if (isJavaProject) {
- // check if all entries exist
- try {
- JavaProject javaProject = (JavaProject)JavaCore.create(project);
- javaProject.getResolvedClasspath(true/*ignoreUnresolvedEntry*/, true/*generateMarkerOnError*/, false/*don't returnResolutionInProgress*/);
- } catch (JavaModelException e) {
- // project doesn't exist: ignore
}
}
break;
@@ -2082,86 +2203,71 @@
}
break;
case IResource.FILE :
- /* check classpath file change */
+ /* check classpath or prefs files change */
IFile file = (IFile) resource;
- if (file.getName().equals(JavaProject.CLASSPATH_FILENAME)) {
- affectedProjects.add(file.getProject().getFullPath());
+ String fileName = file.getName();
+ if (fileName.equals(JavaProject.CLASSPATH_FILENAME)) {
JavaProject javaProject = (JavaProject)JavaCore.create(file.getProject());
- javaProject.updateClasspathMarkers(preferredClasspaths, preferredOutputs);
- break;
+ this.state.addClasspathValidation(javaProject);
+ affectedProjects.add(file.getProject().getFullPath());
}
-// /* check custom preference file change */
-// if (file.getName().equals(JavaProject.PREF_FILENAME)) {
-// reconcilePreferenceFileUpdate(delta, file, project);
-// break;
-// }
break;
}
if (processChildren) {
IResourceDelta[] children = delta.getAffectedChildren();
for (int i = 0; i < children.length; i++) {
- updateClasspathMarkers(children[i], affectedProjects, preferredClasspaths, preferredOutputs);
+ validateClasspaths(children[i], affectedProjects);
}
}
}
/*
- * Update the .classpath format, missing entries and cycle markers for the projects affected by the given delta.
+ * Validate the classpaths of the projects affected by the given delta.
+ * Create markers if necessary.
+ * Returns whether cycle markers should be recomputed.
*/
- private void updateClasspathMarkers(IResourceDelta delta) {
-
- Map preferredClasspaths = new HashMap(5);
- Map preferredOutputs = new HashMap(5);
+ private boolean validateClasspaths(IResourceDelta delta) {
HashSet affectedProjects = new HashSet(5);
-
- // read .classpath files that have changed, and create markers if format is wrong or if an entry cannot be found
- JavaModel.flushExternalFileCache();
- updateClasspathMarkers(delta, affectedProjects, preferredClasspaths, preferredOutputs);
+ validateClasspaths(delta, affectedProjects);
+ boolean needCycleValidation = false;
- // update .classpath format markers for affected projects (dependent projects
+ // validate classpaths of affected projects (dependent projects
// or projects that reference a library in one of the projects that have changed)
if (!affectedProjects.isEmpty()) {
- try {
- IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
- IProject[] projects = workspaceRoot.getProjects();
- int length = projects.length;
- for (int i = 0; i < length; i++){
- IProject project = projects[i];
- JavaProject javaProject = (JavaProject)JavaCore.create(project);
- if (preferredClasspaths.get(javaProject) == null) { // not already updated
- try {
- IPath projectPath = project.getFullPath();
- IClasspathEntry[] classpath = javaProject.getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/); // allowed to reuse model cache
- for (int j = 0, cpLength = classpath.length; j < cpLength; j++) {
- IClasspathEntry entry = classpath[j];
- switch (entry.getEntryKind()) {
- case IClasspathEntry.CPE_PROJECT:
- if (affectedProjects.contains(entry.getPath())) {
- javaProject.updateClasspathMarkers(null, null);
- }
- break;
- case IClasspathEntry.CPE_LIBRARY:
- IPath entryPath = entry.getPath();
- IPath libProjectPath = entryPath.removeLastSegments(entryPath.segmentCount()-1);
- if (!libProjectPath.equals(projectPath) // if library contained in another project
- && affectedProjects.contains(libProjectPath)) {
- javaProject.updateClasspathMarkers(null, null);
- }
- break;
+ IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
+ IProject[] projects = workspaceRoot.getProjects();
+ int length = projects.length;
+ for (int i = 0; i < length; i++){
+ IProject project = projects[i];
+ JavaProject javaProject = (JavaProject)JavaCore.create(project);
+ try {
+ IPath projectPath = project.getFullPath();
+ IClasspathEntry[] classpath = javaProject.getResolvedClasspath(); // allowed to reuse model cache
+ for (int j = 0, cpLength = classpath.length; j < cpLength; j++) {
+ IClasspathEntry entry = classpath[j];
+ switch (entry.getEntryKind()) {
+ case IClasspathEntry.CPE_PROJECT:
+ if (affectedProjects.contains(entry.getPath())) {
+ this.state.addClasspathValidation(javaProject);
+ needCycleValidation = true;
}
- }
- } catch(JavaModelException e) {
- // project no longer exists
+ break;
+ case IClasspathEntry.CPE_LIBRARY:
+ IPath entryPath = entry.getPath();
+ IPath libProjectPath = entryPath.removeLastSegments(entryPath.segmentCount()-1);
+ if (!libProjectPath.equals(projectPath) // if library contained in another project
+ && affectedProjects.contains(libProjectPath)) {
+ this.state.addClasspathValidation(javaProject);
+ }
+ break;
}
}
+ } catch(JavaModelException e) {
+ // project no longer exists
}
-
- // update all cycle markers
- JavaProject.updateAllCycleMarkers(preferredClasspaths);
- } catch(JavaModelException e) {
- // project no longer exists
}
}
+ return needCycleValidation;
}
/*
@@ -2182,6 +2288,8 @@
}
updateIndex(element, delta);
elementAdded(element, delta, rootInfo);
+ if (elementType == IJavaElement.PACKAGE_FRAGMENT_ROOT)
+ this.state.addClasspathValidation(rootInfo.project);
return elementType == IJavaElement.PACKAGE_FRAGMENT;
case IResourceDelta.REMOVED :
deltaRes = delta.getResource();
@@ -2193,6 +2301,8 @@
}
updateIndex(element, delta);
elementRemoved(element, delta, rootInfo);
+ if (elementType == IJavaElement.PACKAGE_FRAGMENT_ROOT)
+ this.state.addClasspathValidation(rootInfo.project);
if (deltaRes.getType() == IResource.PROJECT){
// reset the corresponding project built state, since cannot reuse if added back
@@ -2235,8 +2345,7 @@
this.manager.indexManager.indexAll(res);
}
} else {
- JavaModel javaModel = this.manager.getJavaModel();
- boolean wasJavaProject = javaModel.findJavaProject(res) != null;
+ boolean wasJavaProject = this.state.findJavaProject(res.getName()) != null;
if (wasJavaProject) {
close(element);
removeFromParentInfo(element);
@@ -2249,8 +2358,7 @@
}
if ((flags & IResourceDelta.DESCRIPTION) != 0) {
IProject res = (IProject)delta.getResource();
- JavaModel javaModel = this.manager.getJavaModel();
- boolean wasJavaProject = javaModel.findJavaProject(res) != null;
+ boolean wasJavaProject = this.state.findJavaProject(res.getName()) != null;
boolean isJavaProject = JavaProject.hasJavaNature(res);
if (wasJavaProject != isJavaProject) {
// project's nature has been added or removed
@@ -2400,10 +2508,14 @@
if ((flags & IResourceDelta.CONTENT) == 0 && (flags & IResourceDelta.ENCODING) == 0)
break;
case IResourceDelta.ADDED :
- indexManager.addSource(file, file.getProject().getFullPath());
+ indexManager.addSource(file, file.getProject().getFullPath(), getSourceElementParser(element));
+ // Clean file from secondary types cache but do not update indexing secondary type cache as it will be updated through indexing itself
+ this.manager.secondaryTypesRemoving(file, false);
break;
case IResourceDelta.REMOVED :
indexManager.remove(Util.relativePath(file.getFullPath(), 1/*remove project segment*/), file.getProject().getFullPath());
+ // Clean file from secondary types cache and update indexing secondary type cache as indexing cannot remove secondary types from cache
+ this.manager.secondaryTypesRemoving(file, true);
break;
}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DiscardWorkingCopyOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DiscardWorkingCopyOperation.java
index fc424d6..0dc263f 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DiscardWorkingCopyOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DiscardWorkingCopyOperation.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -12,6 +12,7 @@
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaElementDelta;
+import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaModelException;
/**
@@ -26,23 +27,29 @@
protected void executeOperation() throws JavaModelException {
CompilationUnit workingCopy = getWorkingCopy();
- int useCount = JavaModelManager.getJavaModelManager().discardPerWorkingCopyInfo(workingCopy);
+ JavaModelManager manager = JavaModelManager.getJavaModelManager();
+ int useCount = manager.discardPerWorkingCopyInfo(workingCopy);
if (useCount == 0) {
+ IJavaProject javaProject = workingCopy.getJavaProject();
+ if (ExternalJavaProject.EXTERNAL_PROJECT_NAME.equals(javaProject.getElementName())) {
+ manager.removePerProjectInfo((JavaProject) javaProject);
+ manager.containerRemove(javaProject);
+ }
if (!workingCopy.isPrimary()) {
// report removed java delta for a non-primary working copy
- JavaElementDelta delta = new JavaElementDelta(this.getJavaModel());
+ JavaElementDelta delta = new JavaElementDelta(getJavaModel());
delta.removed(workingCopy);
addDelta(delta);
removeReconcileDelta(workingCopy);
} else {
if (workingCopy.getResource().isAccessible()) {
// report a F_PRIMARY_WORKING_COPY change delta for a primary working copy
- JavaElementDelta delta = new JavaElementDelta(this.getJavaModel());
+ JavaElementDelta delta = new JavaElementDelta(getJavaModel());
delta.changed(workingCopy, IJavaElementDelta.F_PRIMARY_WORKING_COPY);
addDelta(delta);
} else {
// report a REMOVED delta
- JavaElementDelta delta = new JavaElementDelta(this.getJavaModel());
+ JavaElementDelta delta = new JavaElementDelta(getJavaModel());
delta.removed(workingCopy, IJavaElementDelta.F_PRIMARY_WORKING_COPY);
addDelta(delta);
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ElementCache.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ElementCache.java
index a9ce910..599602f 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ElementCache.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ElementCache.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -77,6 +77,13 @@
}
/*
+ * Returns a new instance of the receiver.
+ */
+protected LRUCache newInstance(int size, int overflow) {
+ return new ElementCache(size, overflow);
+}
+
+/*
* If the given parent was the one that increased the space limit, reset
* the space limit to the given default value.
*/
@@ -87,11 +94,4 @@
}
}
-/**
- * Returns a new instance of the reciever.
- */
-protected LRUCache newInstance(int size, int overflow) {
- return new ElementCache(size, overflow);
-}
-
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ExternalJavaProject.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ExternalJavaProject.java
new file mode 100755
index 0000000..03f42d0
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ExternalJavaProject.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+
+public class ExternalJavaProject extends JavaProject {
+
+ /*
+ * Note this name can be surfaced in the UI (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=128258)
+ */
+ public static final String EXTERNAL_PROJECT_NAME = " "; //$NON-NLS-1$
+
+ public ExternalJavaProject(IClasspathEntry[] rawClasspath) {
+ super(ResourcesPlugin.getWorkspace().getRoot().getProject(EXTERNAL_PROJECT_NAME), JavaModelManager.getJavaModelManager().getJavaModel());
+ try {
+ getPerProjectInfo().setClasspath(rawClasspath, defaultOutputLocation(), JavaModelStatus.VERIFIED_OK/*no .classpath format problem*/, null/*no resolved claspath*/, null/*no reverse map*/, null/*no resolve entry map*/, null/*no resolved status*/);
+ } catch (JavaModelException e) {
+ // getPerProjectInfo() never throws JavaModelException for an ExternalJavaProject
+ }
+ }
+
+ public boolean equals(Object o) {
+ return this == o;
+ }
+
+ public boolean exists() {
+ // external project never exists
+ return false;
+ }
+
+ public String getOption(String optionName, boolean inheritJavaCoreOptions) {
+ if (JavaCore.COMPILER_PB_FORBIDDEN_REFERENCE.equals(optionName)
+ || JavaCore.COMPILER_PB_DISCOURAGED_REFERENCE.equals(optionName))
+ return JavaCore.IGNORE;
+ return super.getOption(optionName, inheritJavaCoreOptions);
+ }
+
+ public boolean isOnClasspath(IJavaElement element) {
+ // since project is external, no element is on classpath (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=61013#c16)
+ return false;
+ }
+
+ public boolean isOnClasspath(IResource resource) {
+ // since project is external, no resource is on classpath (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=61013#c16)
+ return false;
+ }
+
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/IJavaElementRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/IJavaElementRequestor.java
index 55b467c..f054045 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/IJavaElementRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/IJavaElementRequestor.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/INamingRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/INamingRequestor.java
index 5c42b88..bf37134 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/INamingRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/INamingRequestor.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -11,8 +11,8 @@
package org.eclipse.jdt.internal.core;
public interface INamingRequestor {
- void acceptNameWithPrefixAndSuffix(char[] name, boolean isFirstPrefix, boolean isFirstSuffix);
- void acceptNameWithPrefix(char[] name, boolean isFirstPrefix);
- void acceptNameWithSuffix(char[] name, boolean isFirstSuffix);
- void acceptNameWithoutPrefixAndSuffix(char[] name);
+ void acceptNameWithPrefixAndSuffix(char[] name, boolean isFirstPrefix, boolean isFirstSuffix, int reusedCharacters);
+ void acceptNameWithPrefix(char[] name, boolean isFirstPrefix, int reusedCharacters);
+ void acceptNameWithSuffix(char[] name, boolean isFirstSuffix, int reusedCharacters);
+ void acceptNameWithoutPrefixAndSuffix(char[] name, int reusedCharacters);
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/IPathRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/IPathRequestor.java
index c303e6a..f96b7fc 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/IPathRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/IPathRequestor.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ImportDeclaration.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ImportDeclaration.java
index 5b86608..e2e0003 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ImportDeclaration.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ImportDeclaration.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,9 +10,8 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core;
+import org.eclipse.core.runtime.Assert;
import org.eclipse.jdt.core.*;
-import org.eclipse.jdt.core.IImportDeclaration;
-import org.eclipse.jdt.core.JavaModelException;
/**
* Handle for an import declaration. Info object is a ImportDeclarationElementInfo.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ImportDeclarationElementInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ImportDeclarationElementInfo.java
index 2554b08..11d1781 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ImportDeclarationElementInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ImportDeclarationElementInfo.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/InitializerElementInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/InitializerElementInfo.java
index 665aa22..9818348 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/InitializerElementInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/InitializerElementInfo.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/InternalNamingConventions.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/InternalNamingConventions.java
index 3e28798..ea6e4a7 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/InternalNamingConventions.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/InternalNamingConventions.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -14,12 +14,12 @@
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.IJavaProject;
-import org.eclipse.jdt.core.JavaConventions;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.compiler.InvalidInputException;
import org.eclipse.jdt.internal.codeassist.impl.AssistOptions;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.parser.Scanner;
+import org.eclipse.jdt.internal.compiler.parser.ScannerHelper;
import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
public class InternalNamingConventions {
@@ -36,7 +36,7 @@
null/*taskPriorities*/,
true/*taskCaseSensitive*/);
}
- public static void suggestArgumentNames(IJavaProject javaProject, char[] packageName, char[] qualifiedTypeName, int dim, char[][] excludedNames, INamingRequestor requestor) {
+ public static void suggestArgumentNames(IJavaProject javaProject, char[] packageName, char[] qualifiedTypeName, int dim, char[] internalPrefix, char[][] excludedNames, INamingRequestor requestor) {
Map options = javaProject.getOptions(true);
CompilerOptions compilerOptions = new CompilerOptions(options);
AssistOptions assistOptions = new AssistOptions(options);
@@ -45,13 +45,14 @@
packageName,
qualifiedTypeName,
dim,
+ internalPrefix,
assistOptions.argumentPrefixes,
assistOptions.argumentSuffixes,
excludedNames,
getNameScanner(compilerOptions),
requestor);
}
- public static void suggestFieldNames(IJavaProject javaProject, char[] packageName, char[] qualifiedTypeName, int dim, int modifiers, char[][] excludedNames, INamingRequestor requestor) {
+ public static void suggestFieldNames(IJavaProject javaProject, char[] packageName, char[] qualifiedTypeName, int dim, int modifiers, char[] internalPrefix, char[][] excludedNames, INamingRequestor requestor) {
boolean isStatic = Flags.isStatic(modifiers);
Map options = javaProject.getOptions(true);
@@ -62,13 +63,14 @@
packageName,
qualifiedTypeName,
dim,
+ internalPrefix,
isStatic ? assistOptions.staticFieldPrefixes : assistOptions.fieldPrefixes,
isStatic ? assistOptions.staticFieldSuffixes : assistOptions.fieldSuffixes,
excludedNames,
getNameScanner(compilerOptions),
requestor);
}
- public static void suggestLocalVariableNames(IJavaProject javaProject, char[] packageName, char[] qualifiedTypeName, int dim, char[][] excludedNames, INamingRequestor requestor) {
+ public static void suggestLocalVariableNames(IJavaProject javaProject, char[] packageName, char[] qualifiedTypeName, int dim, char[] internalPrefix, char[][] excludedNames, INamingRequestor requestor) {
Map options = javaProject.getOptions(true);
CompilerOptions compilerOptions = new CompilerOptions(options);
AssistOptions assistOptions = new AssistOptions(options);
@@ -77,6 +79,7 @@
packageName,
qualifiedTypeName,
dim,
+ internalPrefix,
assistOptions.localPrefixes,
assistOptions.localSuffixes,
excludedNames,
@@ -88,6 +91,7 @@
char[] packageName,
char[] qualifiedTypeName,
int dim,
+ char[] internalPrefix,
char[][] prefixes,
char[][] suffixes,
char[][] excludedNames,
@@ -97,6 +101,12 @@
if(qualifiedTypeName == null || qualifiedTypeName.length == 0)
return;
+ if(internalPrefix == null) {
+ internalPrefix = CharOperation.NO_CHAR;
+ } else {
+ internalPrefix = removePrefix(internalPrefix, prefixes);
+ }
+
char[] typeName = CharOperation.lastSegment(qualifiedTypeName, '.');
if(prefixes == null || prefixes.length == 0) {
@@ -128,7 +138,10 @@
case TerminalTokens.TokenNamelong :
case TerminalTokens.TokenNamefloat :
case TerminalTokens.TokenNamedouble :
- case TerminalTokens.TokenNameboolean :
+ case TerminalTokens.TokenNameboolean :
+
+ if (internalPrefix != null && internalPrefix.length > 0) return;
+
char[] name = computeBaseTypeNames(typeName[0], excludedNames);
if(name != null) {
tempNames = new char[][]{name};
@@ -146,7 +159,7 @@
boolean acceptDefaultName = true;
- for (int i = 0; i < tempNames.length; i++) {
+ next : for (int i = 0; i < tempNames.length; i++) {
char[] tempName = tempNames[i];
if(dim > 0) {
int length = tempName.length;
@@ -167,50 +180,72 @@
}
}
- for (int j = 0; j < prefixes.length; j++) {
- if(prefixes[j].length > 0
- && Character.isLetterOrDigit(prefixes[j][prefixes[j].length - 1])) {
- tempName[0] = Character.toUpperCase(tempName[0]);
- } else {
- tempName[0] = Character.toLowerCase(tempName[0]);
- }
- char[] prefixName = CharOperation.concat(prefixes[j], tempName);
- for (int k = 0; k < suffixes.length; k++) {
- char[] suffixName = CharOperation.concat(prefixName, suffixes[k]);
- suffixName =
- excludeNames(
- suffixName,
- prefixName,
- suffixes[k],
- excludedNames);
- if(JavaConventions.validateFieldName(new String(suffixName)).isOK()) {
- acceptName(suffixName, prefixes[j], suffixes[k], j == 0, k == 0, requestor);
- acceptDefaultName = false;
- } else {
- suffixName = CharOperation.concat(
- prefixName,
- String.valueOf(1).toCharArray(),
- suffixes[k]
- );
- suffixName =
- excludeNames(
- suffixName,
- prefixName,
- suffixes[k],
- excludedNames);
- if(JavaConventions.validateFieldName(new String(suffixName)).isOK()) {
- acceptName(suffixName, prefixes[j], suffixes[k], j == 0, k == 0, requestor);
- acceptDefaultName = false;
+ char[] unprefixedName = tempName;
+ for (int j = 0; j <= internalPrefix.length; j++) {
+ if(j == internalPrefix.length || CharOperation.prefixEquals(CharOperation.subarray(internalPrefix, j, -1), unprefixedName, false)) {
+ tempName = CharOperation.concat(CharOperation.subarray(internalPrefix, 0, j), unprefixedName);
+ if(j != 0) tempName[j] = ScannerHelper.toUpperCase(tempName[j]);
+ for (int k = 0; k < prefixes.length; k++) {
+ if(prefixes[k].length > 0
+ && ScannerHelper.isLetterOrDigit(prefixes[k][prefixes[k].length - 1])) {
+ tempName[0] = ScannerHelper.toUpperCase(tempName[0]);
+ } else {
+ tempName[0] = ScannerHelper.toLowerCase(tempName[0]);
+ }
+ char[] prefixName = CharOperation.concat(prefixes[k], tempName);
+ for (int l = 0; l < suffixes.length; l++) {
+ char[] suffixName = CharOperation.concat(prefixName, suffixes[l]);
+ suffixName =
+ excludeNames(
+ suffixName,
+ prefixName,
+ suffixes[l],
+ excludedNames);
+ try{
+ nameScanner.setSource(suffixName);
+ switch (nameScanner.getNextToken()) {
+ case TerminalTokens.TokenNameIdentifier :
+ int token = nameScanner.getNextToken();
+ if (token == TerminalTokens.TokenNameEOF && nameScanner.startPosition == suffixName.length) {
+ acceptName(suffixName, prefixes[k], suffixes[l], k == 0, l == 0, internalPrefix.length - j, requestor);
+ acceptDefaultName = false;
+ }
+ break;
+ default:
+ suffixName = CharOperation.concat(
+ prefixName,
+ String.valueOf(1).toCharArray(),
+ suffixes[l]
+ );
+ suffixName =
+ excludeNames(
+ suffixName,
+ prefixName,
+ suffixes[l],
+ excludedNames);
+ nameScanner.setSource(suffixName);
+ switch (nameScanner.getNextToken()) {
+ case TerminalTokens.TokenNameIdentifier :
+ token = nameScanner.getNextToken();
+ if (token == TerminalTokens.TokenNameEOF && nameScanner.startPosition == suffixName.length) {
+ acceptName(suffixName, prefixes[k], suffixes[l], k == 0, l == 0, internalPrefix.length - j, requestor);
+ acceptDefaultName = false;
+ }
+ }
+ }
+ } catch(InvalidInputException e){
+ // ignore
+ }
}
}
+ continue next;
}
-
}
}
// if no names were found
if(acceptDefaultName) {
char[] name = excludeNames(DEFAULT_NAME, DEFAULT_NAME, CharOperation.NO_CHAR, excludedNames);
- requestor.acceptNameWithoutPrefixAndSuffix(name);
+ requestor.acceptNameWithoutPrefixAndSuffix(name, 0);
}
}
@@ -220,15 +255,16 @@
char[] suffix,
boolean isFirstPrefix,
boolean isFirstSuffix,
+ int reusedCharacters,
INamingRequestor requestor) {
if(prefix.length > 0 && suffix.length > 0) {
- requestor.acceptNameWithPrefixAndSuffix(name, isFirstPrefix, isFirstSuffix);
+ requestor.acceptNameWithPrefixAndSuffix(name, isFirstPrefix, isFirstSuffix, reusedCharacters);
} else if(prefix.length > 0){
- requestor.acceptNameWithPrefix(name, isFirstPrefix);
+ requestor.acceptNameWithPrefix(name, isFirstPrefix, reusedCharacters);
} else if(suffix.length > 0){
- requestor.acceptNameWithSuffix(name, isFirstSuffix);
+ requestor.acceptNameWithSuffix(name, isFirstSuffix, reusedCharacters);
} else {
- requestor.acceptNameWithoutPrefixAndSuffix(name);
+ requestor.acceptNameWithoutPrefixAndSuffix(name, reusedCharacters);
}
}
@@ -255,15 +291,15 @@
boolean previousIsUpperCase = false;
boolean previousIsLetter = true;
for(int i = sourceName.length - 1 ; i >= 0 ; i--){
- boolean isUpperCase = Character.isUpperCase(sourceName[i]);
- boolean isLetter = Character.isLetter(sourceName[i]);
+ boolean isUpperCase = ScannerHelper.isUpperCase(sourceName[i]);
+ boolean isLetter = ScannerHelper.isLetter(sourceName[i]);
if(isUpperCase && !previousIsUpperCase && previousIsLetter){
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]);
+ name[0] = ScannerHelper.toLowerCase(name[0]);
names[nameCount++] = name;
}
}
@@ -298,4 +334,90 @@
}
return suffixName;
}
+
+ private static char[] removePrefix(char[] name, char[][] prefixes) {
+ // remove longer prefix
+ char[] withoutPrefixName = name;
+ if (prefixes != null) {
+ int bestLength = 0;
+ int nameLength = name.length;
+ for (int i= 0; i < prefixes.length; i++) {
+ char[] prefix = prefixes[i];
+
+ int prefixLength = prefix.length;
+ if(prefixLength <= nameLength) {
+ if(CharOperation.prefixEquals(prefix, name, false)) {
+ if (prefixLength > bestLength) {
+ bestLength = prefixLength;
+ }
+ }
+ } else {
+ int currLen = 0;
+ for (; currLen < nameLength; currLen++) {
+ if(ScannerHelper.toLowerCase(prefix[currLen]) != ScannerHelper.toLowerCase(name[currLen])) {
+ if (currLen > bestLength) {
+ bestLength = currLen;
+ }
+ break;
+ }
+ }
+ if(currLen == nameLength && currLen > bestLength) {
+ bestLength = currLen;
+ }
+ }
+ }
+ if(bestLength > 0) {
+ if(bestLength == nameLength) {
+ withoutPrefixName = CharOperation.NO_CHAR;
+ } else {
+ withoutPrefixName = CharOperation.subarray(name, bestLength, nameLength);
+ }
+ }
+ }
+//
+//
+// // remove longer prefix
+// char[] withoutPrefixName = name;
+// if (prefixes != null) {
+// int bestLength = 0;
+// for (int i= 0; i < prefixes.length; i++) {
+// char[] prefix = prefixes[i];
+// int max = prefix.length < name.length ? prefix.length : name.length;
+// int currLen = 0;
+// for (; currLen < max; currLen++) {
+// if(Character.toLowerCase(prefix[currLen]) != Character.toLowerCase(name[currLen])) {
+// if (currLen > bestLength) {
+// bestLength = currLen;
+// }
+// break;
+// }
+// }
+// if(currLen == max && currLen > bestLength) {
+// bestLength = max;
+// }
+// }
+// if(bestLength > 0) {
+// if(bestLength == name.length) {
+// withoutPrefixName = CharOperation.NO_CHAR;
+// } else {
+// withoutPrefixName = CharOperation.subarray(name, bestLength, name.length);
+// }
+// }
+// }
+
+ return withoutPrefixName;
+ }
+
+ public static final boolean prefixEquals(char[] prefix, char[] name) {
+
+ int max = prefix.length;
+ if (name.length < max)
+ return false;
+ for (int i = max;
+ --i >= 0;
+ ) // assumes the prefix is not larger than the name
+ if (prefix[i] != name[i])
+ return false;
+ return true;
+ }
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarEntryDirectory.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarEntryDirectory.java
new file mode 100755
index 0000000..317df0e
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarEntryDirectory.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jdt.core.IJarEntryResource;
+
+public class JarEntryDirectory extends JarEntryResource {
+ private IJarEntryResource[] children;
+
+ public JarEntryDirectory(String simpleName) {
+ super(simpleName);
+ }
+
+ public JarEntryResource clone(Object newParent) {
+ JarEntryDirectory dir = new JarEntryDirectory(this.simpleName);
+ dir.setParent(newParent);
+ int length = this.children.length;
+ if (length > 0) {
+ IJarEntryResource[] newChildren = new IJarEntryResource[length];
+ for (int i = 0; i < length; i++) {
+ JarEntryResource child = (JarEntryResource) this.children[i];
+ newChildren[i] = child.clone(dir);
+ }
+ dir.setChildren(newChildren);
+ }
+ return dir;
+ }
+
+ public IJarEntryResource[] getChildren() {
+ return this.children;
+ }
+
+ public InputStream getContents() throws CoreException {
+ return new ByteArrayInputStream(new byte[0]);
+ }
+
+ public boolean isFile() {
+ return false;
+ }
+
+ public void setChildren(IJarEntryResource[] children) {
+ this.children = children;
+ }
+
+ public String toString() {
+ return "JarEntryDirectory["+getEntryName()+"]"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarEntryFile.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarEntryFile.java
index b457b77..2848e33 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarEntryFile.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarEntryFile.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,6 +10,7 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core;
+import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.ZipEntry;
@@ -17,65 +18,60 @@
import org.eclipse.core.resources.IStorage;
import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.Path;
-import org.eclipse.core.runtime.PlatformObject;
+import org.eclipse.jdt.core.IJarEntryResource;
import org.eclipse.jdt.core.IJavaModelStatusConstants;
import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.internal.compiler.util.Util;
/**
- * A jar entry that represents a non-java resource found in a JAR.
+ * A jar entry that represents a non-java file found in a JAR.
*
* @see IStorage
*/
-public class JarEntryFile extends PlatformObject implements IStorage {
- private String entryName;
- private String zipName;
- private IPath path;
+public class JarEntryFile extends JarEntryResource {
+ private static final IJarEntryResource[] NO_CHILDREN = new IJarEntryResource[0];
- public JarEntryFile(String entryName, String zipName){
- this.entryName = entryName;
- this.zipName = zipName;
- this.path = new Path(this.entryName);
+ public JarEntryFile(String simpleName) {
+ super(simpleName);
}
-public InputStream getContents() throws CoreException {
-
- try {
- if (JavaModelManager.ZIP_ACCESS_VERBOSE) {
- System.out.println("(" + Thread.currentThread() + ") [JarEntryFile.getContents()] Creating ZipFile on " + this.zipName); //$NON-NLS-1$ //$NON-NLS-2$
- }
- ZipFile zipFile = new ZipFile(this.zipName);
- ZipEntry zipEntry = zipFile.getEntry(this.entryName);
- if (zipEntry == null){
- throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INVALID_PATH, this.entryName));
- }
- return zipFile.getInputStream(zipEntry);
- } catch (IOException e){
- throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
+
+ public JarEntryResource clone(Object newParent) {
+ JarEntryFile file = new JarEntryFile(simpleName);
+ file.setParent(newParent);
+ return file;
}
-}
-/**
- * @see IStorage#getFullPath
- */
-public IPath getFullPath() {
- return this.path;
-}
-/**
- * @see IStorage#getName
- */
-public String getName() {
- return this.path.lastSegment();
-}
-/**
- * @see IStorage#isReadOnly()
- */
-public boolean isReadOnly() {
- return true;
-}
-/**
- * @see IStorage#isReadOnly()
- */
-public String toString() {
- return "JarEntryFile["+this.zipName+"::"+this.entryName+"]"; //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-1$
-}
+
+ public InputStream getContents() throws CoreException {
+ ZipFile zipFile = null;
+ try {
+ zipFile = getZipFile();
+ if (JavaModelManager.ZIP_ACCESS_VERBOSE) {
+ System.out.println("(" + Thread.currentThread() + ") [JarEntryFile.getContents()] Creating ZipFile on " +zipFile.getName()); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ String entryName = getEntryName();
+ ZipEntry zipEntry = zipFile.getEntry(entryName);
+ if (zipEntry == null){
+ throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INVALID_PATH, entryName));
+ }
+ byte[] contents = Util.getZipEntryByteContent(zipEntry, zipFile);
+ return new ByteArrayInputStream(contents);
+ } catch (IOException e){
+ throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
+ } finally {
+ // avoid leaking ZipFiles
+ JavaModelManager.getJavaModelManager().closeZipFile(zipFile);
+ }
+ }
+
+ public IJarEntryResource[] getChildren() {
+ return NO_CHILDREN;
+ }
+
+ public boolean isFile() {
+ return true;
+ }
+
+ public String toString() {
+ return "JarEntryFile["+getEntryName()+"]"; //$NON-NLS-2$ //$NON-NLS-1$
+ }
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarEntryResource.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarEntryResource.java
new file mode 100755
index 0000000..cc8c4de
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarEntryResource.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core;
+
+import java.util.zip.ZipFile;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.PlatformObject;
+import org.eclipse.jdt.core.IJarEntryResource;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.internal.core.util.Util;
+
+public abstract class JarEntryResource extends PlatformObject implements IJarEntryResource {
+
+ protected Object parent;
+ protected String simpleName;
+
+ public JarEntryResource(String simpleName) {
+ this.simpleName = simpleName;
+ }
+
+ public abstract JarEntryResource clone(Object newParent);
+
+ public boolean equals(Object obj) {
+ if (! (obj instanceof JarEntryResource))
+ return false;
+ JarEntryResource other = (JarEntryResource) obj;
+ return this.parent.equals(other.parent) && this.simpleName.equals(other.simpleName);
+ }
+
+ protected String getEntryName() {
+ String parentEntryName;
+ if (this.parent instanceof IPackageFragment) {
+ String elementName = ((IPackageFragment) this.parent).getElementName();
+ parentEntryName = elementName.length() == 0 ? "" : elementName .replace('.', '/') + '/'; //$NON-NLS-1$
+ } else if (this.parent instanceof IPackageFragmentRoot) {
+ parentEntryName = ""; //$NON-NLS-1$
+ } else {
+ parentEntryName = ((JarEntryDirectory) this.parent).getEntryName() + '/';
+ }
+ return parentEntryName + this.simpleName;
+ }
+
+ public IPath getFullPath() {
+ return new Path(getEntryName()).makeAbsolute();
+ }
+
+ public String getName() {
+ return this.simpleName;
+ }
+
+ public Object getParent() {
+ return this.parent;
+ }
+
+ public IPackageFragmentRoot getPackageFragmentRoot() {
+ if (this.parent instanceof IPackageFragment) {
+ return (IPackageFragmentRoot) ((IPackageFragment) this.parent).getParent();
+ } else if (this.parent instanceof IPackageFragmentRoot) {
+ return (IPackageFragmentRoot) this.parent;
+ } else {
+ return ((JarEntryDirectory) this.parent).getPackageFragmentRoot();
+ }
+ }
+
+ protected ZipFile getZipFile() throws CoreException {
+ if (this.parent instanceof IPackageFragment) {
+ JarPackageFragmentRoot root = (JarPackageFragmentRoot) ((IPackageFragment) this.parent).getParent();
+ return root.getJar();
+ } else if (this.parent instanceof JarPackageFragmentRoot) {
+ return ((JarPackageFragmentRoot) this.parent).getJar();
+ } else
+ return ((JarEntryDirectory) this.parent).getZipFile();
+ }
+
+ public int hashCode() {
+ return Util.combineHashCodes(this.simpleName.hashCode(), this.parent.hashCode());
+ }
+
+ public boolean isReadOnly() {
+ return true;
+ }
+
+ public void setParent(Object parent) {
+ this.parent = parent;
+ }
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragment.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragment.java
index 3ef3b6a..66a3350 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragment.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragment.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -13,11 +13,15 @@
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.Map;
import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IClassFile;
import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJarEntryResource;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaModelStatusConstants;
import org.eclipse.jdt.core.JavaModelException;
@@ -59,7 +63,7 @@
/**
* Compute all the non-java resources according to the entry name found in the jar file.
*/
-/* package */ void computeNonJavaResources(String[] resNames, JarPackageFragmentInfo info, String zipName) {
+/* package */ void computeNonJavaResources(String[] resNames, JarPackageFragment pkg, JarPackageFragmentInfo info, String zipName) {
if (resNames == null) {
info.setNonJavaResources(null);
return;
@@ -68,19 +72,62 @@
if (max == 0) {
info.setNonJavaResources(JavaElementInfo.NO_NON_JAVA_RESOURCES);
} else {
- Object[] res = new Object[max];
- int index = 0;
+ HashMap jarEntries = new HashMap(); // map from IPath to IJarEntryResource
+ HashMap childrenMap = new HashMap(); // map from IPath to ArrayList<IJarEntryResource>
+ ArrayList topJarEntries = new ArrayList();
for (int i = 0; i < max; i++) {
String resName = resNames[i];
// consider that a .java file is not a non-java resource (see bug 12246 Packages view shows .class and .java files when JAR has source)
if (!Util.isJavaLikeFileName(resName)) {
- resName = Util.concatWith(this.names, resName, '/');
- res[index++] = new JarEntryFile(resName, zipName);
+ IPath filePath = new Path(resName);
+ IPath childPath = filePath.removeFirstSegments(this.names.length);
+ JarEntryFile file = new JarEntryFile(filePath.lastSegment());
+ jarEntries.put(childPath, file);
+ if (childPath.segmentCount() == 1) {
+ file.setParent(pkg);
+ topJarEntries.add(file);
+ } else {
+ IPath parentPath = childPath.removeLastSegments(1);
+ while (parentPath.segmentCount() > 0) {
+ ArrayList parentChildren = (ArrayList) childrenMap.get(parentPath);
+ if (parentChildren == null) {
+ Object dir = new JarEntryDirectory(parentPath.lastSegment());
+ jarEntries.put(parentPath, dir);
+ childrenMap.put(parentPath, parentChildren = new ArrayList());
+ parentChildren.add(childPath);
+ if (parentPath.segmentCount() == 1) {
+ topJarEntries.add(dir);
+ break;
+ }
+ childPath = parentPath;
+ parentPath = childPath.removeLastSegments(1);
+ } else {
+ parentChildren.add(childPath);
+ break; // all parents are already registered
+ }
+ }
+ }
}
- }
- if (index != max) {
- System.arraycopy(res, 0, res = new Object[index], 0, index);
}
+ Iterator entries = childrenMap.entrySet().iterator();
+ while (entries.hasNext()) {
+ Map.Entry entry = (Map.Entry) entries.next();
+ IPath entryPath = (IPath) entry.getKey();
+ ArrayList entryValue = (ArrayList) entry.getValue();
+ JarEntryDirectory jarEntryDirectory = (JarEntryDirectory) jarEntries.get(entryPath);
+ int size = entryValue.size();
+ IJarEntryResource[] children = new IJarEntryResource[size];
+ for (int i = 0; i < size; i++) {
+ JarEntryResource child = (JarEntryResource) jarEntries.get(entryValue.get(i));
+ child.setParent(jarEntryDirectory);
+ children[i] = child;
+ }
+ jarEntryDirectory.setChildren(children);
+ if (entryPath.segmentCount() == 1) {
+ jarEntryDirectory.setParent(pkg);
+ }
+ }
+ Object[] res = topJarEntries.toArray(new Object[topJarEntries.size()]);
info.setNonJavaResources(res);
}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentInfo.java
index ed4f277..6a406d2 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentInfo.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentRoot.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentRoot.java
index 2aafe2a..a729b47 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentRoot.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentRoot.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -84,29 +84,9 @@
for (Enumeration e= jar.entries(); e.hasMoreElements();) {
ZipEntry member= (ZipEntry) e.nextElement();
- String entryName= member.getName();
-
- if (member.isDirectory()) {
-
- initPackageFragToTypes(packageFragToTypes, entryName, entryName.length()-1);
- } else {
- //store the class file / non-java rsc entry name to be cached in the appropriate package fragment
- //zip entries only use '/'
- int lastSeparator= entryName.lastIndexOf('/');
- String fileName= entryName.substring(lastSeparator + 1);
- String[] pkgName = initPackageFragToTypes(packageFragToTypes, entryName, lastSeparator);
-
- // add classfile info amongst children
- ArrayList[] children = (ArrayList[]) packageFragToTypes.get(pkgName);
- if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(entryName)) {
- if (children[JAVA] == EMPTY_LIST) children[JAVA] = new ArrayList();
- children[JAVA].add(fileName);
- } else {
- if (children[NON_JAVA] == EMPTY_LIST) children[NON_JAVA] = new ArrayList();
- children[NON_JAVA].add(fileName);
- }
- }
+ initPackageFragToTypes(packageFragToTypes, member.getName(), member.isDirectory());
}
+
//loop through all of referenced packages, creating package fragments if necessary
// and cache the entry names in the infos created for those package fragments
for (int i = 0, length = packageFragToTypes.keyTable.length; i < length; i++) {
@@ -118,11 +98,11 @@
JarPackageFragmentInfo fragInfo= new JarPackageFragmentInfo();
int resLength= entries[NON_JAVA].size();
if (resLength == 0) {
- packFrag.computeNonJavaResources(CharOperation.NO_STRINGS, fragInfo, jar.getName());
+ packFrag.computeNonJavaResources(CharOperation.NO_STRINGS, packFrag, fragInfo, jar.getName());
} else {
String[] resNames= new String[resLength];
entries[NON_JAVA].toArray(resNames);
- packFrag.computeNonJavaResources(resNames, fragInfo, jar.getName());
+ packFrag.computeNonJavaResources(resNames, packFrag, fragInfo, jar.getName());
}
packFrag.computeChildren(fragInfo, entries[JAVA]);
newElements.put(packFrag, fragInfo);
@@ -191,7 +171,16 @@
*/
public Object[] getNonJavaResources() throws JavaModelException {
// We want to show non java resources of the default package at the root (see PR #1G58NB8)
- return ((JarPackageFragment) getPackageFragment(CharOperation.NO_STRINGS)).storedNonJavaResources();
+ Object[] defaultPkgResources = ((JarPackageFragment) getPackageFragment(CharOperation.NO_STRINGS)).storedNonJavaResources();
+ int length = defaultPkgResources.length;
+ if (length == 0)
+ return defaultPkgResources;
+ Object[] nonJavaResources = new Object[length];
+ for (int i = 0; i < length; i++) {
+ JarEntryResource nonJavaResource = (JarEntryResource) defaultPkgResources[i];
+ nonJavaResources[i] = nonJavaResource.clone(this);
+ }
+ return nonJavaResources;
}
public PackageFragment getPackageFragment(String[] pkgName) {
return new JarPackageFragment(this, pkgName);
@@ -233,7 +222,8 @@
public int hashCode() {
return this.jarPath.hashCode();
}
- private String[] initPackageFragToTypes(HashtableOfArrayToObject packageFragToTypes, String entryName, int lastSeparator) {
+ private void initPackageFragToTypes(HashtableOfArrayToObject packageFragToTypes, String entryName, boolean isDirectory) {
+ int lastSeparator = isDirectory ? entryName.length()-1 : entryName.lastIndexOf('/');
String[] pkgName = Util.splitOn('/', entryName, 0, lastSeparator);
String[] existing = null;
int length = pkgName.length;
@@ -244,13 +234,36 @@
existingLength--;
}
JavaModelManager manager = JavaModelManager.getJavaModelManager();
+ IJavaProject project = getJavaProject();
for (int i = existingLength; i < length; i++) {
- System.arraycopy(existing, 0, existing = new String[i+1], 0, i);
- existing[i] = manager.intern(pkgName[i]);
- packageFragToTypes.put(existing, new ArrayList[] { EMPTY_LIST, EMPTY_LIST });
+ if (Util.isValidFolderNameForPackage(pkgName[i], project.getOption(JavaCore.COMPILER_SOURCE, true), project.getOption(JavaCore.COMPILER_COMPLIANCE, true))) {
+ System.arraycopy(existing, 0, existing = new String[i+1], 0, i);
+ existing[i] = manager.intern(pkgName[i]);
+ packageFragToTypes.put(existing, new ArrayList[] { EMPTY_LIST, EMPTY_LIST });
+ } else {
+ // non-Java resource folder
+ if (!isDirectory) {
+ ArrayList[] children = (ArrayList[]) packageFragToTypes.get(existing);
+ if (children[1/*NON_JAVA*/] == EMPTY_LIST) children[1/*NON_JAVA*/] = new ArrayList();
+ children[1/*NON_JAVA*/].add(entryName);
+ }
+ return;
+ }
+ }
+ if (isDirectory)
+ return;
+
+ // add classfile info amongst children
+ ArrayList[] children = (ArrayList[]) packageFragToTypes.get(pkgName);
+ if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(entryName)) {
+ if (children[0/*JAVA*/] == EMPTY_LIST) children[0/*JAVA*/] = new ArrayList();
+ String fileName = entryName.substring(lastSeparator + 1);
+ children[0/*JAVA*/].add(fileName);
+ } else {
+ if (children[1/*NON_JAVA*/] == EMPTY_LIST) children[1/*NON_JAVA*/] = new ArrayList();
+ children[1/*NON_JAVA*/].add(entryName);
}
- return existing;
}
/**
* @see IPackageFragmentRoot
@@ -285,4 +298,11 @@
return super.resourceExists();
}
}
+protected void toStringAncestors(StringBuffer buffer) {
+ if (isExternal())
+ // don't show project as it is irrelevant for external jar files.
+ // also see https://bugs.eclipse.org/bugs/show_bug.cgi?id=146615
+ return;
+ super.toStringAncestors(buffer);
+}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentRootInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentRootInfo.java
index e353be5..26804df 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentRootInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentRootInfo.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaCorePreferenceInitializer.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaCorePreferenceInitializer.java
index 32f0765..ba869ce 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaCorePreferenceInitializer.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaCorePreferenceInitializer.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -13,8 +13,6 @@
import java.util.*;
import org.eclipse.core.runtime.preferences.*;
-import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
-import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
@@ -30,7 +28,7 @@
* @see org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer#initializeDefaultPreferences()
*/
public void initializeDefaultPreferences() {
-
+ // If modified, also modify the method JavaModelManager#getDefaultOptionsNoInitialization()
// Get options names set
HashSet optionNames = JavaModelManager.getJavaModelManager().optionNames;
@@ -45,12 +43,13 @@
defaultOptionsMap.put(JavaCore.COMPILER_TASK_CASE_SENSITIVE, JavaCore.ENABLED);
defaultOptionsMap.put(JavaCore.COMPILER_DOC_COMMENT_SUPPORT, JavaCore.ENABLED);
defaultOptionsMap.put(JavaCore.COMPILER_PB_FORBIDDEN_REFERENCE, JavaCore.ERROR);
-
+
// Builder settings
defaultOptionsMap.put(JavaCore.CORE_JAVA_BUILD_RESOURCE_COPY_FILTER, ""); //$NON-NLS-1$
defaultOptionsMap.put(JavaCore.CORE_JAVA_BUILD_INVALID_CLASSPATH, JavaCore.ABORT);
defaultOptionsMap.put(JavaCore.CORE_JAVA_BUILD_DUPLICATE_RESOURCE, JavaCore.WARNING);
defaultOptionsMap.put(JavaCore.CORE_JAVA_BUILD_CLEAN_OUTPUT_FOLDER, JavaCore.CLEAN);
+ defaultOptionsMap.put(JavaCore.CORE_JAVA_BUILD_RECREATE_MODIFIED_CLASS_FILES_IN_OUTPUT_FOLDER, JavaCore.IGNORE);
// JavaCore settings
defaultOptionsMap.put(JavaCore.CORE_JAVA_BUILD_ORDER, JavaCore.IGNORE);
@@ -73,8 +72,9 @@
}
// CodeAssist settings
- defaultOptionsMap.put(JavaCore.CODEASSIST_VISIBILITY_CHECK, JavaCore.DISABLED); //$NON-NLS-1$
- defaultOptionsMap.put(JavaCore.CODEASSIST_IMPLICIT_QUALIFICATION, JavaCore.DISABLED); //$NON-NLS-1$
+ defaultOptionsMap.put(JavaCore.CODEASSIST_VISIBILITY_CHECK, JavaCore.DISABLED);
+ defaultOptionsMap.put(JavaCore.CODEASSIST_DEPRECATION_CHECK, JavaCore.DISABLED);
+ defaultOptionsMap.put(JavaCore.CODEASSIST_IMPLICIT_QUALIFICATION, JavaCore.DISABLED);
defaultOptionsMap.put(JavaCore.CODEASSIST_FIELD_PREFIXES, ""); //$NON-NLS-1$
defaultOptionsMap.put(JavaCore.CODEASSIST_STATIC_FIELD_PREFIXES, ""); //$NON-NLS-1$
defaultOptionsMap.put(JavaCore.CODEASSIST_LOCAL_PREFIXES, ""); //$NON-NLS-1$
@@ -83,11 +83,16 @@
defaultOptionsMap.put(JavaCore.CODEASSIST_STATIC_FIELD_SUFFIXES, ""); //$NON-NLS-1$
defaultOptionsMap.put(JavaCore.CODEASSIST_LOCAL_SUFFIXES, ""); //$NON-NLS-1$
defaultOptionsMap.put(JavaCore.CODEASSIST_ARGUMENT_SUFFIXES, ""); //$NON-NLS-1$
- defaultOptionsMap.put(JavaCore.CODEASSIST_FORBIDDEN_REFERENCE_CHECK, JavaCore.ENABLED); //$NON-NLS-1$
- defaultOptionsMap.put(JavaCore.CODEASSIST_DISCOURAGED_REFERENCE_CHECK, JavaCore.DISABLED); //$NON-NLS-1$
+ defaultOptionsMap.put(JavaCore.CODEASSIST_FORBIDDEN_REFERENCE_CHECK, JavaCore.ENABLED);
+ defaultOptionsMap.put(JavaCore.CODEASSIST_DISCOURAGED_REFERENCE_CHECK, JavaCore.DISABLED);
+ defaultOptionsMap.put(JavaCore.CODEASSIST_CAMEL_CASE_MATCH, JavaCore.ENABLED);
+ defaultOptionsMap.put(JavaCore.CODEASSIST_SUGGEST_STATIC_IMPORTS, JavaCore.ENABLED);
+ // Time out for parameter names
+ defaultOptionsMap.put(JavaCore.TIMEOUT_FOR_PARAMETER_NAME_FROM_ATTACHED_JAVADOC, "50"); //$NON-NLS-1$
+
// Store default values to default preferences
- IEclipsePreferences defaultPreferences = new DefaultScope().getNode(JavaCore.PLUGIN_ID);
+ IEclipsePreferences defaultPreferences = ((IScopeContext) new DefaultScope()).getNode(JavaCore.PLUGIN_ID);
for (Iterator iter = defaultOptionsMap.entrySet().iterator(); iter.hasNext();) {
Map.Entry entry = (Map.Entry) iter.next();
String optionName = (String) entry.getKey();
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElement.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElement.java
index 06fad7f..1492540 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElement.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElement.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,6 +10,16 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core;
+import java.io.BufferedInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.net.JarURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
import java.util.ArrayList;
import java.util.HashMap;
@@ -29,7 +39,12 @@
* @see IJavaElement
*/
public abstract class JavaElement extends PlatformObject implements IJavaElement {
+// private static final QualifiedName PROJECT_JAVADOC= new QualifiedName(JavaCore.PLUGIN_ID, "project_javadoc_location"); //$NON-NLS-1$
+ private static final byte[] CLOSING_DOUBLE_QUOTE = new byte[] { 34 };
+ private static final byte[] CHARSET = new byte[] {99, 104, 97, 114, 115, 101, 116, 61 };
+ private static final byte[] CONTENT_TYPE = new byte[] { 34, 67, 111, 110, 116, 101, 110, 116, 45, 84, 121, 112, 101, 34 };
+ private static final byte[] CONTENT = new byte[] { 99, 111, 110, 116, 101, 110, 116, 61, 34 };
public static final char JEM_ESCAPE = '\\';
public static final char JEM_JAVAPROJECT = '=';
public static final char JEM_PACKAGEFRAGMENTROOT = '/';
@@ -123,6 +138,7 @@
case JEM_PACKAGEDECLARATION:
case JEM_IMPORTDECLARATION:
case JEM_LOCALVARIABLE:
+ case JEM_TYPE_PARAMETER:
buffer.append(JEM_ESCAPE);
}
buffer.append(character);
@@ -154,6 +170,7 @@
* Puts the newly created element info in the given map.
*/
protected abstract void generateInfos(Object info, HashMap newElements, IProgressMonitor pm) throws JavaModelException;
+
/**
* @see IJavaElement
*/
@@ -516,6 +533,9 @@
public JavaElement resolved(Binding binding) {
return this;
}
+ public JavaElement unresolved() {
+ return this;
+ }
protected String tabString(int tab) {
StringBuffer buffer = new StringBuffer();
for (int i = tab; i > 0; i--)
@@ -611,4 +631,181 @@
protected void toStringName(StringBuffer buffer) {
buffer.append(getElementName());
}
+
+ protected URL getJavadocBaseLocation() throws JavaModelException {
+ IPackageFragmentRoot root= (IPackageFragmentRoot) this.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
+ if (root == null) {
+ return null;
+ }
+
+ if (root.getKind() == IPackageFragmentRoot.K_BINARY) {
+ IClasspathEntry entry= root.getRawClasspathEntry();
+ if (entry == null) {
+ return null;
+ }
+ if (entry.getEntryKind() == IClasspathEntry.CPE_CONTAINER) {
+ entry= getRealClasspathEntry(root.getJavaProject(), entry.getPath(), root.getPath());
+ if (entry == null) {
+ return null;
+ }
+ }
+ return getLibraryJavadocLocation(entry);
+ }
+ return null;
+ }
+
+ private static IClasspathEntry getRealClasspathEntry(IJavaProject jproject, IPath containerPath, IPath libPath) throws JavaModelException {
+ IClasspathContainer container= JavaCore.getClasspathContainer(containerPath, jproject);
+ if (container != null) {
+ IClasspathEntry[] entries= container.getClasspathEntries();
+ for (int i= 0; i < entries.length; i++) {
+ IClasspathEntry curr = entries[i];
+ if (curr == null) {
+ if (JavaModelManager.CP_RESOLVE_VERBOSE) {
+ JavaModelManager.getJavaModelManager().verbose_missbehaving_container(jproject, containerPath, entries);
+ }
+ break;
+ }
+ IClasspathEntry resolved= JavaCore.getResolvedClasspathEntry(curr);
+ if (resolved != null && libPath.equals(resolved.getPath())) {
+ return curr; // return the real entry
+ }
+ }
+ }
+ return null; // not found
+ }
+
+ protected static URL getLibraryJavadocLocation(IClasspathEntry entry) throws JavaModelException {
+ switch(entry.getEntryKind()) {
+ case IClasspathEntry.CPE_LIBRARY :
+ case IClasspathEntry.CPE_VARIABLE :
+ break;
+ default :
+ throw new IllegalArgumentException("Entry must be of kind CPE_LIBRARY or CPE_VARIABLE"); //$NON-NLS-1$
+ }
+
+ IClasspathAttribute[] extraAttributes= entry.getExtraAttributes();
+ for (int i= 0; i < extraAttributes.length; i++) {
+ IClasspathAttribute attrib= extraAttributes[i];
+ if (IClasspathAttribute.JAVADOC_LOCATION_ATTRIBUTE_NAME.equals(attrib.getName())) {
+ String value = attrib.getValue();
+ try {
+ return new URL(value);
+ } catch (MalformedURLException e) {
+ throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.CANNOT_RETRIEVE_ATTACHED_JAVADOC, value));
+ }
+ }
+ }
+ return null;
+ }
+
+ /*
+ * @see IJavaElement#getAttachedJavadoc(IProgressMonitor)
+ */
+ public String getAttachedJavadoc(IProgressMonitor monitor) throws JavaModelException {
+ return null;
+ }
+
+ int getIndexOf(byte[] array, byte[] toBeFound, int start) {
+ if (array == null || toBeFound == null)
+ return -1;
+ final int toBeFoundLength = toBeFound.length;
+ final int arrayLength = array.length;
+ if (arrayLength < toBeFoundLength)
+ return -1;
+ loop: for (int i = start, max = arrayLength - toBeFoundLength + 1; i < max; i++) {
+ if (array[i] == toBeFound[0]) {
+ for (int j = 1; j < toBeFoundLength; j++) {
+ if (array[i + j] != toBeFound[j])
+ continue loop;
+ }
+ return i;
+ }
+ }
+ return -1;
+ }
+ /*
+ * We don't use getContentEncoding() on the URL connection, because it might leave open streams behind.
+ * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=117890
+ */
+ protected String getURLContents(String docUrlValue) throws JavaModelException {
+ InputStream stream = null;
+ JarURLConnection connection2 = null;
+ try {
+ URL docUrl = new URL(docUrlValue);
+ URLConnection connection = docUrl.openConnection();
+ if (connection instanceof JarURLConnection) {
+ connection2 = (JarURLConnection) connection;
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=156307
+ connection.setUseCaches(false);
+ }
+ stream = new BufferedInputStream(connection.getInputStream());
+ String encoding = connection.getContentEncoding();
+ byte[] contents = org.eclipse.jdt.internal.compiler.util.Util.getInputStreamAsByteArray(stream, connection.getContentLength());
+ if (encoding == null) {
+ int index = getIndexOf(contents, CONTENT_TYPE, 0);
+ if (index != -1) {
+ index = getIndexOf(contents, CONTENT, index);
+ if (index != -1) {
+ int offset = index + CONTENT.length;
+ int index2 = getIndexOf(contents, CLOSING_DOUBLE_QUOTE, offset);
+ if (index2 != -1) {
+ final int charsetIndex = getIndexOf(contents, CHARSET, offset);
+ if (charsetIndex != -1) {
+ int start = charsetIndex + CHARSET.length;
+ encoding = new String(contents, start, index2 - start, "UTF-8"); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+ }
+ try {
+ if (encoding == null) {
+ encoding = this.getJavaProject().getProject().getDefaultCharset();
+ }
+ } catch (CoreException e) {
+ // ignore
+ }
+ if (contents != null) {
+ if (encoding != null) {
+ return new String(contents, encoding);
+ } else {
+ // platform encoding is used
+ return new String(contents);
+ }
+ }
+ } catch (MalformedURLException e) {
+ throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.CANNOT_RETRIEVE_ATTACHED_JAVADOC, this));
+ } catch (FileNotFoundException e) {
+ // ignore. see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=120559
+ } catch(IOException e) {
+ StringWriter stringWriter = new StringWriter();
+ PrintWriter writer = new PrintWriter(stringWriter);
+ e.printStackTrace(writer);
+ writer.flush();
+ writer.close();
+ throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.CANNOT_RETRIEVE_ATTACHED_JAVADOC, this, String.valueOf(stringWriter.getBuffer())));
+ } finally {
+ if (stream != null) {
+ try {
+ stream.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ if (connection2 != null) {
+ try {
+ connection2.getJarFile().close();
+ } catch(IOException e) {
+ // ignore
+ } catch(IllegalStateException e) {
+ /*
+ * ignore. Can happen in case the stream.close() did close the jar file
+ * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=140750
+ */
+ }
+ }
+ }
+ return null;
+ }
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementDelta.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementDelta.java
index 401810c..070b303 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementDelta.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementDelta.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -15,6 +15,7 @@
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaElementDelta;
+import org.eclipse.jdt.core.dom.CompilationUnit;
/**
* @see IJavaElementDelta
@@ -23,7 +24,16 @@
/**
* @see #getAffectedChildren()
*/
- protected IJavaElementDelta[] fAffectedChildren = fgEmptyDelta;
+ protected IJavaElementDelta[] affectedChildren = EMPTY_DELTA;
+
+ /*
+ * The AST created during the last reconcile operation.
+ * Non-null only iff:
+ * - in a POST_RECONCILE event
+ * - an AST was requested during the last reconcile operation
+ * - the changed element is an ICompilationUnit in working copy mode
+ */
+ protected CompilationUnit ast = null;
/*
* The element that this delta describes the change to.
@@ -42,15 +52,15 @@
/**
* @see #getMovedFromElement()
*/
- protected IJavaElement fMovedFromHandle = null;
+ protected IJavaElement movedFromHandle = null;
/**
* @see #getMovedToElement()
*/
- protected IJavaElement fMovedToHandle = null;
+ protected IJavaElement movedToHandle = null;
/**
* Empty array of IJavaElementDelta
*/
- protected static IJavaElementDelta[] fgEmptyDelta= new IJavaElementDelta[] {};
+ protected static IJavaElementDelta[] EMPTY_DELTA= new IJavaElementDelta[] {};
/**
* Creates the root delta. To create the nested delta
* hierarchies use the following convenience methods. The root
@@ -91,23 +101,23 @@
this.fineGrained();
}
- if (fAffectedChildren.length == 0) {
- fAffectedChildren = new IJavaElementDelta[] {child};
+ if (this.affectedChildren.length == 0) {
+ this.affectedChildren = new IJavaElementDelta[] {child};
return;
}
JavaElementDelta existingChild = null;
int existingChildIndex = -1;
- if (fAffectedChildren != null) {
- for (int i = 0; i < fAffectedChildren.length; i++) {
- if (this.equalsAndSameParent(fAffectedChildren[i].getElement(), child.getElement())) { // handle case of two jars that can be equals but not in the same project
- existingChild = (JavaElementDelta)fAffectedChildren[i];
+ if (this.affectedChildren != null) {
+ for (int i = 0; i < this.affectedChildren.length; i++) {
+ if (this.equalsAndSameParent(this.affectedChildren[i].getElement(), child.getElement())) { // handle case of two jars that can be equals but not in the same project
+ existingChild = (JavaElementDelta)this.affectedChildren[i];
existingChildIndex = i;
break;
}
}
}
if (existingChild == null) { //new affected child
- fAffectedChildren= growAndAddToArray(fAffectedChildren, child);
+ this.affectedChildren= growAndAddToArray(this.affectedChildren, child);
} else {
switch (existingChild.getKind()) {
case ADDED:
@@ -116,7 +126,7 @@
case CHANGED: // child was added then changed -> it is added
return;
case REMOVED: // child was added then removed -> noop
- fAffectedChildren = this.removeAndShrinkArray(fAffectedChildren, existingChildIndex);
+ this.affectedChildren = this.removeAndShrinkArray(this.affectedChildren, existingChildIndex);
return;
}
break;
@@ -124,7 +134,7 @@
switch (child.getKind()) {
case ADDED: // child was removed then added -> it is changed
child.kind = CHANGED;
- fAffectedChildren[existingChildIndex] = child;
+ this.affectedChildren[existingChildIndex] = child;
return;
case CHANGED: // child was removed then changed -> it is removed
case REMOVED: // child was removed then removed -> it is removed
@@ -135,7 +145,7 @@
switch (child.getKind()) {
case ADDED: // child was changed then added -> it is added
case REMOVED: // child was changed then removed -> it is removed
- fAffectedChildren[existingChildIndex] = child;
+ this.affectedChildren[existingChildIndex] = child;
return;
case CHANGED: // child was changed then changed -> it is changed
IJavaElementDelta[] children = child.getAffectedChildren();
@@ -164,13 +174,14 @@
existingChild.resourceDeltas = resDeltas;
existingChild.resourceDeltasCounter = child.resourceDeltasCounter;
}
+
return;
}
break;
default:
// unknown -> existing child becomes the child with the existing child's flags
int flags = existingChild.getFlags();
- fAffectedChildren[existingChildIndex] = child;
+ this.affectedChildren[existingChildIndex] = child;
child.changeFlags |= flags;
}
}
@@ -230,6 +241,13 @@
insertDeltaTree(element, changedDelta);
return changedDelta;
}
+/*
+ * Records the last changed AST .
+ */
+public void changedAST(CompilationUnit changedAST) {
+ this.ast = changedAST;
+ changed(F_AST_AFFECTED);
+}
/**
* Mark this delta as a content changed delta.
*/
@@ -257,8 +275,8 @@
// the element being changed is the root element
this.kind= delta.kind;
this.changeFlags = delta.changeFlags;
- fMovedToHandle = delta.fMovedToHandle;
- fMovedFromHandle = delta.fMovedFromHandle;
+ this.movedToHandle = delta.movedToHandle;
+ this.movedFromHandle = delta.movedFromHandle;
}
} else {
for (int i = 0, size = ancestors.size(); i < size; i++) {
@@ -285,8 +303,8 @@
if (this.equalsAndSameParent(this.changedElement, e)) { // handle case of two jars that can be equals but not in the same project
return this;
} else {
- for (int i = 0; i < fAffectedChildren.length; i++) {
- JavaElementDelta delta = ((JavaElementDelta)fAffectedChildren[i]).find(e);
+ for (int i = 0; i < this.affectedChildren.length; i++) {
+ JavaElementDelta delta = ((JavaElementDelta)this.affectedChildren[i]).find(e);
if (delta != null) {
return delta;
}
@@ -310,7 +328,7 @@
* @see IJavaElementDelta
*/
public IJavaElementDelta[] getAffectedChildren() {
- return fAffectedChildren;
+ return this.affectedChildren;
}
/**
* Returns a collection of all the parents of this element up to (but
@@ -334,6 +352,9 @@
parents.trimToSize();
return parents;
}
+public CompilationUnit getCompilationUnitAST() {
+ return this.ast;
+}
/**
* @see IJavaElementDelta
*/
@@ -344,14 +365,14 @@
* @see IJavaElementDelta
*/
protected IJavaElementDelta[] getChildrenOfType(int type) {
- int length = fAffectedChildren.length;
+ int length = this.affectedChildren.length;
if (length == 0) {
return new IJavaElementDelta[] {};
}
ArrayList children= new ArrayList(length);
for (int i = 0; i < length; i++) {
- if (fAffectedChildren[i].getKind() == type) {
- children.add(fAffectedChildren[i]);
+ if (this.affectedChildren[i].getKind() == type) {
+ children.add(this.affectedChildren[i]);
}
}
@@ -367,11 +388,11 @@
protected JavaElementDelta getDeltaFor(IJavaElement element) {
if (this.equalsAndSameParent(getElement(), element)) // handle case of two jars that can be equals but not in the same project
return this;
- if (fAffectedChildren.length == 0)
+ if (this.affectedChildren.length == 0)
return null;
- int childrenCount = fAffectedChildren.length;
+ int childrenCount = this.affectedChildren.length;
for (int i = 0; i < childrenCount; i++) {
- JavaElementDelta delta = (JavaElementDelta)fAffectedChildren[i];
+ JavaElementDelta delta = (JavaElementDelta)this.affectedChildren[i];
if (this.equalsAndSameParent(delta.getElement(), element)) { // handle case of two jars that can be equals but not in the same project
return delta;
} else {
@@ -392,13 +413,13 @@
* @see IJavaElementDelta
*/
public IJavaElement getMovedFromElement() {
- return fMovedFromHandle;
+ return this.movedFromHandle;
}
/**
* @see IJavaElementDelta
*/
public IJavaElement getMovedToElement() {
- return fMovedToHandle;
+ return movedToHandle;
}
/**
* @see IJavaElementDelta
@@ -447,7 +468,7 @@
JavaElementDelta removedDelta = new JavaElementDelta(movedFromElement);
removedDelta.kind = REMOVED;
removedDelta.changeFlags |= F_MOVED_TO;
- removedDelta.fMovedToHandle = movedToElement;
+ removedDelta.movedToHandle = movedToElement;
insertDeltaTree(movedFromElement, removedDelta);
}
/**
@@ -460,7 +481,7 @@
JavaElementDelta addedDelta = new JavaElementDelta(movedToElement);
addedDelta.kind = ADDED;
addedDelta.changeFlags |= F_MOVED_FROM;
- addedDelta.fMovedFromHandle = movedFromElement;
+ addedDelta.movedFromHandle = movedFromElement;
insertDeltaTree(movedToElement, addedDelta);
}
/**
@@ -476,16 +497,16 @@
*/
protected void removeAffectedChild(JavaElementDelta child) {
int index = -1;
- if (fAffectedChildren != null) {
- for (int i = 0; i < fAffectedChildren.length; i++) {
- if (this.equalsAndSameParent(fAffectedChildren[i].getElement(), child.getElement())) { // handle case of two jars that can be equals but not in the same project
+ if (this.affectedChildren != null) {
+ for (int i = 0; i < this.affectedChildren.length; i++) {
+ if (this.equalsAndSameParent(this.affectedChildren[i].getElement(), child.getElement())) { // handle case of two jars that can be equals but not in the same project
index = i;
break;
}
}
}
if (index >= 0) {
- fAffectedChildren= removeAndShrinkArray(fAffectedChildren, index);
+ this.affectedChildren= removeAndShrinkArray(this.affectedChildren, index);
}
}
/**
@@ -517,7 +538,7 @@
if (actualDelta != null) {
actualDelta.removed();
actualDelta.changeFlags |= flags;
- actualDelta.fAffectedChildren = fgEmptyDelta;
+ actualDelta.affectedChildren = EMPTY_DELTA;
}
}
/**
@@ -687,6 +708,18 @@
buffer.append("CLOSED"); //$NON-NLS-1$
prev = true;
}
+ if ((flags & IJavaElementDelta.F_AST_AFFECTED) != 0) {
+ if (prev)
+ buffer.append(" | "); //$NON-NLS-1$
+ buffer.append("AST AFFECTED"); //$NON-NLS-1$
+ prev = true;
+ }
+ if ((flags & IJavaElementDelta.F_CATEGORIES) != 0) {
+ if (prev)
+ buffer.append(" | "); //$NON-NLS-1$
+ buffer.append("CATEGORIES"); //$NON-NLS-1$
+ prev = true;
+ }
return prev;
}
/**
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementDeltaBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementDeltaBuilder.java
index afe4ea1..5be0890 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementDeltaBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementDeltaBuilder.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -12,14 +12,17 @@
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
+import java.util.Set;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaElementDelta;
import org.eclipse.jdt.core.IParent;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.core.util.Util;
/**
* A java element delta biulder creates a java element delta on
@@ -61,7 +64,7 @@
/**
* Change delta
*/
- JavaElementDelta delta;
+ public JavaElementDelta delta = null;
/**
* List of added elements
@@ -76,7 +79,7 @@
/**
* Doubly linked list item
*/
- class ListItem {
+ static class ListItem {
public IJavaElement previous;
public IJavaElement next;
@@ -132,6 +135,12 @@
* unit and its new content.
*/
public void buildDeltas() {
+ this.delta = new JavaElementDelta(this.javaElement);
+ // if building a delta on a compilation unit or below,
+ // it's a fine grained delta
+ if (this.javaElement.getElementType() >= IJavaElement.COMPILATION_UNIT) {
+ this.delta.fineGrained();
+ }
this.recordNewPositions(this.javaElement, 0);
this.findAdditions(this.javaElement, 0);
this.findDeletions();
@@ -255,6 +264,32 @@
|| !equals(oldSourceTypeInfo.getTypeParameterBounds(), newSourceTypeInfo.getTypeParameterBounds())) {
this.delta.changed(newElement, IJavaElementDelta.F_CONTENT);
}
+ HashMap oldTypeCategories = oldSourceTypeInfo.categories;
+ HashMap newTypeCategories = newSourceTypeInfo.categories;
+ if (oldTypeCategories != null) {
+ // take the union of old and new categories elements (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=125675)
+ Set elements;
+ if (newTypeCategories != null) {
+ elements = new HashSet(oldTypeCategories.keySet());
+ elements.addAll(newTypeCategories.keySet());
+ } else
+ elements = oldTypeCategories.keySet();
+ Iterator iterator = elements.iterator();
+ while (iterator.hasNext()) {
+ IJavaElement element = (IJavaElement) iterator.next();
+ String[] oldCategories = (String[]) oldTypeCategories.get(element);
+ String[] newCategories = newTypeCategories == null ? null : (String[]) newTypeCategories.get(element);
+ if (!Util.equalArraysOrNull(oldCategories, newCategories)) {
+ this.delta.changed(element, IJavaElementDelta.F_CATEGORIES);
+ }
+ }
+ } else if (newTypeCategories != null) {
+ Iterator elements = newTypeCategories.keySet().iterator();
+ while (elements.hasNext()) {
+ IJavaElement element = (IJavaElement) elements.next();
+ this.delta.changed(element, IJavaElementDelta.F_CATEGORIES); // all categories for this element were removed
+ }
+ }
}
}
/**
@@ -282,15 +317,7 @@
this.oldPositions = new HashMap(20);
this.newPositions = new HashMap(20);
this.putOldPosition(this.javaElement, new ListItem(null, null));
- this.putNewPosition(this.javaElement, new ListItem(null, null));
- this.delta = new JavaElementDelta(javaElement);
-
- // if building a delta on a compilation unit or below,
- // it's a fine grained delta
- if (javaElement.getElementType() >= IJavaElement.COMPILATION_UNIT) {
- this.delta.fineGrained();
- }
-
+ this.putNewPosition(this.javaElement, new ListItem(null, null));
this.added = new ArrayList(5);
this.removed = new ArrayList(5);
}
@@ -405,7 +432,7 @@
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append("Built delta:\n"); //$NON-NLS-1$
- buffer.append(this.delta.toString());
+ buffer.append(this.delta == null ? "<null>" : this.delta.toString()); //$NON-NLS-1$
return buffer.toString();
}
/**
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementInfo.java
index f45a060..ea1e690 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementInfo.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -34,12 +34,16 @@
this.children = JavaElement.NO_ELEMENTS;
}
public void addChild(IJavaElement child) {
- if (this.children == JavaElement.NO_ELEMENTS) {
- setChildren(new IJavaElement[] {child});
+ int length = this.children.length;
+ if (length == 0) {
+ this.children = new IJavaElement[] {child};
} else {
- if (!includesChild(child)) {
- setChildren(growAndAddToArray(this.children, child));
+ for (int i = 0; i < length; i++) {
+ if (children[i].equals(child))
+ return; // already included
}
+ System.arraycopy(this.children, 0, this.children = new IJavaElement[length+1], 0, length);
+ this.children[length] = child;
}
}
public Object clone() {
@@ -53,51 +57,21 @@
public IJavaElement[] getChildren() {
return this.children;
}
- /**
- * 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 < this.children.length; i++) {
- if (this.children[i].equals(child)) {
- return true;
- }
- }
- return false;
- }
- /**
- * 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(this.children, child));
+ for (int i = 0, length = this.children.length; i < length; i++) {
+ IJavaElement element = this.children[i];
+ if (element.equals(child)) {
+ if (length == 1) {
+ this.children = JavaElement.NO_ELEMENTS;
+ } else {
+ IJavaElement[] newChildren = new IJavaElement[length-1];
+ System.arraycopy(this.children, 0, newChildren , 0, i);
+ if (i < length-1)
+ System.arraycopy(this.children, i+1, newChildren, i, length-1-i);
+ this.children = newChildren;
+ }
+ break;
+ }
}
}
public void setChildren(IJavaElement[] children) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementRequestor.java
index ddcd8d2..97751d5 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementRequestor.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModel.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModel.java
index cbebfbe..519bf7a 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModel.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModel.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -22,14 +22,11 @@
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.*;
-import org.eclipse.jdt.core.IJavaElement;
-import org.eclipse.jdt.core.IJavaModel;
-import org.eclipse.jdt.core.IJavaProject;
-import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.core.util.MementoTokenizer;
import org.eclipse.jdt.internal.core.util.Messages;
@@ -72,12 +69,18 @@
// determine my children
IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
- for (int i = 0, max = projects.length; i < max; i++) {
+ int length = projects.length;
+ IJavaElement[] children = new IJavaElement[length];
+ int index = 0;
+ for (int i = 0; i < length; i++) {
IProject project = projects[i];
if (JavaProject.hasJavaNature(project)) {
- info.addChild(getJavaProject(project));
+ children[index++] = getJavaProject(project);
}
}
+ if (index < length)
+ System.arraycopy(children, 0, children = new IJavaElement[index], 0, index);
+ info.setChildren(children);
newElements.put(this, info);
@@ -139,24 +142,6 @@
return super.equals(o);
}
/**
- * Finds the given project in the list of the java model's children.
- * Returns null if not found.
- */
-public IJavaProject findJavaProject(IProject project) {
- try {
- IJavaProject[] projects = this.getOldJavaProjectsList();
- for (int i = 0, length = projects.length; i < length; i++) {
- IJavaProject javaProject = projects[i];
- if (project.equals(javaProject.getProject())) {
- return javaProject;
- }
- }
- } catch (JavaModelException e) {
- // java model doesn't exist: cannot find any project
- }
- return null;
-}
-/**
* @see IJavaElement
*/
public int getElementType() {
@@ -240,17 +225,6 @@
return ((JavaModelInfo) getElementInfo()).getNonJavaResources();
}
-/**
- * Workaround for bug 15168 circular errors not reported
- * Returns the list of java projects before resource delta processing
- * has started.
- */
-public IJavaProject[] getOldJavaProjectsList() throws JavaModelException {
- JavaModelManager manager = JavaModelManager.getJavaModelManager();
- return manager.deltaState.modelProjectsCache == null ?
- this.getJavaProjects() :
- manager.deltaState.modelProjectsCache;
-}
/*
* @see IJavaElement
*/
@@ -358,6 +332,9 @@
if (!path.isAbsolute()) return null;
// lookup - outside the container
+ return getTargetAsExternalFile(path, checkResourceExistence);
+}
+private synchronized static Object getTargetAsExternalFile(IPath path, boolean checkResourceExistence) {
File externalFile = new File(path.toOSString());
if (!checkResourceExistence) {
return externalFile;
@@ -373,7 +350,7 @@
return externalFile;
}
}
- return null;
+ return null;
}
/**
@@ -387,7 +364,7 @@
* Helper method - returns the file item (ie. which returns true to {@link java.io.File#isFile()},
* or null if unbound
*/
-public static File getFile(Object target) {
+public static synchronized File getFile(Object target) {
if (existingExternalConfirmedFiles.contains(target))
return (File) target;
if (target instanceof File) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelCache.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelCache.java
index 4a96fd3..ee2d80b 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelCache.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelCache.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -9,22 +9,30 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.core;
-import java.text.NumberFormat;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.internal.core.util.LRUCache;
/**
* The cache of java elements to their respective info.
*/
public class JavaModelCache {
- public static final int BASE_VALUE = 20;
+ public static boolean VERBOSE = false;
+
public static final int DEFAULT_PROJECT_SIZE = 5; // average 25552 bytes per project.
- public static final int DEFAULT_ROOT_SIZE = BASE_VALUE*10; // average 2590 bytes per root -> maximum size : 25900*BASE_VALUE bytes
- public static final int DEFAULT_PKG_SIZE = BASE_VALUE*100; // average 1782 bytes per pkg -> maximum size : 178200*BASE_VALUE bytes
- public static final int DEFAULT_OPENABLE_SIZE = BASE_VALUE*100; // average 6629 bytes per openable (includes children) -> maximum size : 662900*BASE_VALUE bytes
- public static final int DEFAULT_CHILDREN_SIZE = BASE_VALUE*100*20; // average 20 children per openable
+ public static final int DEFAULT_ROOT_SIZE = 50; // average 2590 bytes per root -> maximum size : 25900*BASE_VALUE bytes
+ public static final int DEFAULT_PKG_SIZE = 500; // average 1782 bytes per pkg -> maximum size : 178200*BASE_VALUE bytes
+ public static final int DEFAULT_OPENABLE_SIZE = 500; // average 6629 bytes per openable (includes children) -> maximum size : 662900*BASE_VALUE bytes
+ public static final int DEFAULT_CHILDREN_SIZE = 500*20; // average 20 children per openable
+
+ public static final Object NON_EXISTING_JAR_TYPE_INFO = new Object();
+
+ /*
+ * The memory ratio that should be applied to the above constants.
+ */
+ protected double memoryRatio = -1;
/**
* Active Java Model Info
@@ -56,12 +64,26 @@
*/
protected Map childrenCache;
+ /*
+ * Cache of open binary type (inside a jar) that have a non-open parent
+ */
+ protected LRUCache jarTypeCache;
+
public JavaModelCache() {
+ // set the size of the caches in function of the maximum amount of memory available
+ double ratio = getMemoryRatio();
this.projectCache = new HashMap(DEFAULT_PROJECT_SIZE); // NB: Don't use a LRUCache for projects as they are constantly reopened (e.g. during delta processing)
- this.rootCache = new ElementCache(DEFAULT_ROOT_SIZE);
- this.pkgCache = new ElementCache(DEFAULT_PKG_SIZE);
- this.openableCache = new ElementCache(DEFAULT_OPENABLE_SIZE);
- this.childrenCache = new HashMap(DEFAULT_CHILDREN_SIZE);
+ if (VERBOSE) {
+ this.rootCache = new VerboseElementCache((int) (DEFAULT_ROOT_SIZE * ratio), "Root cache"); //$NON-NLS-1$
+ this.pkgCache = new VerboseElementCache((int) (DEFAULT_PKG_SIZE * ratio), "Package cache"); //$NON-NLS-1$
+ this.openableCache = new VerboseElementCache((int) (DEFAULT_OPENABLE_SIZE * ratio), "Openable cache"); //$NON-NLS-1$
+ } else {
+ this.rootCache = new ElementCache((int) (DEFAULT_ROOT_SIZE * ratio));
+ this.pkgCache = new ElementCache((int) (DEFAULT_PKG_SIZE * ratio));
+ this.openableCache = new ElementCache((int) (DEFAULT_OPENABLE_SIZE * ratio));
+ }
+ this.childrenCache = new HashMap((int) (DEFAULT_CHILDREN_SIZE * ratio));
+ resetJarTypeCache();
}
/**
@@ -80,11 +102,27 @@
case IJavaElement.COMPILATION_UNIT:
case IJavaElement.CLASS_FILE:
return this.openableCache.get(element);
+ case IJavaElement.TYPE:
+ Object result = this.jarTypeCache.get(element);
+ if (result != null)
+ return result;
+ else
+ return this.childrenCache.get(element);
default:
return this.childrenCache.get(element);
}
}
+protected double getMemoryRatio() {
+ if (this.memoryRatio == -1) {
+ long maxMemory = Runtime.getRuntime().maxMemory();
+ // if max memory is infinite, set the ratio to 4d which corresponds to the 256MB that Eclipse defaults to
+ // (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=111299)
+ this.memoryRatio = maxMemory == Long.MAX_VALUE ? 4d : ((double) maxMemory) / (64 * 0x100000); // 64MB is the base memory for most JVM
+ }
+ return this.memoryRatio;
+}
+
/**
* Returns the info for this element without
* disturbing the cache ordering.
@@ -102,6 +140,12 @@
case IJavaElement.COMPILATION_UNIT:
case IJavaElement.CLASS_FILE:
return this.openableCache.peek(element);
+ case IJavaElement.TYPE:
+ Object result = this.jarTypeCache.peek(element);
+ if (result != null)
+ return result;
+ else
+ return this.childrenCache.get(element);
default:
return this.childrenCache.get(element);
}
@@ -138,22 +182,22 @@
/**
* Removes the info of the element from the cache.
*/
-protected void removeInfo(IJavaElement element) {
+protected void removeInfo(JavaElement element) {
switch (element.getElementType()) {
case IJavaElement.JAVA_MODEL:
this.modelInfo = null;
break;
case IJavaElement.JAVA_PROJECT:
this.projectCache.remove(element);
- this.rootCache.resetSpaceLimit(DEFAULT_ROOT_SIZE, element);
+ this.rootCache.resetSpaceLimit((int) (DEFAULT_ROOT_SIZE * getMemoryRatio()), element);
break;
case IJavaElement.PACKAGE_FRAGMENT_ROOT:
this.rootCache.remove(element);
- this.pkgCache.resetSpaceLimit(DEFAULT_PKG_SIZE, element);
+ this.pkgCache.resetSpaceLimit((int) (DEFAULT_PKG_SIZE * getMemoryRatio()), element);
break;
case IJavaElement.PACKAGE_FRAGMENT:
this.pkgCache.remove(element);
- this.openableCache.resetSpaceLimit(DEFAULT_OPENABLE_SIZE, element);
+ this.openableCache.resetSpaceLimit((int) (DEFAULT_OPENABLE_SIZE * getMemoryRatio()), element);
break;
case IJavaElement.COMPILATION_UNIT:
case IJavaElement.CLASS_FILE:
@@ -163,6 +207,12 @@
this.childrenCache.remove(element);
}
}
+protected void resetJarTypeCache() {
+ this.jarTypeCache = new LRUCache((int) (DEFAULT_OPENABLE_SIZE * getMemoryRatio()));
+}
+public String toString() {
+ return toStringFillingRation(""); //$NON-NLS-1$
+}
public String toStringFillingRation(String prefix) {
StringBuffer buffer = new StringBuffer();
buffer.append(prefix);
@@ -170,23 +220,17 @@
buffer.append(this.projectCache.size());
buffer.append(" projects\n"); //$NON-NLS-1$
buffer.append(prefix);
- buffer.append("Root cache["); //$NON-NLS-1$
- buffer.append(this.rootCache.getSpaceLimit());
- buffer.append("]: "); //$NON-NLS-1$
- buffer.append(NumberFormat.getInstance().format(this.rootCache.fillingRatio()));
- buffer.append("%\n"); //$NON-NLS-1$
+ buffer.append(this.rootCache.toStringFillingRation("Root cache")); //$NON-NLS-1$
+ buffer.append('\n');
buffer.append(prefix);
- buffer.append("Package cache["); //$NON-NLS-1$
- buffer.append(this.pkgCache.getSpaceLimit());
- buffer.append("]: "); //$NON-NLS-1$
- buffer.append(NumberFormat.getInstance().format(this.pkgCache.fillingRatio()));
- buffer.append("%\n"); //$NON-NLS-1$
+ buffer.append(this.pkgCache.toStringFillingRation("Package cache")); //$NON-NLS-1$
+ buffer.append('\n');
buffer.append(prefix);
- buffer.append("Openable cache["); //$NON-NLS-1$
- buffer.append(this.openableCache.getSpaceLimit());
- buffer.append("]: "); //$NON-NLS-1$
- buffer.append(NumberFormat.getInstance().format(this.openableCache.fillingRatio()));
- buffer.append("%\n"); //$NON-NLS-1$
+ buffer.append(this.openableCache.toStringFillingRation("Openable cache")); //$NON-NLS-1$
+ buffer.append('\n');
+ buffer.append(prefix);
+ buffer.append(this.jarTypeCache.toStringFillingRation("Jar type cache")); //$NON-NLS-1$
+ buffer.append('\n');
return buffer.toString();
}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelInfo.java
index 2451d41..3f020e2 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelInfo.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java
index c1758f4..4c5263f 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -7,11 +7,17 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Theodora Yeung (tyeung@bea.com) - ensure that JarPackageFragmentRoot make it into cache
+ * before its contents
+ * (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=102422)
*******************************************************************************/
package org.eclipse.jdt.internal.core;
import java.io.*;
+import java.net.URI;
+import java.text.MessageFormat;
import java.util.*;
+import java.util.Map.Entry;
import java.util.zip.ZipFile;
import javax.xml.parsers.DocumentBuilder;
@@ -20,28 +26,42 @@
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
+import org.eclipse.core.runtime.content.IContentTypeManager.ContentTypeChangeEvent;
+import org.eclipse.core.runtime.content.IContentTypeManager.IContentTypeChangeListener;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.preferences.DefaultScope;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.IPreferencesService;
+import org.eclipse.core.runtime.preferences.IScopeContext;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.jdt.core.*;
import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.compiler.CompilationParticipant;
import org.eclipse.jdt.core.compiler.IProblem;
+import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
import org.eclipse.jdt.internal.codeassist.CompletionEngine;
import org.eclipse.jdt.internal.codeassist.SelectionEngine;
+import org.eclipse.jdt.internal.compiler.AbstractAnnotationProcessorManager;
import org.eclipse.jdt.internal.compiler.Compiler;
-import org.eclipse.jdt.internal.compiler.util.WeakHashSet;
-import org.eclipse.jdt.internal.compiler.util.WeakHashSetOfCharArray;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jdt.internal.compiler.util.HashtableOfObjectToInt;
+import org.eclipse.jdt.internal.core.JavaProjectElementInfo.ProjectCache;
import org.eclipse.jdt.internal.core.builder.JavaBuilder;
import org.eclipse.jdt.internal.core.hierarchy.TypeHierarchy;
import org.eclipse.jdt.internal.core.search.AbstractSearchScope;
import org.eclipse.jdt.internal.core.search.BasicSearchEngine;
+import org.eclipse.jdt.internal.core.search.IRestrictedAccessTypeRequestor;
import org.eclipse.jdt.internal.core.search.JavaWorkspaceScope;
import org.eclipse.jdt.internal.core.search.indexing.IndexManager;
import org.eclipse.jdt.internal.core.search.processing.JobManager;
+import org.eclipse.jdt.internal.core.util.HashtableOfArrayToObject;
+import org.eclipse.jdt.internal.core.util.LRUCache;
import org.eclipse.jdt.internal.core.util.Messages;
import org.eclipse.jdt.internal.core.util.Util;
+import org.eclipse.jdt.internal.core.util.WeakHashSet;
+import org.eclipse.jdt.internal.core.util.WeakHashSetOfCharArray;
import org.osgi.service.prefs.BackingStoreException;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
@@ -57,7 +77,7 @@
* The single instance of <code>JavaModelManager</code> is available from
* the static method <code>JavaModelManager.getJavaModelManager()</code>.
*/
-public class JavaModelManager implements ISaveParticipant {
+public class JavaModelManager implements ISaveParticipant, IContentTypeChangeListener {
/**
* Unique handle onto the JavaModel
@@ -68,9 +88,12 @@
* Classpath variables pool
*/
public HashMap variables = new HashMap(5);
+ public HashSet variablesWithInitializer = new HashSet(5);
+ public HashMap deprecatedVariables = new HashMap(5);
+ public HashSet readOnlyVariables = new HashSet(5);
public HashMap previousSessionVariables = new HashMap(5);
private ThreadLocal variableInitializationInProgress = new ThreadLocal();
-
+
/**
* Classpath containers pool
*/
@@ -78,6 +101,7 @@
public HashMap previousSessionContainers = new HashMap(5);
private ThreadLocal containerInitializationInProgress = new ThreadLocal();
public boolean batchContainerInitializations = false;
+ public ThreadLocal batchContainerInitializationsProgress = new ThreadLocal();
public HashMap containerInitializersCache = new HashMap(5);
/*
@@ -96,12 +120,24 @@
*/
private WeakHashSet stringSymbols = new WeakHashSet(5);
private WeakHashSetOfCharArray charArraySymbols = new WeakHashSetOfCharArray(5);
+
+ /*
+ * Extension used to construct Java 6 annotation processor managers
+ */
+ private IConfigurationElement annotationProcessorManagerFactory = null;
+
+ /*
+ * Map from a package fragment root's path to a source attachment property (source path + ATTACHMENT_PROPERTY_DELIMITER + source root path)
+ */
+ public Map rootPathToAttachments = new HashMap();
public final static String CP_VARIABLE_PREFERENCES_PREFIX = JavaCore.PLUGIN_ID+".classpathVariable."; //$NON-NLS-1$
public final static String CP_CONTAINER_PREFERENCES_PREFIX = JavaCore.PLUGIN_ID+".classpathContainer."; //$NON-NLS-1$
public final static String CP_ENTRY_IGNORE = "##<cp entry ignore>##"; //$NON-NLS-1$
+ public final static IPath CP_ENTRY_IGNORE_PATH = new Path(CP_ENTRY_IGNORE);
+ public final static String TRUE = "true"; //$NON-NLS-1$
- private final static int VARIABLES_AND_CONTAINERS_FILE_VERSION = 1;
+ private final static int VARIABLES_AND_CONTAINERS_FILE_VERSION = 2;
/**
* Name of the extension point for contributing classpath variable initializers
@@ -119,10 +155,15 @@
public static final String FORMATTER_EXTPOINT_ID = "codeFormatter" ; //$NON-NLS-1$
/**
- * Value of the content-type for Java source files
+ * Name of the extension point for contributing a compilation participant
*/
- public static final String JAVA_SOURCE_CONTENT_TYPE = JavaCore.PLUGIN_ID+".javaSource" ; //$NON-NLS-1$
-
+ public static final String COMPILATION_PARTICIPANT_EXTPOINT_ID = "compilationParticipant" ; //$NON-NLS-1$
+
+ /**
+ * Name of the extension point for contributing the Java 6 annotation processor manager
+ */
+ public static final String ANNOTATION_PROCESSOR_MANAGER_EXTPOINT_ID = "annotationProcessorManager" ; //$NON-NLS-1$
+
/**
* Special value used for recognizing ongoing initialization and breaking initialization cycles
*/
@@ -139,7 +180,9 @@
private static final String INDEX_MANAGER_DEBUG = JavaCore.PLUGIN_ID + "/debug/indexmanager" ; //$NON-NLS-1$
private static final String COMPILER_DEBUG = JavaCore.PLUGIN_ID + "/debug/compiler" ; //$NON-NLS-1$
private static final String JAVAMODEL_DEBUG = JavaCore.PLUGIN_ID + "/debug/javamodel" ; //$NON-NLS-1$
+ private static final String JAVAMODELCACHE_DEBUG = JavaCore.PLUGIN_ID + "/debug/javamodel/cache" ; //$NON-NLS-1$
private static final String CP_RESOLVE_DEBUG = JavaCore.PLUGIN_ID + "/debug/cpresolution" ; //$NON-NLS-1$
+ private static final String CP_RESOLVE_ADVANCED_DEBUG = JavaCore.PLUGIN_ID + "/debug/cpresolution/advanced" ; //$NON-NLS-1$
private static final String ZIP_ACCESS_DEBUG = JavaCore.PLUGIN_ID + "/debug/zipaccess" ; //$NON-NLS-1$
private static final String DELTA_DEBUG =JavaCore.PLUGIN_ID + "/debug/javadelta" ; //$NON-NLS-1$
private static final String DELTA_DEBUG_VERBOSE =JavaCore.PLUGIN_ID + "/debug/javadelta/verbose" ; //$NON-NLS-1$
@@ -159,6 +202,8 @@
public static final String CONTAINER_INITIALIZER_PERF = JavaCore.PLUGIN_ID + "/perf/containerinitializer" ; //$NON-NLS-1$
public static final String RECONCILE_PERF = JavaCore.PLUGIN_ID + "/perf/reconcile" ; //$NON-NLS-1$
+ private final static String INDEXED_SECONDARY_TYPES = "#@*_indexing secondary cache_*@#"; //$NON-NLS-1$
+
public static boolean PERF_VARIABLE_INITIALIZER = false;
public static boolean PERF_CONTAINER_INITIALIZER = false;
@@ -172,6 +217,186 @@
static final int PREF_INSTANCE = 0;
static final int PREF_DEFAULT = 1;
+ static final Object[][] NO_PARTICIPANTS = new Object[0][];
+
+ public static class CompilationParticipants {
+
+ private final static int MAX_SOURCE_LEVEL = 7; // 1.1 to 1.7
+
+ /*
+ * The registered compilation participants (a table from int (source level) to Object[])
+ * The Object array contains first IConfigurationElements when not resolved yet, then
+ * it contains CompilationParticipants.
+ */
+ private Object[][] registeredParticipants = null;
+ private HashSet managedMarkerTypes;
+
+ public CompilationParticipant[] getCompilationParticipants(IJavaProject project) {
+ final Object[][] participantsPerSource = getRegisteredParticipants();
+ if (participantsPerSource == NO_PARTICIPANTS)
+ return null;
+ String sourceLevel = project.getOption(JavaCore.COMPILER_SOURCE, true/*inherit options*/);
+ final int sourceLevelIndex = indexForSourceLevel(sourceLevel);
+ final Object[] participants = participantsPerSource[sourceLevelIndex];
+ int length = participants.length;
+ CompilationParticipant[] result = new CompilationParticipant[length];
+ int index = 0;
+ for (int i = 0; i < length; i++) {
+ if (participants[i] instanceof IConfigurationElement) {
+ final IConfigurationElement configElement = (IConfigurationElement) participants[i];
+ final int participantIndex = i;
+ SafeRunner.run(new ISafeRunnable() {
+ public void handleException(Throwable exception) {
+ Util.log(exception, "Exception occurred while creating compilation participant"); //$NON-NLS-1$
+ }
+ public void run() throws Exception {
+ Object executableExtension = configElement.createExecutableExtension("class"); //$NON-NLS-1$
+ for (int j = sourceLevelIndex; j < MAX_SOURCE_LEVEL; j++)
+ participantsPerSource[j][participantIndex] = executableExtension;
+ }
+ });
+ }
+ CompilationParticipant participant = (CompilationParticipant) participants[i];
+ if (participant != null && participant.isActive(project))
+ result[index++] = participant;
+ }
+ if (index == 0)
+ return null;
+ if (index < length)
+ System.arraycopy(result, 0, result = new CompilationParticipant[index], 0, index);
+ return result;
+ }
+
+ public HashSet managedMarkerTypes() {
+ if (this.managedMarkerTypes == null) {
+ // force extension points to be read
+ getRegisteredParticipants();
+ }
+ return this.managedMarkerTypes;
+ }
+
+ private synchronized Object[][] getRegisteredParticipants() {
+ if (this.registeredParticipants != null) {
+ return this.registeredParticipants;
+ }
+ this.managedMarkerTypes = new HashSet();
+ IExtensionPoint extension = Platform.getExtensionRegistry().getExtensionPoint(JavaCore.PLUGIN_ID, COMPILATION_PARTICIPANT_EXTPOINT_ID);
+ if (extension == null)
+ return this.registeredParticipants = NO_PARTICIPANTS;
+ final ArrayList modifyingEnv = new ArrayList();
+ final ArrayList creatingProblems = new ArrayList();
+ final ArrayList others = new ArrayList();
+ IExtension[] extensions = extension.getExtensions();
+ // for all extensions of this point...
+ for(int i = 0; i < extensions.length; i++) {
+ IConfigurationElement[] configElements = extensions[i].getConfigurationElements();
+ // for all config elements named "compilationParticipant"
+ for(int j = 0; j < configElements.length; j++) {
+ final IConfigurationElement configElement = configElements[j];
+ String elementName =configElement.getName();
+ if (!("compilationParticipant".equals(elementName))) { //$NON-NLS-1$
+ continue;
+ }
+ // add config element in the group it belongs to
+ if (TRUE.equals(configElement.getAttribute("modifiesEnvironment"))) //$NON-NLS-1$
+ modifyingEnv.add(configElement);
+ else if (TRUE.equals(configElement.getAttribute("createsProblems"))) //$NON-NLS-1$
+ creatingProblems.add(configElement);
+ else
+ others.add(configElement);
+ // add managed marker types
+ IConfigurationElement[] managedMarkers = configElement.getChildren("managedMarker"); //$NON-NLS-1$
+ for (int k = 0, length = managedMarkers.length; k < length; k++) {
+ IConfigurationElement element = managedMarkers[k];
+ String markerType = element.getAttribute("markerType"); //$NON-NLS-1$
+ if (markerType != null)
+ this.managedMarkerTypes.add(markerType);
+ }
+ }
+ }
+ int size = modifyingEnv.size() + creatingProblems.size() + others.size();
+ if (size == 0)
+ return this.registeredParticipants = NO_PARTICIPANTS;
+
+ // sort config elements in each group
+ IConfigurationElement[] configElements = new IConfigurationElement[size];
+ int index = 0;
+ index = sortParticipants(modifyingEnv, configElements, index);
+ index = sortParticipants(creatingProblems, configElements, index);
+ index = sortParticipants(others, configElements, index);
+
+ // create result table
+ Object[][] result = new Object[MAX_SOURCE_LEVEL][];
+ int length = configElements.length;
+ for (int i = 0; i < MAX_SOURCE_LEVEL; i++) {
+ result[i] = new Object[length];
+ }
+ for (int i = 0; i < length; i++) {
+ String sourceLevel = configElements[i].getAttribute("requiredSourceLevel"); //$NON-NLS-1$
+ int sourceLevelIndex = indexForSourceLevel(sourceLevel);
+ for (int j = sourceLevelIndex; j < MAX_SOURCE_LEVEL; j++) {
+ result[j][i] = configElements[i];
+ }
+ }
+ return this.registeredParticipants = result;
+ }
+
+ /*
+ * 1.1 -> 0
+ * 1.2 -> 1
+ * ...
+ * 1.6 -> 5
+ * 1.7 -> 6
+ * null -> 0
+ */
+ private int indexForSourceLevel(String sourceLevel) {
+ if (sourceLevel == null) return 0;
+ int majVersion = (int) (CompilerOptions.versionToJdkLevel(sourceLevel) >>> 16);
+ switch (majVersion) {
+ case ClassFileConstants.MAJOR_VERSION_1_2:
+ return 1;
+ case ClassFileConstants.MAJOR_VERSION_1_3:
+ return 2;
+ case ClassFileConstants.MAJOR_VERSION_1_4:
+ return 3;
+ case ClassFileConstants.MAJOR_VERSION_1_5:
+ return 4;
+ case ClassFileConstants.MAJOR_VERSION_1_6:
+ return 5;
+ case ClassFileConstants.MAJOR_VERSION_1_7:
+ return 6;
+ default:
+ // all other cases including ClassFileConstants.MAJOR_VERSION_1_1
+ return 0;
+ }
+ }
+
+ private int sortParticipants(ArrayList group, IConfigurationElement[] configElements, int index) {
+ int size = group.size();
+ if (size == 0) return index;
+ Object[] elements = group.toArray();
+ Util.sort(elements, new Util.Comparer() {
+ public int compare(Object a, Object b) {
+ if (a == b) return 0;
+ String id = ((IConfigurationElement) a).getAttribute("id"); //$NON-NLS-1$
+ if (id == null) return -1;
+ IConfigurationElement[] requiredElements = ((IConfigurationElement) b).getChildren("requires"); //$NON-NLS-1$
+ for (int i = 0, length = requiredElements.length; i < length; i++) {
+ IConfigurationElement required = requiredElements[i];
+ if (id.equals(required.getAttribute("id"))) //$NON-NLS-1$
+ return 1;
+ }
+ return -1;
+ }
+ });
+ for (int i = 0; i < size; i++)
+ configElements[index+i] = (IConfigurationElement) elements[i];
+ return index + size;
+ }
+ }
+
+ public final CompilationParticipants compilationParticipants = new CompilationParticipants();
+
/**
* Returns whether the given full path (for a package) conflicts with the output location
* of the given project.
@@ -186,7 +411,7 @@
if (outputLocation.isPrefixOf(folderPath)) {
// only allow nesting in project's output if there is a corresponding source folder
// or if the project's output is not used (in other words, if all source folders have their custom output)
- IClasspathEntry[] classpath = project.getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/);
+ IClasspathEntry[] classpath = project.getResolvedClasspath();
boolean isOutputUsed = false;
for (int i = 0, length = classpath.length; i < length; i++) {
IClasspathEntry entry = classpath[i];
@@ -210,8 +435,7 @@
public synchronized IClasspathContainer containerGet(IJavaProject project, IPath containerPath) {
// check initialization in progress first
- HashSet projectInitializations = containerInitializationInProgress(project);
- if (projectInitializations.contains(containerPath)) {
+ if (containerIsInitializationInProgress(project, containerPath)) {
return CONTAINER_INITIALIZATION_IN_PROGRESS;
}
@@ -223,6 +447,16 @@
return container;
}
+ public synchronized IClasspathContainer containerGetDefaultToPreviousSession(IJavaProject project, IPath containerPath) {
+ Map projectContainers = (Map)this.containers.get(project);
+ if (projectContainers == null)
+ return getPreviousSessionContainer(containerPath, project);
+ IClasspathContainer container = (IClasspathContainer)projectContainers.get(containerPath);
+ if (container == null)
+ return getPreviousSessionContainer(containerPath, project);
+ return container;
+ }
+
private synchronized Map containerClone(IJavaProject project) {
Map originalProjectContainers = (Map)this.containers.get(project);
if (originalProjectContainers == null) return null;
@@ -231,37 +465,39 @@
return projectContainers;
}
- /*
- * Returns the set of container paths for the given project that are being initialized in the current thread.
- */
- private HashSet containerInitializationInProgress(IJavaProject project) {
+ private boolean containerIsInitializationInProgress(IJavaProject project, IPath containerPath) {
Map initializations = (Map)this.containerInitializationInProgress.get();
- if (initializations == null) {
- initializations = new HashMap();
- this.containerInitializationInProgress.set(initializations);
- }
- HashSet projectInitializations = (HashSet)initializations.get(project);
- if (projectInitializations == null) {
- projectInitializations = new HashSet();
- initializations.put(project, projectInitializations);
- }
- return projectInitializations;
+ if (initializations == null)
+ return false;
+ HashSet projectInitializations = (HashSet) initializations.get(project);
+ if (projectInitializations == null)
+ return false;
+ return projectInitializations.contains(containerPath);
}
+ private void containerAddInitializationInProgress(IJavaProject project, IPath containerPath) {
+ Map initializations = (Map)this.containerInitializationInProgress.get();
+ if (initializations == null)
+ this.containerInitializationInProgress.set(initializations = new HashMap());
+ HashSet projectInitializations = (HashSet) initializations.get(project);
+ if (projectInitializations == null)
+ initializations.put(project, projectInitializations = new HashSet());
+ projectInitializations.add(containerPath);
+ }
+
public synchronized void containerPut(IJavaProject project, IPath containerPath, IClasspathContainer container){
// set/unset the initialization in progress
if (container == CONTAINER_INITIALIZATION_IN_PROGRESS) {
- HashSet projectInitializations = containerInitializationInProgress(project);
- projectInitializations.add(containerPath);
+ containerAddInitializationInProgress(project, containerPath);
// do not write out intermediate initialization value
return;
} else {
containerRemoveInitializationInProgress(project, containerPath);
- Map projectContainers = (Map)this.containers.get(project);
- if (projectContainers == null){
+ Map projectContainers = (Map)this.containers.get(project);
+ if (projectContainers == null){
projectContainers = new HashMap(1);
this.containers.put(project, projectContainers);
}
@@ -269,7 +505,7 @@
if (container == null) {
projectContainers.remove(containerPath);
} else {
- projectContainers.put(containerPath, container);
+ projectContainers.put(containerPath, container);
}
// discard obsoleted information about previous session
Map previousContainers = (Map)this.previousSessionContainers.get(project);
@@ -281,109 +517,174 @@
}
/*
- * Optimize startup case where a container for 1 project is initialized at a time with the same entries as on shutdown.
+ * The given project is being removed. Remove all containers for this project from the cache.
*/
+ public synchronized void containerRemove(IJavaProject project) {
+ Map initializations = (Map) this.containerInitializationInProgress.get();
+ if (initializations != null) {
+ initializations.remove(project);
+ }
+ this.containers.remove(project);
+ }
+
public boolean containerPutIfInitializingWithSameEntries(IPath containerPath, IJavaProject[] projects, IClasspathContainer[] respectiveContainers) {
int projectLength = projects.length;
if (projectLength != 1)
return false;
final IClasspathContainer container = respectiveContainers[0];
- if (container == null)
- return false;
IJavaProject project = projects[0];
- if (!containerInitializationInProgress(project).contains(containerPath))
+ // optimize only if initializing, otherwise we are in a regular setContainer(...) call
+ if (!containerIsInitializationInProgress(project, containerPath))
return false;
- IClasspathContainer previousSessionContainer = getPreviousSessionContainer(containerPath, project);
+ IClasspathContainer previousContainer = containerGetDefaultToPreviousSession(project, containerPath);
+ if (container == null) {
+ if (previousContainer == null) {
+ containerPut(project, containerPath, null);
+ return true;
+ }
+ return false;
+ }
final IClasspathEntry[] newEntries = container.getClasspathEntries();
- if (previousSessionContainer == null)
+ if (previousContainer == null)
if (newEntries.length == 0) {
containerPut(project, containerPath, container);
return true;
} else {
+ if (CP_RESOLVE_VERBOSE)
+ verbose_missbehaving_container(containerPath, projects, respectiveContainers, container, newEntries, null/*no old entries*/);
return false;
}
- final IClasspathEntry[] oldEntries = previousSessionContainer.getClasspathEntries();
- if (oldEntries.length != newEntries.length)
+ final IClasspathEntry[] oldEntries = previousContainer.getClasspathEntries();
+ if (oldEntries.length != newEntries.length) {
+ if (CP_RESOLVE_VERBOSE)
+ verbose_missbehaving_container(containerPath, projects, respectiveContainers, container, newEntries, oldEntries);
return false;
+ }
for (int i = 0, length = newEntries.length; i < length; i++) {
+ if (newEntries[i] == null) {
+ if (CP_RESOLVE_VERBOSE)
+ verbose_missbehaving_container(project, containerPath, newEntries);
+ return false;
+ }
if (!newEntries[i].equals(oldEntries[i])) {
- if (CP_RESOLVE_VERBOSE) {
- Util.verbose(
- "CPContainer SET - missbehaving container\n" + //$NON-NLS-1$
- " container path: " + containerPath + '\n' + //$NON-NLS-1$
- " projects: {" +//$NON-NLS-1$
- org.eclipse.jdt.internal.compiler.util.Util.toString(
- projects,
- new org.eclipse.jdt.internal.compiler.util.Util.Displayable(){
- public String displayString(Object o) { return ((IJavaProject) o).getElementName(); }
- }) +
- "}\n values on previous session: {\n" +//$NON-NLS-1$
- org.eclipse.jdt.internal.compiler.util.Util.toString(
- respectiveContainers,
- new org.eclipse.jdt.internal.compiler.util.Util.Displayable(){
- public String displayString(Object o) {
- StringBuffer buffer = new StringBuffer(" "); //$NON-NLS-1$
- if (o == null) {
- buffer.append("<null>"); //$NON-NLS-1$
- return buffer.toString();
- }
- buffer.append(container.getDescription());
- buffer.append(" {\n"); //$NON-NLS-1$
- for (int j = 0; j < oldEntries.length; j++){
- buffer.append(" "); //$NON-NLS-1$
- buffer.append(oldEntries[j]);
- buffer.append('\n');
- }
- buffer.append(" }"); //$NON-NLS-1$
- return buffer.toString();
- }
- }) +
- "}\n new values: {\n" +//$NON-NLS-1$
- org.eclipse.jdt.internal.compiler.util.Util.toString(
- respectiveContainers,
- new org.eclipse.jdt.internal.compiler.util.Util.Displayable(){
- public String displayString(Object o) {
- StringBuffer buffer = new StringBuffer(" "); //$NON-NLS-1$
- if (o == null) {
- buffer.append("<null>"); //$NON-NLS-1$
- return buffer.toString();
- }
- buffer.append(container.getDescription());
- buffer.append(" {\n"); //$NON-NLS-1$
- for (int j = 0; j < newEntries.length; j++){
- buffer.append(" "); //$NON-NLS-1$
- buffer.append(newEntries[j]);
- buffer.append('\n');
- }
- buffer.append(" }"); //$NON-NLS-1$
- return buffer.toString();
- }
- }) +
- "\n }"); //$NON-NLS-1$
- }
+ if (CP_RESOLVE_VERBOSE)
+ verbose_missbehaving_container(containerPath, projects, respectiveContainers, container, newEntries, oldEntries);
return false;
}
}
containerPut(project, containerPath, container);
return true;
}
+
+ private void verbose_missbehaving_container(
+ IPath containerPath,
+ IJavaProject[] projects,
+ IClasspathContainer[] respectiveContainers,
+ final IClasspathContainer container,
+ final IClasspathEntry[] newEntries,
+ final IClasspathEntry[] oldEntries) {
+ Util.verbose(
+ "CPContainer SET - missbehaving container\n" + //$NON-NLS-1$
+ " container path: " + containerPath + '\n' + //$NON-NLS-1$
+ " projects: {" +//$NON-NLS-1$
+ org.eclipse.jdt.internal.compiler.util.Util.toString(
+ projects,
+ new org.eclipse.jdt.internal.compiler.util.Util.Displayable(){
+ public String displayString(Object o) { return ((IJavaProject) o).getElementName(); }
+ }) +
+ "}\n values on previous session: {\n" +//$NON-NLS-1$
+ org.eclipse.jdt.internal.compiler.util.Util.toString(
+ respectiveContainers,
+ new org.eclipse.jdt.internal.compiler.util.Util.Displayable(){
+ public String displayString(Object o) {
+ StringBuffer buffer = new StringBuffer(" "); //$NON-NLS-1$
+ if (o == null) {
+ buffer.append("<null>"); //$NON-NLS-1$
+ return buffer.toString();
+ }
+ buffer.append(container.getDescription());
+ buffer.append(" {\n"); //$NON-NLS-1$
+ if (oldEntries == null) {
+ buffer.append(" "); //$NON-NLS-1$
+ buffer.append("<null>\n"); //$NON-NLS-1$
+ } else {
+ for (int j = 0; j < oldEntries.length; j++){
+ buffer.append(" "); //$NON-NLS-1$
+ buffer.append(oldEntries[j]);
+ buffer.append('\n');
+ }
+ }
+ buffer.append(" }"); //$NON-NLS-1$
+ return buffer.toString();
+ }
+ }) +
+ "}\n new values: {\n" +//$NON-NLS-1$
+ org.eclipse.jdt.internal.compiler.util.Util.toString(
+ respectiveContainers,
+ new org.eclipse.jdt.internal.compiler.util.Util.Displayable(){
+ public String displayString(Object o) {
+ StringBuffer buffer = new StringBuffer(" "); //$NON-NLS-1$
+ if (o == null) {
+ buffer.append("<null>"); //$NON-NLS-1$
+ return buffer.toString();
+ }
+ buffer.append(container.getDescription());
+ buffer.append(" {\n"); //$NON-NLS-1$
+ for (int j = 0; j < newEntries.length; j++){
+ buffer.append(" "); //$NON-NLS-1$
+ buffer.append(newEntries[j]);
+ buffer.append('\n');
+ }
+ buffer.append(" }"); //$NON-NLS-1$
+ return buffer.toString();
+ }
+ }) +
+ "\n }"); //$NON-NLS-1$
+ }
+ void verbose_missbehaving_container(IJavaProject project, IPath containerPath, IClasspathEntry[] classpathEntries) {
+ Util.verbose(
+ "CPContainer GET - missbehaving container (returning null classpath entry)\n" + //$NON-NLS-1$
+ " project: " + project.getElementName() + '\n' + //$NON-NLS-1$
+ " container path: " + containerPath + '\n' + //$NON-NLS-1$
+ " classpath entries: {\n" + //$NON-NLS-1$
+ org.eclipse.jdt.internal.compiler.util.Util.toString(
+ classpathEntries,
+ new org.eclipse.jdt.internal.compiler.util.Util.Displayable(){
+ public String displayString(Object o) {
+ StringBuffer buffer = new StringBuffer(" "); //$NON-NLS-1$
+ if (o == null) {
+ buffer.append("<null>"); //$NON-NLS-1$
+ return buffer.toString();
+ }
+ buffer.append(o);
+ return buffer.toString();
+ }
+ }) +
+ "\n }" //$NON-NLS-1$
+ );
+ }
+
private void containerRemoveInitializationInProgress(IJavaProject project, IPath containerPath) {
- HashSet projectInitializations = containerInitializationInProgress(project);
+ Map initializations = (Map)this.containerInitializationInProgress.get();
+ if (initializations == null)
+ return;
+ HashSet projectInitializations = (HashSet) initializations.get(project);
+ if (projectInitializations == null)
+ return;
projectInitializations.remove(containerPath);
- if (projectInitializations.size() == 0) {
- Map initializations = (Map)this.containerInitializationInProgress.get();
+ if (projectInitializations.size() == 0)
initializations.remove(project);
- }
+ if (initializations.size() == 0)
+ this.containerInitializationInProgress.set(null);
}
private synchronized void containersReset(String[] containerIDs) {
for (int i = 0; i < containerIDs.length; i++) {
String containerID = containerIDs[i];
- Iterator projectIterator = this.containers.keySet().iterator();
+ Iterator projectIterator = this.containers.values().iterator();
while (projectIterator.hasNext()){
- IJavaProject project = (IJavaProject)projectIterator.next();
- Map projectContainers = (Map)this.containers.get(project);
+ Map projectContainers = (Map) projectIterator.next();
if (projectContainers != null){
Iterator containerIterator = projectContainers.keySet().iterator();
while (containerIterator.hasNext()){
@@ -505,14 +806,7 @@
} else {
element = determineIfOnClasspath(folder, project);
}
-
- if (conflictsWithOutputLocation(folder.getFullPath(), (JavaProject)project)
- || (folder.getName().indexOf('.') >= 0
- && !(element instanceof IPackageFragmentRoot))) {
- return null; // only package fragment roots are allowed with dot names
- } else {
- return element;
- }
+ return element;
}
/**
@@ -580,13 +874,9 @@
// Create a jar package fragment root only if on the classpath
IPath resourcePath = file.getFullPath();
try {
- IClasspathEntry[] entries = ((JavaProject)project).getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/);
- for (int i = 0, length = entries.length; i < length; i++) {
- IClasspathEntry entry = entries[i];
- IPath rootPath = entry.getPath();
- if (rootPath.equals(resourcePath)) {
- return project.getPackageFragmentRoot(file);
- }
+ IClasspathEntry entry = ((JavaProject)project).getClasspathEntryFor(resourcePath);
+ if (entry != null) {
+ return project.getPackageFragmentRoot(file);
}
} catch (JavaModelException e) {
// project doesn't exist: return null
@@ -605,35 +895,49 @@
IPath resourcePath = resource.getFullPath();
try {
+ JavaProjectElementInfo projectInfo = (JavaProjectElementInfo) getJavaModelManager().getInfo(project);
+ ProjectCache projectCache = projectInfo == null ? null : projectInfo.projectCache;
+ HashtableOfArrayToObject allPkgFragmentsCache = projectCache == null ? null : projectCache.allPkgFragmentsCache;
IClasspathEntry[] entries =
org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(resourcePath.lastSegment())
? project.getRawClasspath() // JAVA file can only live inside SRC folder (on the raw path)
- : ((JavaProject)project).getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/);
-
- for (int i = 0; i < entries.length; i++) {
- IClasspathEntry entry = entries[i];
- if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) continue;
- IPath rootPath = entry.getPath();
- if (rootPath.equals(resourcePath)) {
- return project.getPackageFragmentRoot(resource);
- } else if (rootPath.isPrefixOf(resourcePath)) {
- // allow creation of package fragment if it contains a .java file that is included
- if (!Util.isExcluded(resource, ((ClasspathEntry)entry).fullInclusionPatternChars(), ((ClasspathEntry)entry).fullExclusionPatternChars())) {
- // given we have a resource child of the root, it cannot be a JAR pkg root
- PackageFragmentRoot root =(PackageFragmentRoot) ((JavaProject) project).getFolderPackageFragmentRoot(rootPath);
- if (root == null) return null;
- IPath pkgPath = resourcePath.removeFirstSegments(rootPath.segmentCount());
+ : ((JavaProject)project).getResolvedClasspath();
+
+ int length = entries.length;
+ if (length > 0) {
+ String sourceLevel = project.getOption(JavaCore.COMPILER_SOURCE, true);
+ String complianceLevel = project.getOption(JavaCore.COMPILER_COMPLIANCE, true);
+ for (int i = 0; i < length; i++) {
+ IClasspathEntry entry = entries[i];
+ if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) continue;
+ IPath rootPath = entry.getPath();
+ if (rootPath.equals(resourcePath)) {
+ return project.getPackageFragmentRoot(resource);
+ } else if (rootPath.isPrefixOf(resourcePath)) {
+ // allow creation of package fragment if it contains a .java file that is included
+ if (!Util.isExcluded(resource, ((ClasspathEntry)entry).fullInclusionPatternChars(), ((ClasspathEntry)entry).fullExclusionPatternChars())) {
+ // given we have a resource child of the root, it cannot be a JAR pkg root
+ PackageFragmentRoot root =(PackageFragmentRoot) ((JavaProject) project).getFolderPackageFragmentRoot(rootPath);
+ if (root == null) return null;
+ IPath pkgPath = resourcePath.removeFirstSegments(rootPath.segmentCount());
- if (resource.getType() == IResource.FILE) {
- // if the resource is a file, then remove the last segment which
- // is the file name in the package
- pkgPath = pkgPath.removeLastSegments(1);
+ if (resource.getType() == IResource.FILE) {
+ // if the resource is a file, then remove the last segment which
+ // is the file name in the package
+ pkgPath = pkgPath.removeLastSegments(1);
+ }
+ String[] pkgName = pkgPath.segments();
+
+ // if package name is in the cache, then it has already been validated
+ // (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=133141)
+ if (allPkgFragmentsCache != null && allPkgFragmentsCache.containsKey(pkgName))
+ return root.getPackageFragment(pkgName);
+
+ if (pkgName.length != 0 && JavaConventions.validatePackageName(Util.packageName(pkgPath, sourceLevel, complianceLevel), sourceLevel, complianceLevel).getSeverity() == IStatus.ERROR) {
+ return null;
+ }
+ return root.getPackageFragment(pkgName);
}
- String[] pkgName = pkgPath.segments();
- if (pkgName.length != 0 && JavaConventions.validatePackageName(Util.packageName(pkgPath)).getSeverity() == IStatus.ERROR) {
- return null;
- }
- return root.getPackageFragment(pkgName);
}
}
}
@@ -651,7 +955,7 @@
/**
* Infos cache.
*/
- public JavaModelCache cache = new JavaModelCache();
+ private JavaModelCache cache;
/*
* Temporary cache of newly opened elements
@@ -661,14 +965,14 @@
/**
* Set of elements which are out of sync with their buffers.
*/
- protected Map elementsOutOfSynchWithBuffers = new HashMap(11);
+ protected HashSet elementsOutOfSynchWithBuffers = new HashSet(11);
/**
* Holds the state used for delta processing.
*/
public DeltaProcessingState deltaState = new DeltaProcessingState();
- public IndexManager indexManager = new IndexManager();
+ public IndexManager indexManager = null;
/**
* Table from IProject to PerProjectInfo.
@@ -688,23 +992,30 @@
protected WeakHashMap searchScopes = new WeakHashMap();
public static class PerProjectInfo {
+ private static final int JAVADOC_CACHE_INITIAL_SIZE = 10;
public IProject project;
public Object savedState;
public boolean triedRead;
public IClasspathEntry[] rawClasspath;
+ public IJavaModelStatus rawClasspathStatus;
public IClasspathEntry[] resolvedClasspath;
- public Map resolvedPathToRawEntries; // reverse map from resolved path to raw entries
+ public IJavaModelStatus unresolvedEntryStatus;
+ public Map rootPathToRawEntries; // reverse map from a package fragment root's path to the raw entry
+ public Map rootPathToResolvedEntries; // map from a package fragment root's path to the resolved entry
public IPath outputLocation;
public IEclipsePreferences preferences;
public Hashtable options;
+ public Hashtable secondaryTypes;
+ public LRUCache javadocCache;
public PerProjectInfo(IProject project) {
this.triedRead = false;
this.savedState = null;
this.project = project;
+ this.javadocCache = new LRUCache(JAVADOC_CACHE_INITIAL_SIZE);
}
public void rememberExternalLibTimestamps() {
@@ -727,13 +1038,82 @@
}
}
- // updating raw classpath need to flush obsoleted cached information about resolved entries
- public synchronized void updateClasspathInformation(IClasspathEntry[] newRawClasspath) {
-
- this.rawClasspath = newRawClasspath;
- this.resolvedClasspath = null;
- this.resolvedPathToRawEntries = null;
+ public synchronized void resetResolvedClasspath() {
+ // null out resolved information
+ setClasspath(this.rawClasspath, this.outputLocation, this.rawClasspathStatus, null, null, null, null);
}
+
+ public synchronized void setClasspath(IClasspathEntry[] newRawClasspath, IPath newOutputLocation, IJavaModelStatus newRawClasspathStatus, IClasspathEntry[] newResolvedClasspath, Map newRootPathToRawEntries, Map newRootPathToResolvedEntries, IJavaModelStatus newUnresolvedEntryStatus) {
+ // remember old info
+ JavaModelManager manager = JavaModelManager.getJavaModelManager();
+ DeltaProcessor deltaProcessor = manager.deltaState.getDeltaProcessor();
+ deltaProcessor.addClasspathChange(this.project, this.rawClasspath, this.outputLocation, this.resolvedClasspath);
+
+ this.rawClasspath = newRawClasspath;
+ this.outputLocation = newOutputLocation;
+ this.rawClasspathStatus = newRawClasspathStatus;
+ this.resolvedClasspath = newResolvedClasspath;
+ this.rootPathToRawEntries = newRootPathToRawEntries;
+ this.rootPathToResolvedEntries = newRootPathToResolvedEntries;
+ this.unresolvedEntryStatus = newUnresolvedEntryStatus;
+ this.javadocCache = new LRUCache(JAVADOC_CACHE_INITIAL_SIZE);
+ }
+
+ /*
+ * Reads the raw classpath and output location from disk, and remember them.
+ * Return the raw classpath, or JavaProject#INVALID_CLASSPATH if unable to read it.
+ */
+ public synchronized IClasspathEntry[] readAndCacheClasspath(JavaProject javaProject) {
+ // read file entries and update status
+ IClasspathEntry[] classpath;
+ IJavaModelStatus status;
+ try {
+ classpath = javaProject.readFileEntriesWithException(null/*not interested in unknown elements*/);
+ status = JavaModelStatus.VERIFIED_OK;
+ } catch (CoreException e) {
+ classpath = JavaProject.INVALID_CLASSPATH;
+ status =
+ new JavaModelStatus(
+ IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
+ Messages.bind(Messages.classpath_cannotReadClasspathFile, javaProject.getElementName()));
+ } catch (IOException e) {
+ classpath = JavaProject.INVALID_CLASSPATH;
+ if (Messages.file_badFormat.equals(e.getMessage()))
+ status =
+ new JavaModelStatus(
+ IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
+ Messages.bind(Messages.classpath_xmlFormatError, javaProject.getElementName(), Messages.file_badFormat));
+ else
+ status =
+ new JavaModelStatus(
+ IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
+ Messages.bind(Messages.classpath_cannotReadClasspathFile, javaProject.getElementName()));
+ } catch (AssertionFailedException e) {
+ classpath = JavaProject.INVALID_CLASSPATH;
+ status =
+ new JavaModelStatus(
+ IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
+ Messages.bind(Messages.classpath_illegalEntryInClasspathFile, new String[] {javaProject.getElementName(), e.getMessage()}));
+ }
+
+ // extract out the output location
+ IPath output = null;
+ if (classpath.length > 0) {
+ IClasspathEntry entry = classpath[classpath.length - 1];
+ if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) {
+ output = entry.getPath();
+ IClasspathEntry[] copy = new IClasspathEntry[classpath.length - 1];
+ System.arraycopy(classpath, 0, copy, 0, copy.length);
+ classpath = copy;
+ }
+ }
+
+ // store new raw classpath, new output and new status, and null out resolved info
+ setClasspath(classpath, output, status, null, null, null, null);
+
+ return classpath;
+ }
+
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append("Info for "); //$NON-NLS-1$
@@ -772,28 +1152,38 @@
public static class PerWorkingCopyInfo implements IProblemRequestor {
int useCount = 0;
IProblemRequestor problemRequestor;
- ICompilationUnit workingCopy;
- public PerWorkingCopyInfo(ICompilationUnit workingCopy, IProblemRequestor problemRequestor) {
+ CompilationUnit workingCopy;
+ public PerWorkingCopyInfo(CompilationUnit workingCopy, IProblemRequestor problemRequestor) {
this.workingCopy = workingCopy;
this.problemRequestor = problemRequestor;
}
public void acceptProblem(IProblem problem) {
- if (this.problemRequestor == null) return;
- this.problemRequestor.acceptProblem(problem);
+ IProblemRequestor requestor = getProblemRequestor();
+ if (requestor == null) return;
+ requestor.acceptProblem(problem);
}
public void beginReporting() {
- if (this.problemRequestor == null) return;
- this.problemRequestor.beginReporting();
+ IProblemRequestor requestor = getProblemRequestor();
+ if (requestor == null) return;
+ requestor.beginReporting();
}
public void endReporting() {
- if (this.problemRequestor == null) return;
- this.problemRequestor.endReporting();
+ IProblemRequestor requestor = getProblemRequestor();
+ if (requestor == null) return;
+ requestor.endReporting();
+ }
+ public IProblemRequestor getProblemRequestor() {
+ if (this.problemRequestor == null && this.workingCopy.owner != null) {
+ return this.workingCopy.owner.getProblemRequestor(this.workingCopy);
+ }
+ return this.problemRequestor;
}
public ICompilationUnit getWorkingCopy() {
return this.workingCopy;
}
public boolean isActive() {
- return this.problemRequestor != null && this.problemRequestor.isActive();
+ IProblemRequestor requestor = getProblemRequestor();
+ return requestor != null && requestor.isActive();
}
public String toString() {
StringBuffer buffer = new StringBuffer();
@@ -803,12 +1193,18 @@
buffer.append(this.useCount);
buffer.append("\nProblem requestor:\n "); //$NON-NLS-1$
buffer.append(this.problemRequestor);
+ if (this.problemRequestor == null) {
+ IProblemRequestor requestor = getProblemRequestor();
+ buffer.append("\nOwner problem requestor:\n "); //$NON-NLS-1$
+ buffer.append(requestor);
+ }
return buffer.toString();
}
}
public static boolean VERBOSE = false;
public static boolean CP_RESOLVE_VERBOSE = false;
+ public static boolean CP_RESOLVE_VERBOSE_ADVANCED = false;
public static boolean ZIP_ACCESS_VERBOSE = false;
/**
@@ -817,29 +1213,76 @@
*/
private ThreadLocal zipFiles = new ThreadLocal();
+ private UserLibraryManager userLibraryManager;
/**
* Update the classpath variable cache
*/
- public static class EclipsePreferencesListener implements IEclipsePreferences.IPreferenceChangeListener {
+ public class EclipsePreferencesListener implements IEclipsePreferences.IPreferenceChangeListener {
/**
- * @see org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener#preferenceChange(org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent)
- */
- public void preferenceChange(IEclipsePreferences.PreferenceChangeEvent event) {
- String propertyName = event.getKey();
- if (propertyName.startsWith(CP_VARIABLE_PREFERENCES_PREFIX)) {
- String varName = propertyName.substring(CP_VARIABLE_PREFERENCES_PREFIX.length());
- String newValue = (String)event.getNewValue();
- if (newValue != null && !(newValue = newValue.trim()).equals(CP_ENTRY_IGNORE)) {
- getJavaModelManager().variables.put(varName, new Path(newValue));
- } else {
- getJavaModelManager().variables.remove(varName);
+ * @see org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener#preferenceChange(org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent)
+ */
+ public void preferenceChange(IEclipsePreferences.PreferenceChangeEvent event) {
+ String propertyName = event.getKey();
+ if (propertyName.startsWith(CP_VARIABLE_PREFERENCES_PREFIX)) {
+ String varName = propertyName.substring(CP_VARIABLE_PREFERENCES_PREFIX.length());
+ JavaModelManager manager = getJavaModelManager();
+ if (manager.variablesWithInitializer.contains(varName)) {
+ // revert preference value as we will not apply it to JavaCore classpath variable
+ String oldValue = (String) event.getOldValue();
+ if (oldValue == null) {
+ // unexpected old value => remove variable from set
+ manager.variablesWithInitializer.remove(varName);
+ } else {
+ manager.getInstancePreferences().put(varName, oldValue);
+ }
+ } else {
+ String newValue = (String)event.getNewValue();
+ IPath newPath;
+ if (newValue != null && !(newValue = newValue.trim()).equals(CP_ENTRY_IGNORE)) {
+ newPath = new Path(newValue);
+ } else {
+ newPath = null;
+ }
+ try {
+ SetVariablesOperation operation = new SetVariablesOperation(new String[] {varName}, new IPath[] {newPath}, false/*don't update preferences*/);
+ operation.runOperation(null/*no progress available*/);
+ } catch (JavaModelException e) {
+ Util.log(e, "Could not set classpath variable " + varName + " to " + newPath); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+ } else if (propertyName.startsWith(CP_CONTAINER_PREFERENCES_PREFIX)) {
+ recreatePersistedContainer(propertyName, (String)event.getNewValue(), false);
+ } else if (propertyName.equals(JavaCore.CORE_JAVA_BUILD_CLEAN_OUTPUT_FOLDER) ||
+ propertyName.equals(JavaCore.CORE_JAVA_BUILD_RESOURCE_COPY_FILTER) ||
+ propertyName.equals(JavaCore.CORE_JAVA_BUILD_DUPLICATE_RESOURCE) ||
+ propertyName.equals(JavaCore.CORE_JAVA_BUILD_RECREATE_MODIFIED_CLASS_FILES_IN_OUTPUT_FOLDER) ||
+ propertyName.equals(JavaCore.CORE_JAVA_BUILD_INVALID_CLASSPATH) ||
+ propertyName.equals(JavaCore.CORE_ENABLE_CLASSPATH_EXCLUSION_PATTERNS) ||
+ propertyName.equals(JavaCore.CORE_ENABLE_CLASSPATH_MULTIPLE_OUTPUT_LOCATIONS) ||
+ propertyName.equals(JavaCore.CORE_INCOMPLETE_CLASSPATH) ||
+ propertyName.equals(JavaCore.CORE_CIRCULAR_CLASSPATH) ||
+ propertyName.equals(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL)) {
+ JavaModelManager manager = JavaModelManager.getJavaModelManager();
+ IJavaModel model = manager.getJavaModel();
+ IJavaProject[] projects;
+ try {
+ projects = model.getJavaProjects();
+ for (int i = 0, pl = projects.length; i < pl; i++) {
+ JavaProject javaProject = (JavaProject) projects[i];
+ manager.deltaState.addClasspathValidation(javaProject);
+ try {
+ // need to touch the project to force validation by DeltaProcessor
+ javaProject.getProject().touch(null);
+ } catch (CoreException e) {
+ // skip
+ }
+ }
+ } catch (JavaModelException e) {
+ // skip
}
- }
- if (propertyName.startsWith(CP_CONTAINER_PREFERENCES_PREFIX)) {
- recreatePersistedContainer(propertyName, (String)event.getNewValue(), false);
- }
- }
+ }
+ }
}
/**
@@ -847,6 +1290,7 @@
*/
private JavaModelManager() {
// singleton: prevent others from creating a new instance
+ if (Platform.isRunning()) this.indexManager = new IndexManager();
}
/**
@@ -886,52 +1330,58 @@
public void configurePluginDebugOptions(){
if(JavaCore.getPlugin().isDebugging()){
String option = Platform.getDebugOption(BUFFER_MANAGER_DEBUG);
- if(option != null) BufferManager.VERBOSE = option.equalsIgnoreCase("true") ; //$NON-NLS-1$
+ if(option != null) BufferManager.VERBOSE = option.equalsIgnoreCase(TRUE) ;
option = Platform.getDebugOption(BUILDER_DEBUG);
- if(option != null) JavaBuilder.DEBUG = option.equalsIgnoreCase("true") ; //$NON-NLS-1$
+ if(option != null) JavaBuilder.DEBUG = option.equalsIgnoreCase(TRUE) ;
option = Platform.getDebugOption(COMPILER_DEBUG);
- if(option != null) Compiler.DEBUG = option.equalsIgnoreCase("true") ; //$NON-NLS-1$
+ if(option != null) Compiler.DEBUG = option.equalsIgnoreCase(TRUE) ;
option = Platform.getDebugOption(COMPLETION_DEBUG);
- if(option != null) CompletionEngine.DEBUG = option.equalsIgnoreCase("true") ; //$NON-NLS-1$
+ if(option != null) CompletionEngine.DEBUG = option.equalsIgnoreCase(TRUE) ;
option = Platform.getDebugOption(CP_RESOLVE_DEBUG);
- if(option != null) JavaModelManager.CP_RESOLVE_VERBOSE = option.equalsIgnoreCase("true") ; //$NON-NLS-1$
+ if(option != null) JavaModelManager.CP_RESOLVE_VERBOSE = option.equalsIgnoreCase(TRUE) ;
+
+ option = Platform.getDebugOption(CP_RESOLVE_ADVANCED_DEBUG);
+ if(option != null) JavaModelManager.CP_RESOLVE_VERBOSE_ADVANCED = option.equalsIgnoreCase(TRUE) ;
option = Platform.getDebugOption(DELTA_DEBUG);
- if(option != null) DeltaProcessor.DEBUG = option.equalsIgnoreCase("true") ; //$NON-NLS-1$
+ if(option != null) DeltaProcessor.DEBUG = option.equalsIgnoreCase(TRUE) ;
option = Platform.getDebugOption(DELTA_DEBUG_VERBOSE);
- if(option != null) DeltaProcessor.VERBOSE = option.equalsIgnoreCase("true") ; //$NON-NLS-1$
+ if(option != null) DeltaProcessor.VERBOSE = option.equalsIgnoreCase(TRUE) ;
option = Platform.getDebugOption(HIERARCHY_DEBUG);
- if(option != null) TypeHierarchy.DEBUG = option.equalsIgnoreCase("true") ; //$NON-NLS-1$
+ if(option != null) TypeHierarchy.DEBUG = option.equalsIgnoreCase(TRUE) ;
option = Platform.getDebugOption(INDEX_MANAGER_DEBUG);
- if(option != null) JobManager.VERBOSE = option.equalsIgnoreCase("true") ; //$NON-NLS-1$
+ if(option != null) JobManager.VERBOSE = option.equalsIgnoreCase(TRUE) ;
option = Platform.getDebugOption(JAVAMODEL_DEBUG);
- if(option != null) JavaModelManager.VERBOSE = option.equalsIgnoreCase("true") ; //$NON-NLS-1$
+ if(option != null) JavaModelManager.VERBOSE = option.equalsIgnoreCase(TRUE) ;
+
+ option = Platform.getDebugOption(JAVAMODELCACHE_DEBUG);
+ if(option != null) JavaModelCache.VERBOSE = option.equalsIgnoreCase(TRUE) ;
option = Platform.getDebugOption(POST_ACTION_DEBUG);
- if(option != null) JavaModelOperation.POST_ACTION_VERBOSE = option.equalsIgnoreCase("true") ; //$NON-NLS-1$
+ if(option != null) JavaModelOperation.POST_ACTION_VERBOSE = option.equalsIgnoreCase(TRUE) ;
option = Platform.getDebugOption(RESOLUTION_DEBUG);
- if(option != null) NameLookup.VERBOSE = option.equalsIgnoreCase("true") ; //$NON-NLS-1$
+ if(option != null) NameLookup.VERBOSE = option.equalsIgnoreCase(TRUE) ;
option = Platform.getDebugOption(SEARCH_DEBUG);
- if(option != null) BasicSearchEngine.VERBOSE = option.equalsIgnoreCase("true") ; //$NON-NLS-1$
+ if(option != null) BasicSearchEngine.VERBOSE = option.equalsIgnoreCase(TRUE) ;
option = Platform.getDebugOption(SELECTION_DEBUG);
- if(option != null) SelectionEngine.DEBUG = option.equalsIgnoreCase("true") ; //$NON-NLS-1$
+ if(option != null) SelectionEngine.DEBUG = option.equalsIgnoreCase(TRUE) ;
option = Platform.getDebugOption(ZIP_ACCESS_DEBUG);
- if(option != null) JavaModelManager.ZIP_ACCESS_VERBOSE = option.equalsIgnoreCase("true") ; //$NON-NLS-1$
+ if(option != null) JavaModelManager.ZIP_ACCESS_VERBOSE = option.equalsIgnoreCase(TRUE) ;
option = Platform.getDebugOption(SOURCE_MAPPER_DEBUG_VERBOSE);
- if(option != null) SourceMapper.VERBOSE = option.equalsIgnoreCase("true") ; //$NON-NLS-1$
+ if(option != null) SourceMapper.VERBOSE = option.equalsIgnoreCase(TRUE) ;
}
// configure performance options
@@ -946,6 +1396,55 @@
}
/*
+ * Return a new Java 6 annotation processor manager. The manager will need to
+ * be configured before it can be used. Returns null if a manager cannot be
+ * created, ie if the current VM does not support Java 6 annotation processing.
+ */
+ public AbstractAnnotationProcessorManager createAnnotationProcessorManager() {
+ synchronized(this) {
+ if (this.annotationProcessorManagerFactory == null) {
+ IExtensionPoint extension = Platform.getExtensionRegistry().getExtensionPoint(JavaCore.PLUGIN_ID, ANNOTATION_PROCESSOR_MANAGER_EXTPOINT_ID);
+ if (extension == null)
+ return null;
+ IExtension[] extensions = extension.getExtensions();
+ for(int i = 0; i < extensions.length; i++) {
+ if (i > 0) {
+ Util.log(null, "An annotation processor manager is already registered: ignoring " + extensions[i].getUniqueIdentifier()); //$NON-NLS-1$
+ break;
+ }
+ IConfigurationElement[] configElements = extensions[i].getConfigurationElements();
+ for(int j = 0; j < configElements.length; j++) {
+ final IConfigurationElement configElement = configElements[j];
+ if ("annotationProcessorManager".equals(configElement.getName())) { //$NON-NLS-1$
+ this.annotationProcessorManagerFactory = configElement;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (this.annotationProcessorManagerFactory == null) {
+ return null;
+ }
+ final AbstractAnnotationProcessorManager[] apm = new AbstractAnnotationProcessorManager[1];
+ apm[0] = null;
+ final IConfigurationElement factory = this.annotationProcessorManagerFactory;
+ SafeRunner.run(new ISafeRunnable() {
+ public void handleException(Throwable exception) {
+ Util.log(exception, "Exception occurred while loading annotation processor manager"); //$NON-NLS-1$
+ }
+ public void run() throws Exception {
+ Object executableExtension = factory.createExecutableExtension("class"); //$NON-NLS-1$
+ if (executableExtension instanceof AbstractAnnotationProcessorManager) {
+ apm[0] = (AbstractAnnotationProcessorManager) executableExtension;
+ }
+ }
+ });
+ return apm[0];
+ }
+
+ /*
* Discards the per working copy info for the given working copy (making it a compilation unit)
* if its use count was 1. Otherwise, just decrement the use count.
* If the working copy is primary, computes the delta between its state and the original compilation unit
@@ -960,7 +1459,7 @@
// create the delta builder (this remembers the current content of the working copy)
// outside the perWorkingCopyInfos lock (see bug 50667)
JavaElementDeltaBuilder deltaBuilder = null;
- if (workingCopy.isPrimary()) {
+ if (workingCopy.isPrimary() && workingCopy.hasUnsavedChanges()) {
deltaBuilder = new JavaElementDeltaBuilder(workingCopy);
}
PerWorkingCopyInfo info = null;
@@ -989,7 +1488,7 @@
// compute the delta if needed and register it if there are changes
if (deltaBuilder != null) {
deltaBuilder.buildDeltas();
- if ((deltaBuilder.delta != null) && (deltaBuilder.delta.getAffectedChildren().length > 0)) {
+ if (deltaBuilder.delta != null) {
getDeltaProcessor().registerJavaModelDelta(deltaBuilder.delta);
}
}
@@ -1026,18 +1525,26 @@
}
}
- public IClasspathContainer getClasspathContainer(IPath containerPath, IJavaProject project) throws JavaModelException {
+ private synchronized boolean batchContainerInitializations() {
+ if (this.batchContainerInitializations) {
+ this.batchContainerInitializations = false;
+ return true;
+ }
+ return false;
+ }
+
+ public IClasspathContainer getClasspathContainer(final IPath containerPath, final IJavaProject project) throws JavaModelException {
IClasspathContainer container = containerGet(project, containerPath);
if (container == null) {
- if (this.batchContainerInitializations) {
+ if (batchContainerInitializations()) {
// avoid deep recursion while initializaing container on workspace restart
// (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=60437)
- this.batchContainerInitializations = false;
- return initializeAllContainers(project, containerPath);
+ container = initializeAllContainers(project, containerPath);
+ } else {
+ container = initializeContainer(project, containerPath);
}
- return initializeContainer(project, containerPath);
}
return container;
}
@@ -1049,7 +1556,7 @@
/**
* Returns the set of elements which are out of synch with their buffers.
*/
- protected Map getElementsOutOfSynchWithBuffers() {
+ protected HashSet getElementsOutOfSynchWithBuffers() {
return this.elementsOutOfSynchWithBuffers;
}
@@ -1078,11 +1585,13 @@
return preferencesLookup[PREF_INSTANCE];
}
+ // If modified, also modify the method getDefaultOptionsNoInitialization()
public Hashtable getDefaultOptions(){
-
+
Hashtable defaultOptions = new Hashtable(10);
// see JavaCorePreferenceInitializer#initializeDefaultPluginPreferences() for changing default settings
+ // If modified, also modify the method getDefaultOptionsNoInitialization()
IEclipsePreferences defaultPreferences = getDefaultPreferences();
// initialize preferences to their default
@@ -1170,6 +1679,9 @@
// return cached options if already computed
if (this.optionsCache != null) return new Hashtable(this.optionsCache);
+ if (!Platform.isRunning()) {
+ return this.optionsCache = getDefaultOptionsNoInitialization();
+ }
// init
Hashtable options = new Hashtable(10);
IPreferencesService service = Platform.getPreferencesService();
@@ -1196,6 +1708,59 @@
// return built map
return options;
}
+
+ // Do not modify without modifying getDefaultOptions()
+ private Hashtable getDefaultOptionsNoInitialization() {
+ Map defaultOptionsMap = new CompilerOptions().getMap(); // compiler defaults
+
+ // Override some compiler defaults
+ defaultOptionsMap.put(JavaCore.COMPILER_LOCAL_VARIABLE_ATTR, JavaCore.GENERATE);
+ defaultOptionsMap.put(JavaCore.COMPILER_CODEGEN_UNUSED_LOCAL, JavaCore.PRESERVE);
+ defaultOptionsMap.put(JavaCore.COMPILER_TASK_TAGS, JavaCore.DEFAULT_TASK_TAGS);
+ defaultOptionsMap.put(JavaCore.COMPILER_TASK_PRIORITIES, JavaCore.DEFAULT_TASK_PRIORITIES);
+ defaultOptionsMap.put(JavaCore.COMPILER_TASK_CASE_SENSITIVE, JavaCore.ENABLED);
+ defaultOptionsMap.put(JavaCore.COMPILER_DOC_COMMENT_SUPPORT, JavaCore.ENABLED);
+ defaultOptionsMap.put(JavaCore.COMPILER_PB_FORBIDDEN_REFERENCE, JavaCore.ERROR);
+
+ // Builder settings
+ defaultOptionsMap.put(JavaCore.CORE_JAVA_BUILD_RESOURCE_COPY_FILTER, ""); //$NON-NLS-1$
+ defaultOptionsMap.put(JavaCore.CORE_JAVA_BUILD_INVALID_CLASSPATH, JavaCore.ABORT);
+ defaultOptionsMap.put(JavaCore.CORE_JAVA_BUILD_DUPLICATE_RESOURCE, JavaCore.WARNING);
+ defaultOptionsMap.put(JavaCore.CORE_JAVA_BUILD_CLEAN_OUTPUT_FOLDER, JavaCore.CLEAN);
+
+ // JavaCore settings
+ defaultOptionsMap.put(JavaCore.CORE_JAVA_BUILD_ORDER, JavaCore.IGNORE);
+ defaultOptionsMap.put(JavaCore.CORE_INCOMPLETE_CLASSPATH, JavaCore.ERROR);
+ defaultOptionsMap.put(JavaCore.CORE_CIRCULAR_CLASSPATH, JavaCore.ERROR);
+ defaultOptionsMap.put(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL, JavaCore.IGNORE);
+ defaultOptionsMap.put(JavaCore.CORE_ENABLE_CLASSPATH_EXCLUSION_PATTERNS, JavaCore.ENABLED);
+ defaultOptionsMap.put(JavaCore.CORE_ENABLE_CLASSPATH_MULTIPLE_OUTPUT_LOCATIONS, JavaCore.ENABLED);
+
+ // Formatter settings
+ defaultOptionsMap.putAll(DefaultCodeFormatterConstants.getEclipseDefaultSettings());
+
+ // CodeAssist settings
+ defaultOptionsMap.put(JavaCore.CODEASSIST_VISIBILITY_CHECK, JavaCore.DISABLED);
+ defaultOptionsMap.put(JavaCore.CODEASSIST_DEPRECATION_CHECK, JavaCore.DISABLED);
+ defaultOptionsMap.put(JavaCore.CODEASSIST_IMPLICIT_QUALIFICATION, JavaCore.DISABLED);
+ defaultOptionsMap.put(JavaCore.CODEASSIST_FIELD_PREFIXES, ""); //$NON-NLS-1$
+ defaultOptionsMap.put(JavaCore.CODEASSIST_STATIC_FIELD_PREFIXES, ""); //$NON-NLS-1$
+ defaultOptionsMap.put(JavaCore.CODEASSIST_LOCAL_PREFIXES, ""); //$NON-NLS-1$
+ defaultOptionsMap.put(JavaCore.CODEASSIST_ARGUMENT_PREFIXES, ""); //$NON-NLS-1$
+ defaultOptionsMap.put(JavaCore.CODEASSIST_FIELD_SUFFIXES, ""); //$NON-NLS-1$
+ defaultOptionsMap.put(JavaCore.CODEASSIST_STATIC_FIELD_SUFFIXES, ""); //$NON-NLS-1$
+ defaultOptionsMap.put(JavaCore.CODEASSIST_LOCAL_SUFFIXES, ""); //$NON-NLS-1$
+ defaultOptionsMap.put(JavaCore.CODEASSIST_ARGUMENT_SUFFIXES, ""); //$NON-NLS-1$
+ defaultOptionsMap.put(JavaCore.CODEASSIST_FORBIDDEN_REFERENCE_CHECK, JavaCore.ENABLED);
+ defaultOptionsMap.put(JavaCore.CODEASSIST_DISCOURAGED_REFERENCE_CHECK, JavaCore.DISABLED);
+ defaultOptionsMap.put(JavaCore.CODEASSIST_CAMEL_CASE_MATCH, JavaCore.ENABLED);
+ defaultOptionsMap.put(JavaCore.CODEASSIST_SUGGEST_STATIC_IMPORTS, JavaCore.ENABLED);
+
+ // Time out for parameter names
+ defaultOptionsMap.put(JavaCore.TIMEOUT_FOR_PARAMETER_NAME_FROM_ATTACHED_JAVADOC, "50"); //$NON-NLS-1$
+
+ return new Hashtable(defaultOptionsMap);
+ }
/*
* Returns the per-project info for the given project. If specified, create the info if the info doesn't exist.
@@ -1262,31 +1827,34 @@
if (previousContainerValues != null){
IClasspathContainer previousContainer = (IClasspathContainer)previousContainerValues.get(containerPath);
if (previousContainer != null) {
- if (JavaModelManager.CP_RESOLVE_VERBOSE){
- StringBuffer buffer = new StringBuffer();
- buffer.append("CPContainer INIT - reentering access to project container during its initialization, will see previous value\n"); //$NON-NLS-1$
- buffer.append(" project: " + project.getElementName() + '\n'); //$NON-NLS-1$
- buffer.append(" container path: " + containerPath + '\n'); //$NON-NLS-1$
- buffer.append(" previous value: "); //$NON-NLS-1$
- buffer.append(previousContainer.getDescription());
- buffer.append(" {\n"); //$NON-NLS-1$
- IClasspathEntry[] entries = previousContainer.getClasspathEntries();
- if (entries != null){
- for (int j = 0; j < entries.length; j++){
- buffer.append(" "); //$NON-NLS-1$
- buffer.append(entries[j]);
- buffer.append('\n');
- }
- }
- buffer.append(" }"); //$NON-NLS-1$
- Util.verbose(buffer.toString());
- new Exception("<Fake exception>").printStackTrace(System.out); //$NON-NLS-1$
- }
+ if (JavaModelManager.CP_RESOLVE_VERBOSE_ADVANCED)
+ verbose_reentering_project_container_access(containerPath, project, previousContainer);
return previousContainer;
}
}
return null; // break cycle if none found
}
+
+ private void verbose_reentering_project_container_access( IPath containerPath, IJavaProject project, IClasspathContainer previousContainer) {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("CPContainer INIT - reentering access to project container during its initialization, will see previous value\n"); //$NON-NLS-1$
+ buffer.append(" project: " + project.getElementName() + '\n'); //$NON-NLS-1$
+ buffer.append(" container path: " + containerPath + '\n'); //$NON-NLS-1$
+ buffer.append(" previous value: "); //$NON-NLS-1$
+ buffer.append(previousContainer.getDescription());
+ buffer.append(" {\n"); //$NON-NLS-1$
+ IClasspathEntry[] entries = previousContainer.getClasspathEntries();
+ if (entries != null){
+ for (int j = 0; j < entries.length; j++){
+ buffer.append(" "); //$NON-NLS-1$
+ buffer.append(entries[j]);
+ buffer.append('\n');
+ }
+ }
+ buffer.append(" }"); //$NON-NLS-1$
+ Util.verbose(buffer.toString());
+ new Exception("<Fake exception>").printStackTrace(System.out); //$NON-NLS-1$
+ }
/**
* Returns a persisted container from previous session if any
@@ -1294,18 +1862,21 @@
public IPath getPreviousSessionVariable(String variableName) {
IPath previousPath = (IPath)this.previousSessionVariables.get(variableName);
if (previousPath != null){
- if (CP_RESOLVE_VERBOSE){
- Util.verbose(
- "CPVariable INIT - reentering access to variable during its initialization, will see previous value\n" + //$NON-NLS-1$
- " variable: "+ variableName + '\n' + //$NON-NLS-1$
- " previous value: " + previousPath); //$NON-NLS-1$
- new Exception("<Fake exception>").printStackTrace(System.out); //$NON-NLS-1$
- }
+ if (CP_RESOLVE_VERBOSE_ADVANCED)
+ verbose_reentering_variable_access(variableName, previousPath);
return previousPath;
}
return null; // break cycle
}
-
+
+ private void verbose_reentering_variable_access(String variableName, IPath previousPath) {
+ Util.verbose(
+ "CPVariable INIT - reentering access to variable during its initialization, will see previous value\n" + //$NON-NLS-1$
+ " variable: "+ variableName + '\n' + //$NON-NLS-1$
+ " previous value: " + previousPath); //$NON-NLS-1$
+ new Exception("<Fake exception>").printStackTrace(System.out); //$NON-NLS-1$
+ }
+
/**
* Returns the temporary cache for newly opened elements for the current thread.
* Creates it if not already created.
@@ -1382,6 +1953,20 @@
return workingLocation.append("state.dat").toFile(); //$NON-NLS-1$
}
+ public static UserLibraryManager getUserLibraryManager() {
+ JavaModelManager modelManager = getJavaModelManager();
+ if (modelManager.userLibraryManager == null) {
+ UserLibraryManager libraryManager = new UserLibraryManager();
+ synchronized(modelManager) {
+ if (modelManager.userLibraryManager == null) { // ensure another library manager was not set while creating the instance above
+ modelManager.userLibraryManager = libraryManager;
+ modelManager.getInstancePreferences().addPreferenceChangeListener(libraryManager);
+ }
+ }
+ }
+ return modelManager.userLibraryManager;
+ }
+
/*
* Returns all the working copies which have the given owner.
* Adds the working copies of the primary owner if specified.
@@ -1424,9 +2009,13 @@
}
/**
- * Returns the open ZipFile at the given location. If the ZipFile
+ * Returns the open ZipFile at the given path. If the ZipFile
* does not yet exist, it is created, opened, and added to the cache
- * of open ZipFiles. The path must be absolute.
+ * of open ZipFiles.
+ *
+ * The path must be a file system path if representing an external
+ * zip/jar, or it must be an absolute workspace relative path if
+ * representing a zip/jar inside the workspace.
*
* @exception CoreException If unable to create/open the ZipFile
*/
@@ -1439,26 +2028,28 @@
return zipFile;
}
- String fileSystemPath= null;
+ File localFile = null;
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
IResource file = root.findMember(path);
if (file != null) {
// internal resource
- IPath location;
- if (file.getType() != IResource.FILE || (location = file.getLocation()) == null) {
+ URI location;
+ if (file.getType() != IResource.FILE || (location = file.getLocationURI()) == null) {
throw new CoreException(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.bind(Messages.file_notFound, path.toString()), null));
}
- fileSystemPath= location.toOSString();
+ localFile = Util.toLocalFile(location, null/*no progress availaible*/);
+ if (localFile == null)
+ throw new CoreException(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.bind(Messages.file_notFound, path.toString()), null));
} else {
- // external resource
- fileSystemPath= path.toOSString();
+ // external resource -> it is ok to use toFile()
+ localFile= path.toFile();
}
try {
if (ZIP_ACCESS_VERBOSE) {
- System.out.println("(" + Thread.currentThread() + ") [JavaModelManager.getZipFile(IPath)] Creating ZipFile on " + fileSystemPath ); //$NON-NLS-1$ //$NON-NLS-2$
+ System.out.println("(" + Thread.currentThread() + ") [JavaModelManager.getZipFile(IPath)] Creating ZipFile on " + localFile ); //$NON-NLS-1$ //$NON-NLS-2$
}
- zipFile = new ZipFile(fileSystemPath);
+ zipFile = new ZipFile(localFile);
if (map != null) {
map.put(path, zipFile);
}
@@ -1480,21 +2071,17 @@
* Return the container for the given path and project.
*/
private IClasspathContainer initializeAllContainers(IJavaProject javaProjectToInit, IPath containerToInit) throws JavaModelException {
- if (CP_RESOLVE_VERBOSE) {
- Util.verbose(
- "CPContainer INIT - batching containers initialization\n" + //$NON-NLS-1$
- " project to init: " + javaProjectToInit.getElementName() + '\n' + //$NON-NLS-1$
- " container path to init: " + containerToInit); //$NON-NLS-1$
- }
+ if (CP_RESOLVE_VERBOSE_ADVANCED)
+ verbose_batching_containers_initialization(javaProjectToInit, containerToInit);
// collect all container paths
- HashMap allContainerPaths = new HashMap();
+ final HashMap allContainerPaths = new HashMap();
IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
for (int i = 0, length = projects.length; i < length; i++) {
IProject project = projects[i];
if (!JavaProject.hasJavaNature(project)) continue;
IJavaProject javaProject = new JavaProject(project, getJavaModel());
- HashSet paths = null;
+ HashSet paths = (HashSet) allContainerPaths.get(javaProject);
IClasspathEntry[] rawClasspath = javaProject.getRawClasspath();
for (int j = 0, length2 = rawClasspath.length; j < length2; j++) {
IClasspathEntry entry = rawClasspath[j];
@@ -1506,6 +2093,8 @@
allContainerPaths.put(javaProject, paths);
}
paths.add(path);
+ // mark container as being initialized
+ containerAddInitializationInProgress(javaProject, path);
}
}
/* TODO (frederic) put back when JDT/UI dummy project will be thrown away...
@@ -1527,31 +2116,60 @@
allContainerPaths.put(javaProjectToInit, containerPaths);
}
containerPaths.add(containerToInit);
+ // mark container as being initialized
+ containerAddInitializationInProgress(javaProjectToInit, containerToInit);
// end block
- // mark all containers as being initialized
- this.containerInitializationInProgress.set(allContainerPaths);
-
// initialize all containers
boolean ok = false;
try {
- Set keys = allContainerPaths.keySet();
- int length = keys.size();
- IJavaProject[] javaProjects = new IJavaProject[length]; // clone as the following will have a side effect
- keys.toArray(javaProjects);
- for (int i = 0; i < length; i++) {
- IJavaProject javaProject = javaProjects[i];
- HashSet pathSet = (HashSet) allContainerPaths.get(javaProject);
- if (pathSet == null) continue;
- int length2 = pathSet.size();
- IPath[] paths = new IPath[length2];
- pathSet.toArray(paths); // clone as the following will have a side effect
- for (int j = 0; j < length2; j++) {
- IPath path = paths[j];
- initializeContainer(javaProject, path);
- }
- }
+ // if possible run inside an IWokspaceRunnable with AVOID_UPATE to avoid unwanted builds
+ // (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=118507)
+ IWorkspaceRunnable runnable =
+ new IWorkspaceRunnable() {
+ public void run(IProgressMonitor monitor) throws CoreException {
+ try {
+ Set entrySet = allContainerPaths.entrySet();
+ int length = entrySet.size();
+ if (monitor != null)
+ monitor.beginTask("", length); //$NON-NLS-1$
+ Map.Entry[] entries = new Map.Entry[length]; // clone as the following will have a side effect
+ entrySet.toArray(entries);
+ for (int i = 0; i < length; i++) {
+ Map.Entry entry = entries[i];
+ IJavaProject javaProject = (IJavaProject) entry.getKey();
+ HashSet pathSet = (HashSet) entry.getValue();
+ if (pathSet == null) continue;
+ int length2 = pathSet.size();
+ IPath[] paths = new IPath[length2];
+ pathSet.toArray(paths); // clone as the following will have a side effect
+ for (int j = 0; j < length2; j++) {
+ IPath path = paths[j];
+ initializeContainer(javaProject, path);
+ }
+ if (monitor != null)
+ monitor.worked(1);
+ }
+ } finally {
+ if (monitor != null)
+ monitor.done();
+ }
+ }
+ };
+ IProgressMonitor monitor = (IProgressMonitor) this.batchContainerInitializationsProgress.get();
+ IWorkspace workspace = ResourcesPlugin.getWorkspace();
+ if (workspace.isTreeLocked())
+ runnable.run(monitor);
+ else
+ workspace.run(
+ runnable,
+ null/*don't take any lock*/,
+ IWorkspace.AVOID_UPDATE,
+ monitor);
ok = true;
+ } catch (CoreException e) {
+ // ignore
+ Util.log(e, "Exception while initializing all containers"); //$NON-NLS-1$
} finally {
if (!ok) {
// if we're being traversed by an exception, ensure that that containers are
@@ -1564,20 +2182,26 @@
return containerGet(javaProjectToInit, containerToInit);
}
- private IClasspathContainer initializeContainer(IJavaProject project, IPath containerPath) throws JavaModelException {
+ private void verbose_batching_containers_initialization(IJavaProject javaProjectToInit, IPath containerToInit) {
+ Util.verbose(
+ "CPContainer INIT - batching containers initialization\n" + //$NON-NLS-1$
+ " project to init: " + javaProjectToInit.getElementName() + '\n' + //$NON-NLS-1$
+ " container path to init: " + containerToInit); //$NON-NLS-1$
+ }
+ IClasspathContainer initializeContainer(IJavaProject project, IPath containerPath) throws JavaModelException {
+
+ IProgressMonitor monitor = (IProgressMonitor) this.batchContainerInitializationsProgress.get();
+ if (monitor != null && monitor.isCanceled())
+ throw new OperationCanceledException();
+
IClasspathContainer container = null;
final ClasspathContainerInitializer initializer = JavaCore.getClasspathContainerInitializer(containerPath.segment(0));
if (initializer != null){
- if (CP_RESOLVE_VERBOSE){
- Util.verbose(
- "CPContainer INIT - triggering initialization\n" + //$NON-NLS-1$
- " project: " + project.getElementName() + '\n' + //$NON-NLS-1$
- " container path: " + containerPath + '\n' + //$NON-NLS-1$
- " initializer: " + initializer + '\n' + //$NON-NLS-1$
- " invocation stack trace:"); //$NON-NLS-1$
- new Exception("<Fake exception>").printStackTrace(System.out); //$NON-NLS-1$
- }
+ if (CP_RESOLVE_VERBOSE)
+ verbose_triggering_container_initialization(project, containerPath, initializer);
+ if (CP_RESOLVE_VERBOSE_ADVANCED)
+ verbose_triggering_container_initialization_invocation_trace();
PerformanceStats stats = null;
if(JavaModelManager.PERF_CONTAINER_INITIALIZER) {
stats = PerformanceStats.getStats(JavaModelManager.CONTAINER_INITIALIZER_PERF, this);
@@ -1586,13 +2210,30 @@
containerPut(project, containerPath, CONTAINER_INITIALIZATION_IN_PROGRESS); // avoid initialization cycles
boolean ok = false;
try {
+ if (monitor != null)
+ monitor.subTask(Messages.bind(Messages.javamodel_configuring, initializer.getDescription(containerPath, project)));
+
// let OperationCanceledException go through
// (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=59363)
initializer.initialize(containerPath, project);
+ if (monitor != null)
+ monitor.subTask(""); //$NON-NLS-1$
+
// retrieve value (if initialization was successful)
container = containerGet(project, containerPath);
- if (container == CONTAINER_INITIALIZATION_IN_PROGRESS) return null; // break cycle
+ if (container == CONTAINER_INITIALIZATION_IN_PROGRESS) {
+ // initializer failed to do its job: redirect to the failure container
+ container = initializer.getFailureContainer(containerPath, project);
+ if (container == null) {
+ if (CP_RESOLVE_VERBOSE)
+ verbose_container_null_failure_container(project, containerPath, initializer);
+ return null; // break cycle
+ }
+ if (CP_RESOLVE_VERBOSE)
+ verbose_container_using_failure_container(project, containerPath, initializer);
+ containerPut(project, containerPath, container);
+ }
ok = true;
} catch (CoreException e) {
if (e instanceof JavaModelException) {
@@ -1601,14 +2242,12 @@
throw new JavaModelException(e);
}
} catch (RuntimeException e) {
- if (JavaModelManager.CP_RESOLVE_VERBOSE) {
+ if (JavaModelManager.CP_RESOLVE_VERBOSE)
e.printStackTrace();
- }
throw e;
} catch (Error e) {
- if (JavaModelManager.CP_RESOLVE_VERBOSE) {
+ if (JavaModelManager.CP_RESOLVE_VERBOSE)
e.printStackTrace();
- }
throw e;
} finally {
if(JavaModelManager.PERF_CONTAINER_INITIALIZER) {
@@ -1618,62 +2257,108 @@
// just remove initialization in progress and keep previous session container so as to avoid a full build
// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=92588
containerRemoveInitializationInProgress(project, containerPath);
- if (CP_RESOLVE_VERBOSE) {
- if (container == CONTAINER_INITIALIZATION_IN_PROGRESS) {
- Util.verbose(
- "CPContainer INIT - FAILED (initializer did not initialize container)\n" + //$NON-NLS-1$
- " project: " + project.getElementName() + '\n' + //$NON-NLS-1$
- " container path: " + containerPath + '\n' + //$NON-NLS-1$
- " initializer: " + initializer); //$NON-NLS-1$
-
- } else {
- Util.verbose(
- "CPContainer INIT - FAILED (see exception above)\n" + //$NON-NLS-1$
- " project: " + project.getElementName() + '\n' + //$NON-NLS-1$
- " container path: " + containerPath + '\n' + //$NON-NLS-1$
- " initializer: " + initializer); //$NON-NLS-1$
- }
- }
+ if (CP_RESOLVE_VERBOSE)
+ verbose_container_initialization_failed(project, containerPath, container, initializer);
}
}
- if (CP_RESOLVE_VERBOSE){
- StringBuffer buffer = new StringBuffer();
- buffer.append("CPContainer INIT - after resolution\n"); //$NON-NLS-1$
- buffer.append(" project: " + project.getElementName() + '\n'); //$NON-NLS-1$
- buffer.append(" container path: " + containerPath + '\n'); //$NON-NLS-1$
- if (container != null){
- buffer.append(" container: "+container.getDescription()+" {\n"); //$NON-NLS-2$//$NON-NLS-1$
- IClasspathEntry[] entries = container.getClasspathEntries();
- if (entries != null){
- for (int i = 0; i < entries.length; i++){
- buffer.append(" " + entries[i] + '\n'); //$NON-NLS-1$
- }
- }
- buffer.append(" }");//$NON-NLS-1$
- } else {
- buffer.append(" container: {unbound}");//$NON-NLS-1$
- }
- Util.verbose(buffer.toString());
- }
+ if (CP_RESOLVE_VERBOSE_ADVANCED)
+ verbose_container_value_after_initialization(project, containerPath, container);
} else {
- if (CP_RESOLVE_VERBOSE){
- Util.verbose(
- "CPContainer INIT - no initializer found\n" + //$NON-NLS-1$
- " project: " + project.getElementName() + '\n' + //$NON-NLS-1$
- " container path: " + containerPath); //$NON-NLS-1$
- }
+ // create a dummy initializer and get the default failure container
+ container = (new ClasspathContainerInitializer() {
+ public void initialize(IPath path, IJavaProject javaProject) throws CoreException {
+ // not used
+ }
+ }).getFailureContainer(containerPath, project);
+ if (CP_RESOLVE_VERBOSE_ADVANCED)
+ verbose_no_container_initializer_found(project, containerPath);
}
return container;
}
+ private void verbose_no_container_initializer_found(IJavaProject project, IPath containerPath) {
+ Util.verbose(
+ "CPContainer INIT - no initializer found\n" + //$NON-NLS-1$
+ " project: " + project.getElementName() + '\n' + //$NON-NLS-1$
+ " container path: " + containerPath); //$NON-NLS-1$
+ }
+
+ private void verbose_container_value_after_initialization(IJavaProject project, IPath containerPath, IClasspathContainer container) {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("CPContainer INIT - after resolution\n"); //$NON-NLS-1$
+ buffer.append(" project: " + project.getElementName() + '\n'); //$NON-NLS-1$
+ buffer.append(" container path: " + containerPath + '\n'); //$NON-NLS-1$
+ if (container != null){
+ buffer.append(" container: "+container.getDescription()+" {\n"); //$NON-NLS-2$//$NON-NLS-1$
+ IClasspathEntry[] entries = container.getClasspathEntries();
+ if (entries != null){
+ for (int i = 0; i < entries.length; i++) {
+ buffer.append(" " + entries[i] + '\n'); //$NON-NLS-1$
+ }
+ }
+ buffer.append(" }");//$NON-NLS-1$
+ } else {
+ buffer.append(" container: {unbound}");//$NON-NLS-1$
+ }
+ Util.verbose(buffer.toString());
+ }
+
+ private void verbose_container_initialization_failed(IJavaProject project, IPath containerPath, IClasspathContainer container, ClasspathContainerInitializer initializer) {
+ if (container == CONTAINER_INITIALIZATION_IN_PROGRESS) {
+ Util.verbose(
+ "CPContainer INIT - FAILED (initializer did not initialize container)\n" + //$NON-NLS-1$
+ " project: " + project.getElementName() + '\n' + //$NON-NLS-1$
+ " container path: " + containerPath + '\n' + //$NON-NLS-1$
+ " initializer: " + initializer); //$NON-NLS-1$
+
+ } else {
+ Util.verbose(
+ "CPContainer INIT - FAILED (see exception above)\n" + //$NON-NLS-1$
+ " project: " + project.getElementName() + '\n' + //$NON-NLS-1$
+ " container path: " + containerPath + '\n' + //$NON-NLS-1$
+ " initializer: " + initializer); //$NON-NLS-1$
+ }
+ }
+
+ private void verbose_container_null_failure_container(IJavaProject project, IPath containerPath, ClasspathContainerInitializer initializer) {
+ Util.verbose(
+ "CPContainer INIT - FAILED (and failure container is null)\n" + //$NON-NLS-1$
+ " project: " + project.getElementName() + '\n' + //$NON-NLS-1$
+ " container path: " + containerPath + '\n' + //$NON-NLS-1$
+ " initializer: " + initializer); //$NON-NLS-1$
+ }
+
+ private void verbose_container_using_failure_container(IJavaProject project, IPath containerPath, ClasspathContainerInitializer initializer) {
+ Util.verbose(
+ "CPContainer INIT - FAILED (using failure container)\n" + //$NON-NLS-1$
+ " project: " + project.getElementName() + '\n' + //$NON-NLS-1$
+ " container path: " + containerPath + '\n' + //$NON-NLS-1$
+ " initializer: " + initializer); //$NON-NLS-1$
+ }
+
+ private void verbose_triggering_container_initialization(IJavaProject project, IPath containerPath, ClasspathContainerInitializer initializer) {
+ Util.verbose(
+ "CPContainer INIT - triggering initialization\n" + //$NON-NLS-1$
+ " project: " + project.getElementName() + '\n' + //$NON-NLS-1$
+ " container path: " + containerPath + '\n' + //$NON-NLS-1$
+ " initializer: " + initializer); //$NON-NLS-1$
+ }
+
+ private void verbose_triggering_container_initialization_invocation_trace() {
+ Util.verbose(
+ "CPContainer INIT - triggering initialization\n" + //$NON-NLS-1$
+ " invocation trace:"); //$NON-NLS-1$
+ new Exception("<Fake exception>").printStackTrace(System.out); //$NON-NLS-1$
+ }
+
/**
* Initialize preferences lookups for JavaCore plugin.
*/
public void initializePreferences() {
// Create lookups
- preferencesLookup[PREF_INSTANCE] = new InstanceScope().getNode(JavaCore.PLUGIN_ID);
- preferencesLookup[PREF_DEFAULT] = new DefaultScope().getNode(JavaCore.PLUGIN_ID);
+ preferencesLookup[PREF_INSTANCE] = ((IScopeContext) new InstanceScope()).getNode(JavaCore.PLUGIN_ID);
+ preferencesLookup[PREF_DEFAULT] = ((IScopeContext) new DefaultScope()).getNode(JavaCore.PLUGIN_ID);
// Listen to instance preferences node removal from parent in order to refresh stored one
IEclipsePreferences.INodeChangeListener listener = new IEclipsePreferences.INodeChangeListener() {
@@ -1682,7 +2367,7 @@
}
public void removed(IEclipsePreferences.NodeChangeEvent event) {
if (event.getChild() == preferencesLookup[PREF_INSTANCE]) {
- preferencesLookup[PREF_INSTANCE] = new InstanceScope().getNode(JavaCore.PLUGIN_ID);
+ preferencesLookup[PREF_INSTANCE] = ((IScopeContext) new InstanceScope()).getNode(JavaCore.PLUGIN_ID);
preferencesLookup[PREF_INSTANCE].addPreferenceChangeListener(new EclipsePreferencesListener());
}
}
@@ -1697,7 +2382,7 @@
}
public void removed(IEclipsePreferences.NodeChangeEvent event) {
if (event.getChild() == preferencesLookup[PREF_DEFAULT]) {
- preferencesLookup[PREF_DEFAULT] = new DefaultScope().getNode(JavaCore.PLUGIN_ID);
+ preferencesLookup[PREF_DEFAULT] = ((IScopeContext) new DefaultScope()).getNode(JavaCore.PLUGIN_ID);
}
}
};
@@ -1803,7 +2488,75 @@
}
// backward compatibility, load variables and containers from preferences into cache
- IEclipsePreferences preferences = getInstancePreferences();
+ loadVariablesAndContainers(getDefaultPreferences());
+ loadVariablesAndContainers(getInstancePreferences());
+
+ // load variables and containers from saved file into cache
+ File file = getVariableAndContainersFile();
+ DataInputStream in = null;
+ try {
+ in = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));
+ switch (in.readInt()) {
+ case 2 :
+ new VariablesAndContainersLoadHelper(in).load();
+ break;
+ case 1 : // backward compatibility, load old format
+ // variables
+ int size = in.readInt();
+ while (size-- > 0) {
+ String varName = in.readUTF();
+ String pathString = in.readUTF();
+ if (CP_ENTRY_IGNORE.equals(pathString))
+ continue;
+ IPath varPath = Path.fromPortableString(pathString);
+ this.variables.put(varName, varPath);
+ this.previousSessionVariables.put(varName, varPath);
+ }
+
+ // containers
+ IJavaModel model = getJavaModel();
+ int projectSize = in.readInt();
+ while (projectSize-- > 0) {
+ String projectName = in.readUTF();
+ IJavaProject project = model.getJavaProject(projectName);
+ int containerSize = in.readInt();
+ while (containerSize-- > 0) {
+ IPath containerPath = Path.fromPortableString(in.readUTF());
+ int length = in.readInt();
+ byte[] containerString = new byte[length];
+ in.readFully(containerString);
+ recreatePersistedContainer(project, containerPath, new String(containerString), true/*add to container values*/);
+ }
+ }
+ break;
+ }
+ } catch (IOException e) {
+ if (file.exists())
+ Util.log(e, "Unable to read variable and containers file"); //$NON-NLS-1$
+ } catch (RuntimeException e) {
+ if (file.exists())
+ Util.log(e, "Unable to read variable and containers file (file is corrupt)"); //$NON-NLS-1$
+ } finally {
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException e) {
+ // nothing we can do: ignore
+ }
+ }
+ }
+
+ // override persisted values for variables which have a registered initializer
+ String[] registeredVariables = getRegisteredVariableNames();
+ for (int i = 0; i < registeredVariables.length; i++) {
+ String varName = registeredVariables[i];
+ this.variables.put(varName, null); // reset variable, but leave its entry in the Map, so it will be part of variable names.
+ }
+ // override persisted values for containers which have a registered initializer
+ containersReset(getRegisteredContainerIDs());
+ }
+
+ private void loadVariablesAndContainers(IEclipsePreferences preferences) {
try {
// only get variable from preferences not set to their default
String[] propertyNames = preferences.keys();
@@ -1841,63 +2594,285 @@
} catch (BackingStoreException e1) {
// TODO (frederic) see if it's necessary to report this failure...
}
+ }
- // load variables and containers from saved file into cache
- File file = getVariableAndContainersFile();
- DataInputStream in = null;
- try {
- in = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));
- if (VARIABLES_AND_CONTAINERS_FILE_VERSION == in.readInt()) {
-
- // variables
- int size = in.readInt();
- while (size-- > 0) {
- String varName = in.readUTF();
- String pathString = in.readUTF();
- if (CP_ENTRY_IGNORE.equals(pathString))
- continue;
- IPath varPath = Path.fromPortableString(pathString);
- this.variables.put(varName, varPath);
- this.previousSessionVariables.put(varName, varPath);
- }
-
- // containers
- IJavaModel model = getJavaModel();
- int projectSize = in.readInt();
- while (projectSize-- > 0) {
- String projectName = in.readUTF();
- IJavaProject project = model.getJavaProject(projectName);
- int containerSize = in.readInt();
- while (containerSize-- > 0) {
- IPath containerPath = Path.fromPortableString(in.readUTF());
- int length = in.readInt();
- byte[] containerString = new byte[length];
- in.readFully(containerString);
- recreatePersistedContainer(project, containerPath, new String(containerString), true/*add to container values*/);
- }
- }
+ private static final class PersistedClasspathContainer implements
+ IClasspathContainer {
+
+ private final IPath containerPath;
+
+ private final IClasspathEntry[] entries;
+
+ private final IJavaProject project;
+
+ PersistedClasspathContainer(IJavaProject project, IPath containerPath,
+ IClasspathEntry[] entries) {
+ super();
+ this.containerPath = containerPath;
+ this.entries = entries;
+ this.project = project;
+ }
+
+ public IClasspathEntry[] getClasspathEntries() {
+ return entries;
+ }
+
+ public String getDescription() {
+ return "Persisted container [" + containerPath //$NON-NLS-1$
+ + " for project [" + project.getElementName() //$NON-NLS-1$
+ + "]]"; //$NON-NLS-1$
+ }
+
+ public int getKind() {
+ return 0;
+ }
+
+ public IPath getPath() {
+ return containerPath;
+ }
+
+ public String toString() {
+ return getDescription();
+ }
+ }
+
+ private final class VariablesAndContainersLoadHelper {
+
+ private static final int ARRAY_INCREMENT = 200;
+
+ private IClasspathEntry[] allClasspathEntries;
+ private int allClasspathEntryCount;
+
+ private final Map allPaths; // String -> IPath
+
+ private String[] allStrings;
+ private int allStringsCount;
+
+ private final DataInputStream in;
+
+ VariablesAndContainersLoadHelper(DataInputStream in) {
+ super();
+ this.allClasspathEntries = null;
+ this.allClasspathEntryCount = 0;
+ this.allPaths = new HashMap();
+ this.allStrings = null;
+ this.allStringsCount = 0;
+ this.in = in;
+ }
+
+ void load() throws IOException {
+ loadProjects(JavaModelManager.this.getJavaModel());
+ loadVariables();
+ }
+
+ private IAccessRule loadAccessRule() throws IOException {
+ int problemId = loadInt();
+ IPath pattern = loadPath();
+ return new ClasspathAccessRule(pattern.toString().toCharArray(), problemId);
+ }
+
+ private IAccessRule[] loadAccessRules() throws IOException {
+ int count = loadInt();
+
+ if (count == 0)
+ return ClasspathEntry.NO_ACCESS_RULES;
+
+ IAccessRule[] rules = new IAccessRule[count];
+
+ for (int i = 0; i < count; ++i)
+ rules[i] = loadAccessRule();
+
+ return rules;
+ }
+
+ private IClasspathAttribute loadAttribute() throws IOException {
+ String name = loadString();
+ String value = loadString();
+
+ return new ClasspathAttribute(name, value);
+ }
+
+ private IClasspathAttribute[] loadAttributes() throws IOException {
+ int count = loadInt();
+
+ if (count == 0)
+ return ClasspathEntry.NO_EXTRA_ATTRIBUTES;
+
+ IClasspathAttribute[] attributes = new IClasspathAttribute[count];
+
+ for (int i = 0; i < count; ++i)
+ attributes[i] = loadAttribute();
+
+ return attributes;
+ }
+
+ private boolean loadBoolean() throws IOException {
+ return this.in.readBoolean();
+ }
+
+ private IClasspathEntry[] loadClasspathEntries() throws IOException {
+ int count = loadInt();
+ IClasspathEntry[] entries = new IClasspathEntry[count];
+
+ for (int i = 0; i < count; ++i)
+ entries[i] = loadClasspathEntry();
+
+ return entries;
+ }
+
+ private IClasspathEntry loadClasspathEntry() throws IOException {
+ int id = loadInt();
+
+ if (id < 0 || id > this.allClasspathEntryCount)
+ throw new IOException("Unexpected classpathentry id"); //$NON-NLS-1$
+
+ if (id < this.allClasspathEntryCount)
+ return this.allClasspathEntries[id];
+
+ int contentKind = loadInt();
+ int entryKind = loadInt();
+ IPath path = loadPath();
+ IPath[] inclusionPatterns = loadPaths();
+ IPath[] exclusionPatterns = loadPaths();
+ IPath sourceAttachmentPath = loadPath();
+ IPath sourceAttachmentRootPath = loadPath();
+ IPath specificOutputLocation = loadPath();
+ boolean isExported = loadBoolean();
+ IAccessRule[] accessRules = loadAccessRules();
+ boolean combineAccessRules = loadBoolean();
+ IClasspathAttribute[] extraAttributes = loadAttributes();
+
+ IClasspathEntry entry = new ClasspathEntry(contentKind, entryKind,
+ path, inclusionPatterns, exclusionPatterns,
+ sourceAttachmentPath, sourceAttachmentRootPath,
+ specificOutputLocation, isExported, accessRules,
+ combineAccessRules, extraAttributes);
+
+ IClasspathEntry[] array = this.allClasspathEntries;
+
+ if (array == null || id == array.length) {
+ array = new IClasspathEntry[id + ARRAY_INCREMENT];
+
+ if (id != 0)
+ System.arraycopy(this.allClasspathEntries, 0, array, 0, id);
+
+ this.allClasspathEntries = array;
}
- } catch (IOException e) {
- if (file.exists())
- Util.log(e, "Unable to read variable and containers file"); //$NON-NLS-1$
- } finally {
- if (in != null) {
- try {
- in.close();
- } catch (IOException e) {
- // nothing we can do: ignore
+
+ array[id] = entry;
+ this.allClasspathEntryCount = id + 1;
+
+ return entry;
+ }
+
+ private void loadContainers(IJavaProject project) throws IOException {
+ boolean projectIsAccessible = project.getProject().isAccessible();
+ int count = loadInt();
+ for (int i = 0; i < count; ++i) {
+ IPath path = loadPath();
+ IClasspathEntry[] entries = loadClasspathEntries();
+
+ if (!projectIsAccessible)
+ // avoid leaking deleted project's persisted container,
+ // but still read the container as it is is part of the file format
+ continue;
+
+ IClasspathContainer container = new PersistedClasspathContainer(project, path, entries);
+
+ JavaModelManager.this.containerPut(project, path, container);
+
+ Map oldContainers = (Map) JavaModelManager.this.previousSessionContainers.get(project);
+
+ if (oldContainers == null) {
+ oldContainers = new HashMap();
+ JavaModelManager.this.previousSessionContainers.put(project, oldContainers);
}
+
+ oldContainers.put(path, container);
}
}
- // override persisted values for variables which have a registered initializer
- String[] registeredVariables = getRegisteredVariableNames();
- for (int i = 0; i < registeredVariables.length; i++) {
- String varName = registeredVariables[i];
- this.variables.put(varName, null); // reset variable, but leave its entry in the Map, so it will be part of variable names.
+ private int loadInt() throws IOException {
+ return this.in.readInt();
}
- // override persisted values for containers which have a registered initializer
- containersReset(getRegisteredContainerIDs());
+
+ private IPath loadPath() throws IOException {
+ if (loadBoolean())
+ return null;
+
+ String portableString = loadString();
+ IPath path = (IPath) this.allPaths.get(portableString);
+
+ if (path == null) {
+ path = Path.fromPortableString(portableString);
+ this.allPaths.put(portableString, path);
+ }
+
+ return path;
+ }
+
+ private IPath[] loadPaths() throws IOException {
+ int count = loadInt();
+ IPath[] pathArray = new IPath[count];
+
+ for (int i = 0; i < count; ++i)
+ pathArray[i] = loadPath();
+
+ return pathArray;
+ }
+
+ private void loadProjects(IJavaModel model) throws IOException {
+ int count = loadInt();
+
+ for (int i = 0; i < count; ++i) {
+ String projectName = loadString();
+
+ loadContainers(model.getJavaProject(projectName));
+ }
+ }
+
+ private String loadString() throws IOException {
+ int id = loadInt();
+
+ if (id < 0 || id > this.allStringsCount)
+ throw new IOException("Unexpected string id"); //$NON-NLS-1$
+
+ if (id < this.allStringsCount)
+ return this.allStrings[id];
+
+ String string = this.in.readUTF();
+ String[] array = this.allStrings;
+
+ if (array == null || id == array.length) {
+ array = new String[id + ARRAY_INCREMENT];
+
+ if (id != 0)
+ System.arraycopy(this.allStrings, 0, array, 0, id);
+
+ this.allStrings = array;
+ }
+
+ array[id] = string;
+ this.allStringsCount = id + 1;
+
+ return string;
+ }
+
+ private void loadVariables() throws IOException {
+ int size = loadInt();
+ Map loadedVars = new HashMap(size);
+
+ for (int i = 0; i < size; ++i) {
+ String varName = loadString();
+ IPath varPath = loadPath();
+
+ if (varPath != null)
+ loadedVars.put(varName, varPath);
+ }
+
+ JavaModelManager.this.previousSessionVariables.putAll(loadedVars);
+ JavaModelManager.this.variables.putAll(loadedVars);
+ }
}
/**
@@ -1943,13 +2918,39 @@
}
}
- Iterator iterator = newElements.keySet().iterator();
+ // Need to put any JarPackageFragmentRoot in first.
+ // This is due to the way the LRU cache flushes entries.
+ // When a JarPackageFragment is flused from the LRU cache, the entire
+ // jar is flushed by removing the JarPackageFragmentRoot and all of its
+ // children (see ElementCache.close()). If we flush the JarPackageFragment
+ // when its JarPackageFragmentRoot is not in the cache and the root is about to be
+ // added (during the 'while' loop), we will end up in an inconsist state.
+ // Subsequent resolution against package in the jar would fail as a result.
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=102422
+ // (theodora)
+ for(Iterator it = newElements.entrySet().iterator(); it.hasNext(); ) {
+ Map.Entry entry = (Map.Entry)it.next();
+ IJavaElement element = (IJavaElement)entry.getKey();
+ if( element instanceof JarPackageFragmentRoot ){
+ Object info = entry.getValue();
+ it.remove();
+ this.cache.putInfo(element, info);
+ }
+ }
+
+ Iterator iterator = newElements.entrySet().iterator();
while (iterator.hasNext()) {
- IJavaElement element = (IJavaElement)iterator.next();
- Object info = newElements.get(element);
- this.cache.putInfo(element, info);
+ Map.Entry entry = (Map.Entry) iterator.next();
+ this.cache.putInfo((IJavaElement) entry.getKey(), entry.getValue());
}
}
+
+ /*
+ * Remember the info for the jar binary type
+ */
+ protected synchronized void putJarTypeInfo(IJavaElement type, Object info) {
+ this.cache.jarTypeCache.put(type, info);
+ }
/**
* Reads the build state for the relevant project.
@@ -2003,8 +3004,15 @@
if (containerString == null) {
getJavaModelManager().containerPut(project, containerPath, null);
} else {
- final IClasspathEntry[] containerEntries = ((JavaProject) project).decodeClasspath(containerString, false, false);
- if (containerEntries != null && containerEntries != JavaProject.INVALID_CLASSPATH) {
+ IClasspathEntry[] entries;
+ try {
+ entries = ((JavaProject) project).decodeClasspath(containerString, null/*not interested in unknown elements*/);
+ } catch (IOException e) {
+ Util.log(e, "Could not recreate persisted container: \n" + containerString); //$NON-NLS-1$
+ entries = JavaProject.INVALID_CLASSPATH;
+ }
+ if (entries != JavaProject.INVALID_CLASSPATH) {
+ final IClasspathEntry[] containerEntries = entries;
IClasspathContainer container = new IClasspathContainer() {
public IClasspathEntry[] getClasspathEntries() {
return containerEntries;
@@ -2055,7 +3063,7 @@
if (info != null) {
boolean wasVerbose = false;
try {
- if (VERBOSE) {
+ if (JavaModelCache.VERBOSE) {
String elementType;
switch (element.getElementType()) {
case IJavaElement.JAVA_PROJECT:
@@ -2078,7 +3086,7 @@
}
System.out.println(Thread.currentThread() + " CLOSING "+ elementType + " " + element.toStringWithAncestors()); //$NON-NLS-1$//$NON-NLS-2$
wasVerbose = true;
- VERBOSE = false;
+ JavaModelCache.VERBOSE = false;
}
element.closing(info);
if (element instanceof IParent && info instanceof JavaElementInfo) {
@@ -2093,7 +3101,7 @@
System.out.println(this.cache.toStringFillingRation("-> ")); //$NON-NLS-1$
}
} finally {
- JavaModelManager.VERBOSE = wasVerbose;
+ JavaModelCache.VERBOSE = wasVerbose;
}
return info;
}
@@ -2142,6 +3150,13 @@
}
/*
+ * Resets the cache that holds on binary type in jar files
+ */
+ protected synchronized void resetJarTypeCache() {
+ this.cache.resetJarTypeCache();
+ }
+
+ /*
* Resets the temporary cache for newly created elements to null.
*/
public void resetTemporaryCache() {
@@ -2212,72 +3227,80 @@
}
}
- private void saveVariablesAndContainers() throws CoreException {
+ private void saveVariablesAndContainers(ISaveContext context) throws CoreException {
File file = getVariableAndContainersFile();
DataOutputStream out = null;
try {
out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file)));
out.writeInt(VARIABLES_AND_CONTAINERS_FILE_VERSION);
-
- // variables
- out.writeInt(this.variables.size());
- Iterator variableNames = this.variables.keySet().iterator();
- while (variableNames.hasNext()) {
- String variableName = (String) variableNames.next();
- out.writeUTF(variableName);
- IPath path = (IPath) this.variables.get(variableName);
- out.writeUTF(path == null ? CP_ENTRY_IGNORE : path.toPortableString());
+ if (VARIABLES_AND_CONTAINERS_FILE_VERSION != 1)
+ new VariablesAndContainersSaveHelper(out).save(context);
+ else {
+ // old code retained for performance comparisons
+
+ // variables
+ out.writeInt(this.variables.size());
+ Iterator iterator = this.variables.entrySet().iterator();
+ while (iterator.hasNext()) {
+ Map.Entry entry = (Map.Entry) iterator.next();
+ String variableName = (String) entry.getKey();
+ out.writeUTF(variableName);
+ IPath path = (IPath) entry.getValue();
+ out.writeUTF(path == null ? CP_ENTRY_IGNORE : path.toPortableString());
+ }
+
+ // containers
+ IJavaProject[] projects = getJavaModel().getJavaProjects();
+ int length = projects.length;
+ out.writeInt(length);
+ for (int i = 0; i < length; i++) {
+ IJavaProject project = projects[i];
+ // clone while iterating (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=59638)
+ Map projectContainers = containerClone(project);
+ out.writeUTF(project.getElementName());
+ if (projectContainers == null) {
+ out.writeInt(0);
+ continue;
+ }
+ HashMap containersToSave = new HashMap();
+ for (iterator = projectContainers.entrySet().iterator(); iterator.hasNext();) {
+ Map.Entry entry = (Map.Entry) iterator.next();
+ IPath containerPath = (IPath) entry.getKey();
+ IClasspathContainer container = (IClasspathContainer) entry.getValue();
+ String containerString = null;
+ try {
+ if (container == null) {
+ // container has not been initialized yet, use previous session value
+ // (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=73969)
+ container = getPreviousSessionContainer(containerPath, project);
+ }
+ if (container != null) {
+ IClasspathEntry[] entries = container.getClasspathEntries();
+ containerString = ((JavaProject)project).encodeClasspath(
+ entries,
+ null,
+ false,
+ null/*not interested in unknown elements*/);
+ }
+ } catch(JavaModelException e){
+ // could not encode entry: will not persist
+ Util.log(e, "Could not persist container " + containerPath + " for project " + project.getElementName()); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ if (containerString != null)
+ containersToSave.put(containerPath, containerString);
+ }
+ out.writeInt(containersToSave.size());
+ iterator = containersToSave.entrySet().iterator();
+ while (iterator.hasNext()) {
+ Map.Entry entry = (Map.Entry) iterator.next();
+ IPath containerPath = (IPath) entry.getKey();
+ out.writeUTF(containerPath.toPortableString());
+ String containerString = (String) entry.getValue();
+ out.writeInt(containerString.length());
+ out.writeBytes(containerString);
+ }
+ }
}
-
- // containers
- IJavaProject[] projects = getJavaModel().getJavaProjects();
- int length = projects.length;
- out.writeInt(length);
- for (int i = 0; i < length; i++) {
- IJavaProject project = projects[i];
- // clone while iterating (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=59638)
- Map projectContainers = containerClone(project);
- out.writeUTF(project.getElementName());
- if (projectContainers == null) {
- out.writeInt(0);
- continue;
- }
- HashMap containersToSave = new HashMap();
- for (Iterator iterator = projectContainers.keySet().iterator(); iterator.hasNext();) {
- IPath containerPath = (IPath) iterator.next();
- IClasspathContainer container = (IClasspathContainer) projectContainers.get(containerPath);
- String containerString = null;
- try {
- if (container == null) {
- // container has not been initialized yet, use previous session value
- // (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=73969)
- container = getPreviousSessionContainer(containerPath, project);
- }
- if (container != null) {
- IClasspathEntry[] entries = container.getClasspathEntries();
- containerString = ((JavaProject)project).encodeClasspath(
- entries,
- null,
- false);
- }
- } catch(JavaModelException e){
- // could not encode entry: will not persist
- Util.log(e, "Could not persist container " + containerPath + " for project " + project.getElementName()); //$NON-NLS-1$ //$NON-NLS-2$
- }
- if (containerString != null)
- containersToSave.put(containerPath, containerString);
- }
- out.writeInt(containersToSave.size());
- Iterator iterator = containersToSave.keySet().iterator();
- while (iterator.hasNext()) {
- IPath containerPath = (IPath) iterator.next();
- out.writeUTF(containerPath.toPortableString());
- String containerString = (String) containersToSave.get(containerPath);
- out.writeInt(containerString.length());
- out.writeBytes(containerString);
- }
- }
-
} catch (IOException e) {
IStatus status = new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, IStatus.ERROR, "Problems while saving variables and containers", e); //$NON-NLS-1$
throw new CoreException(status);
@@ -2292,13 +3315,241 @@
}
}
+ private final class VariablesAndContainersSaveHelper {
+
+ private final HashtableOfObjectToInt classpathEntryIds; // IClasspathEntry -> int
+ private final DataOutputStream out;
+ private final HashtableOfObjectToInt stringIds; // Strings -> int
+
+ VariablesAndContainersSaveHelper(DataOutputStream out) {
+ super();
+ this.classpathEntryIds = new HashtableOfObjectToInt();
+ this.out = out;
+ this.stringIds = new HashtableOfObjectToInt();
+ }
+
+ void save(ISaveContext context) throws IOException, JavaModelException {
+ IProject project = context.getProject();
+ if (project == null) { // save all projects if none specified (snapshot or full save)
+ saveProjects(JavaModelManager.this.getJavaModel().getJavaProjects());
+ }
+ else {
+ saveProjects(new IJavaProject[] {JavaCore.create(project)});
+ }
+
+ switch (context.getKind()) {
+ case ISaveContext.FULL_SAVE :
+ // TODO (eric) - investigate after 3.3 if variables should be saved for a SNAPSHOT
+ case ISaveContext.SNAPSHOT :
+ // remove variables that should not be saved
+ HashMap varsToSave = null;
+ Iterator iterator = JavaModelManager.this.variables.entrySet().iterator();
+ IEclipsePreferences defaultPreferences = getDefaultPreferences();
+ while (iterator.hasNext()) {
+ Map.Entry entry = (Map.Entry) iterator.next();
+ String varName = (String) entry.getKey();
+ if (defaultPreferences.get(CP_VARIABLE_PREFERENCES_PREFIX + varName, null) != null // don't save classpath variables from the default preferences as there is no delta if they are removed
+ || CP_ENTRY_IGNORE_PATH.equals(entry.getValue())) {
+
+ if (varsToSave == null)
+ varsToSave = new HashMap(JavaModelManager.this.variables);
+ varsToSave.remove(varName);
+ }
+ }
+ saveVariables(varsToSave != null ? varsToSave : JavaModelManager.this.variables);
+ break;
+ default :
+ // do nothing
+ }
+ }
+
+ private void saveAccessRule(ClasspathAccessRule rule) throws IOException {
+ saveInt(rule.problemId);
+ savePath(rule.getPattern());
+ }
+
+ private void saveAccessRules(IAccessRule[] rules) throws IOException {
+ int count = rules == null ? 0 : rules.length;
+
+ saveInt(count);
+ for (int i = 0; i < count; ++i)
+ saveAccessRule((ClasspathAccessRule) rules[i]);
+ }
+
+ private void saveAttribute(IClasspathAttribute attribute)
+ throws IOException {
+ saveString(attribute.getName());
+ saveString(attribute.getValue());
+ }
+
+ private void saveAttributes(IClasspathAttribute[] attributes)
+ throws IOException {
+ int count = attributes == null ? 0 : attributes.length;
+
+ saveInt(count);
+ for (int i = 0; i < count; ++i)
+ saveAttribute(attributes[i]);
+ }
+
+ private void saveClasspathEntries(IClasspathEntry[] entries)
+ throws IOException {
+ int count = entries == null ? 0 : entries.length;
+
+ saveInt(count);
+ for (int i = 0; i < count; ++i)
+ saveClasspathEntry(entries[i]);
+ }
+
+ private void saveClasspathEntry(IClasspathEntry entry)
+ throws IOException {
+ if (saveNewId(entry, this.classpathEntryIds)) {
+ saveInt(entry.getContentKind());
+ saveInt(entry.getEntryKind());
+ savePath(entry.getPath());
+ savePaths(entry.getInclusionPatterns());
+ savePaths(entry.getExclusionPatterns());
+ savePath(entry.getSourceAttachmentPath());
+ savePath(entry.getSourceAttachmentRootPath());
+ savePath(entry.getOutputLocation());
+ this.out.writeBoolean(entry.isExported());
+ saveAccessRules(entry.getAccessRules());
+ this.out.writeBoolean(entry.combineAccessRules());
+ saveAttributes(entry.getExtraAttributes());
+ }
+ }
+
+ private void saveContainers(IJavaProject project, Map containerMap)
+ throws IOException {
+ saveInt(containerMap.size());
+
+ for (Iterator i = containerMap.entrySet().iterator(); i.hasNext();) {
+ Entry entry = (Entry) i.next();
+ IPath path = (IPath) entry.getKey();
+ IClasspathContainer container = (IClasspathContainer) entry.getValue();
+ IClasspathEntry[] cpEntries = null;
+
+ if (container == null) {
+ // container has not been initialized yet, use previous
+ // session value
+ // (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=73969)
+ container = JavaModelManager.this.getPreviousSessionContainer(path, project);
+ }
+
+ if (container != null)
+ cpEntries = container.getClasspathEntries();
+
+ savePath(path);
+ saveClasspathEntries(cpEntries);
+ }
+ }
+
+ private void saveInt(int value) throws IOException {
+ this.out.writeInt(value);
+ }
+
+ private boolean saveNewId(Object key, HashtableOfObjectToInt map) throws IOException {
+ int id = map.get(key);
+
+ if (id == -1) {
+ int newId = map.size();
+
+ map.put(key, newId);
+
+ saveInt(newId);
+
+ return true;
+ } else {
+ saveInt(id);
+
+ return false;
+ }
+ }
+
+ private void savePath(IPath path) throws IOException {
+ if (path == null) {
+ this.out.writeBoolean(true);
+ } else {
+ this.out.writeBoolean(false);
+ saveString(path.toPortableString());
+ }
+ }
+
+ private void savePaths(IPath[] paths) throws IOException {
+ int count = paths == null ? 0 : paths.length;
+
+ saveInt(count);
+ for (int i = 0; i < count; ++i)
+ savePath(paths[i]);
+ }
+
+ private void saveProjects(IJavaProject[] projects) throws IOException,
+ JavaModelException {
+ int count = projects.length;
+
+ saveInt(count);
+
+ for (int i = 0; i < count; ++i) {
+ IJavaProject project = projects[i];
+
+ saveString(project.getElementName());
+
+ Map containerMap = (Map) JavaModelManager.this.containers.get(project);
+
+ if (containerMap == null) {
+ containerMap = Collections.EMPTY_MAP;
+ } else {
+ // clone while iterating
+ // (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=59638)
+ containerMap = new HashMap(containerMap);
+ }
+
+ saveContainers(project, containerMap);
+ }
+ }
+
+ private void saveString(String string) throws IOException {
+ if (saveNewId(string, this.stringIds))
+ this.out.writeUTF(string);
+ }
+
+ private void saveVariables(Map map) throws IOException {
+ saveInt(map.size());
+
+ for (Iterator i = map.entrySet().iterator(); i.hasNext();) {
+ Entry entry = (Entry) i.next();
+ String varName = (String) entry.getKey();
+ IPath varPath = (IPath) entry.getValue();
+
+ saveString(varName);
+ savePath(varPath);
+ }
+ }
+ }
+
+ private void traceVariableAndContainers(String action, long start) {
+
+ Long delta = new Long(System.currentTimeMillis() - start);
+ Long length = new Long(getVariableAndContainersFile().length());
+ String pattern = "{0} {1} bytes in variablesAndContainers.dat in {2}ms"; //$NON-NLS-1$
+ String message = MessageFormat.format(pattern, new Object[]{action, length, delta});
+
+ System.out.println(message);
+ }
+
/**
* @see ISaveParticipant
*/
public void saving(ISaveContext context) throws CoreException {
- // save variable and container values on snapshot/full save
- saveVariablesAndContainers();
+ long start = -1;
+ if (VERBOSE)
+ start = System.currentTimeMillis();
+
+ // save variable and container values on snapshot/full save
+ saveVariablesAndContainers(context);
+
+ if (VERBOSE)
+ traceVariableAndContainers("Saved", start); //$NON-NLS-1$
if (context.getKind() == ISaveContext.FULL_SAVE) {
// will need delta since this save (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=38658)
@@ -2329,18 +3580,16 @@
synchronized(this.perProjectInfos) {
values = new ArrayList(this.perProjectInfos.values());
}
- if (values != null) {
- Iterator iterator = values.iterator();
- while (iterator.hasNext()) {
- try {
- PerProjectInfo info = (PerProjectInfo) iterator.next();
- saveState(info, context);
- info.rememberExternalLibTimestamps();
- } catch (CoreException e) {
- if (vStats == null)
- vStats= new ArrayList();
- vStats.add(e.getStatus());
- }
+ Iterator iterator = values.iterator();
+ while (iterator.hasNext()) {
+ try {
+ PerProjectInfo info = (PerProjectInfo) iterator.next();
+ saveState(info, context);
+ info.rememberExternalLibTimestamps();
+ } catch (CoreException e) {
+ if (vStats == null)
+ vStats= new ArrayList();
+ vStats.add(e.getStatus());
}
}
if (vStats != null) {
@@ -2354,6 +3603,412 @@
}
/**
+ * Add a secondary type in temporary indexing cache for a project got from given path.
+ *
+ * Current secondary types cache is not modified as we want to wait that indexing
+ * was finished before taking new secondary types into account.
+ *
+ * Indexing cache is a specific entry in secondary types cache which key is
+ * {@link #INDEXED_SECONDARY_TYPES } and value a map with same structure than
+ * secondary types cache itself.
+ *
+ * @see #secondaryTypes(IJavaProject, boolean, IProgressMonitor)
+ */
+ public void secondaryTypeAdding(String path, char[] typeName, char[] packageName) {
+ if (VERBOSE) {
+ StringBuffer buffer = new StringBuffer("JavaModelManager.addSecondaryType("); //$NON-NLS-1$
+ buffer.append(path);
+ buffer.append(',');
+ buffer.append('[');
+ buffer.append(new String(packageName));
+ buffer.append('.');
+ buffer.append(new String(typeName));
+ buffer.append(']');
+ buffer.append(')');
+ Util.verbose(buffer.toString());
+ }
+ IWorkspaceRoot wRoot = ResourcesPlugin.getWorkspace().getRoot();
+ IResource resource = wRoot.findMember(path);
+ if (resource != null) {
+ if (org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(path) && resource.getType() == IResource.FILE) {
+ IProject project = resource.getProject();
+ try {
+ PerProjectInfo projectInfo = getPerProjectInfoCheckExistence(project);
+ // Get or create map to cache secondary types while indexing (can be not synchronized as indexing insure a non-concurrent usage)
+ HashMap indexedSecondaryTypes = null;
+ if (projectInfo.secondaryTypes == null) {
+ projectInfo.secondaryTypes = new Hashtable(3);
+ indexedSecondaryTypes = new HashMap(3);
+ projectInfo.secondaryTypes.put(INDEXED_SECONDARY_TYPES, indexedSecondaryTypes);
+ } else {
+ indexedSecondaryTypes = (HashMap) projectInfo.secondaryTypes.get(INDEXED_SECONDARY_TYPES);
+ if (indexedSecondaryTypes == null) {
+ indexedSecondaryTypes = new HashMap(3);
+ projectInfo.secondaryTypes.put(INDEXED_SECONDARY_TYPES, indexedSecondaryTypes);
+ }
+ }
+ // Store the secondary type in temporary cache (these are just handles => no problem to create it now...)
+ HashMap allTypes = (HashMap) indexedSecondaryTypes.get(resource);
+ if (allTypes == null) {
+ allTypes = new HashMap(3);
+ indexedSecondaryTypes.put(resource, allTypes);
+ }
+ ICompilationUnit unit = JavaModelManager.createCompilationUnitFrom((IFile)resource, null);
+ if (unit != null) {
+ String typeString = new String(typeName);
+ String packageString = new String(packageName);
+ HashMap packageTypes = (HashMap) allTypes.get(packageString);
+ if (packageTypes == null) {
+ packageTypes = new HashMap(3);
+ allTypes.put(packageString, packageTypes);
+ }
+ packageTypes.put(typeString, unit.getType(typeString));
+ }
+ if (VERBOSE) {
+ Util.verbose(" - indexing cache:"); //$NON-NLS-1$
+ Iterator entries = indexedSecondaryTypes.entrySet().iterator();
+ while (entries.hasNext()) {
+ Map.Entry entry = (Map.Entry) entries.next();
+ IFile file = (IFile) entry.getKey();
+ Util.verbose(" + "+file.getFullPath()+':'+ entry.getValue()); //$NON-NLS-1$
+ }
+ }
+ }
+ catch (JavaModelException jme) {
+ // do nothing
+ }
+ }
+ }
+ }
+
+ /**
+ * Get all secondary types for a project and store result in per project info cache.
+ *
+ * This cache is an Hashtable<String, HashMap<String, IType>>:
+ * - key: package name
+ * - value:
+ * + key: type name
+ * + value: java model handle for the secondary type
+ * Hashtable was used to protect callers from possible concurrent access.
+ *
+ * Note that this map may have a specific entry which key is {@link #INDEXED_SECONDARY_TYPES }
+ * and value is a map containing all secondary types created during indexing.
+ * When this key is in cache and indexing is finished, returned map is merged
+ * with the value of this special key. If indexing is not finished and caller does
+ * not wait for the end of indexing, returned map is the current secondary
+ * types cache content which may be invalid...
+ *
+ * @param project Project we want get secondary types from
+ * @return HashMap Table of secondary type names->path for given project
+ */
+ public Map secondaryTypes(IJavaProject project, boolean waitForIndexes, IProgressMonitor monitor) throws JavaModelException {
+ if (VERBOSE) {
+ StringBuffer buffer = new StringBuffer("JavaModelManager.secondaryTypes("); //$NON-NLS-1$
+ buffer.append(project.getElementName());
+ buffer.append(',');
+ buffer.append(waitForIndexes);
+ buffer.append(')');
+ Util.verbose(buffer.toString());
+ }
+
+ // Return cache if not empty and there's no new secondary types created during indexing
+ final PerProjectInfo projectInfo = getPerProjectInfoCheckExistence(project.getProject());
+ Map indexingSecondaryCache = projectInfo.secondaryTypes == null ? null : (Map) projectInfo.secondaryTypes.get(INDEXED_SECONDARY_TYPES);
+ if (projectInfo.secondaryTypes != null && indexingSecondaryCache == null) {
+ return projectInfo.secondaryTypes;
+ }
+
+ // Perform search request only if secondary types cache is not initialized yet (this will happen only once!)
+ if (projectInfo.secondaryTypes == null) {
+ return secondaryTypesSearching(project, waitForIndexes, monitor, projectInfo);
+ }
+
+ // New secondary types have been created while indexing secondary types cache
+ // => need to know whether the indexing is finished or not
+ boolean indexing = this.indexManager.awaitingJobsCount() > 0;
+ if (indexing) {
+ if (!waitForIndexes) {
+ // Indexing is running but caller cannot wait => return current cache
+ return projectInfo.secondaryTypes;
+ }
+
+ // Wait for the end of indexing or a cancel
+ while (this.indexManager.awaitingJobsCount() > 0) {
+ if (monitor != null && monitor.isCanceled()) {
+ return projectInfo.secondaryTypes;
+ }
+ try {
+ Thread.sleep(10);
+ } catch (InterruptedException e) {
+ return projectInfo.secondaryTypes;
+ }
+ }
+ }
+
+ // Indexing is finished => merge caches and return result
+ return secondaryTypesMerging(projectInfo.secondaryTypes);
+ }
+
+ /*
+ * Return secondary types cache merged with new secondary types created while indexing
+ * Note that merge result is directly stored in given parameter map.
+ */
+ private Hashtable secondaryTypesMerging(Hashtable secondaryTypes) {
+ if (VERBOSE) {
+ Util.verbose("JavaModelManager.getSecondaryTypesMerged()"); //$NON-NLS-1$
+ Util.verbose(" - current cache to merge:"); //$NON-NLS-1$
+ Iterator entries = secondaryTypes.entrySet().iterator();
+ while (entries.hasNext()) {
+ Map.Entry entry = (Map.Entry) entries.next();
+ String packName = (String) entry.getKey();
+ Util.verbose(" + "+packName+':'+ entry.getValue() ); //$NON-NLS-1$
+ }
+ }
+
+ // Return current cache if there's no indexing cache (double check, this should not happen)
+ HashMap indexedSecondaryTypes = (HashMap) secondaryTypes.remove(INDEXED_SECONDARY_TYPES);
+ if (indexedSecondaryTypes == null) {
+ return secondaryTypes;
+ }
+
+ // Merge indexing cache in secondary types one
+ Iterator entries = indexedSecondaryTypes.entrySet().iterator();
+ while (entries.hasNext()) {
+ Map.Entry entry = (Map.Entry) entries.next();
+ IFile file = (IFile) entry.getKey();
+
+ // Remove all secondary types of indexed file from cache
+ secondaryTypesRemoving(secondaryTypes, file);
+
+ // Add all indexing file secondary types in given secondary types cache
+ HashMap fileSecondaryTypes = (HashMap) entry.getValue();
+ Iterator entries2 = fileSecondaryTypes.entrySet().iterator();
+ while (entries2.hasNext()) {
+ Map.Entry entry2 = (Map.Entry) entries2.next();
+ String packageName = (String) entry2.getKey();
+ HashMap cachedTypes = (HashMap) secondaryTypes.get(packageName);
+ if (cachedTypes == null) {
+ secondaryTypes.put(packageName, entry2.getValue());
+ } else {
+ HashMap types = (HashMap) entry2.getValue();
+ Iterator entries3 = types.entrySet().iterator();
+ while (entries3.hasNext()) {
+ Map.Entry entry3 = (Map.Entry) entries3.next();
+ String typeName = (String) entry3.getKey();
+ cachedTypes.put(typeName, entry3.getValue());
+ }
+ }
+ }
+ }
+ if (VERBOSE) {
+ Util.verbose(" - secondary types cache merged:"); //$NON-NLS-1$
+ entries = secondaryTypes.entrySet().iterator();
+ while (entries.hasNext()) {
+ Map.Entry entry = (Map.Entry) entries.next();
+ String packName = (String) entry.getKey();
+ Util.verbose(" + "+packName+':'+ entry.getValue()); //$NON-NLS-1$
+ }
+ }
+ return secondaryTypes;
+ }
+
+ /*
+ * Perform search request to get all secondary types of a given project.
+ * If not waiting for indexes and indexing is running, will return types found in current built indexes...
+ */
+ private Map secondaryTypesSearching(IJavaProject project, boolean waitForIndexes, IProgressMonitor monitor, final PerProjectInfo projectInfo) throws JavaModelException {
+ if (VERBOSE || BasicSearchEngine.VERBOSE) {
+ StringBuffer buffer = new StringBuffer("JavaModelManager.secondaryTypesSearch("); //$NON-NLS-1$
+ buffer.append(project.getElementName());
+ buffer.append(',');
+ buffer.append(waitForIndexes);
+ buffer.append(')');
+ Util.verbose(buffer.toString());
+ }
+
+ final Hashtable secondaryTypes = new Hashtable(3);
+ IRestrictedAccessTypeRequestor nameRequestor = new IRestrictedAccessTypeRequestor() {
+ public void acceptType(int modifiers, char[] packageName, char[] simpleTypeName, char[][] enclosingTypeNames, String path, AccessRestriction access) {
+ String key = packageName==null ? "" : new String(packageName); //$NON-NLS-1$
+ HashMap types = (HashMap) secondaryTypes.get(key);
+ if (types == null) types = new HashMap(3);
+ types.put(new String(simpleTypeName), path);
+ secondaryTypes.put(key, types);
+ }
+ };
+
+ // Build scope using prereq projects but only source folders
+ IPackageFragmentRoot[] allRoots = project.getAllPackageFragmentRoots();
+ int length = allRoots.length, size = 0;
+ IPackageFragmentRoot[] allSourceFolders = new IPackageFragmentRoot[length];
+ for (int i=0; i<length; i++) {
+ if (allRoots[i].getKind() == IPackageFragmentRoot.K_SOURCE) {
+ allSourceFolders[size++] = allRoots[i];
+ }
+ }
+ if (size < length) {
+ System.arraycopy(allSourceFolders, 0, allSourceFolders = new IPackageFragmentRoot[size], 0, size);
+ }
+
+ // Search all secondary types on scope
+ new BasicSearchEngine().searchAllSecondaryTypeNames(allSourceFolders, nameRequestor, waitForIndexes, monitor);
+
+ // Build types from paths
+ Iterator packages = secondaryTypes.values().iterator();
+ while (packages.hasNext()) {
+ HashMap types = (HashMap) packages.next();
+ Iterator names = types.entrySet().iterator();
+ while (names.hasNext()) {
+ Map.Entry entry = (Map.Entry) names.next();
+ String typeName = (String) entry.getKey();
+ String path = (String) entry.getValue();
+ if (org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(path)) {
+ IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(path));
+ ICompilationUnit unit = JavaModelManager.createCompilationUnitFrom(file, null);
+ IType type = unit.getType(typeName);
+ types.put(typeName, type); // replace stored path with type itself
+ }
+ }
+ }
+
+ // Store result in per project info cache if still null or there's still an indexing cache (may have been set by another thread...)
+ if (projectInfo.secondaryTypes == null || projectInfo.secondaryTypes.get(INDEXED_SECONDARY_TYPES) != null) {
+ projectInfo.secondaryTypes = secondaryTypes;
+ if (VERBOSE || BasicSearchEngine.VERBOSE) {
+ System.out.print(Thread.currentThread() + " -> secondary paths stored in cache: "); //$NON-NLS-1$
+ System.out.println();
+ Iterator entries = secondaryTypes.entrySet().iterator();
+ while (entries.hasNext()) {
+ Map.Entry entry = (Map.Entry) entries.next();
+ String qualifiedName = (String) entry.getKey();
+ Util.verbose(" - "+qualifiedName+'-'+ entry.getValue()); //$NON-NLS-1$
+ }
+ }
+ }
+ return projectInfo.secondaryTypes;
+ }
+
+ /**
+ * Remove from secondary types cache all types belonging to a given file.
+ * Clean secondary types cache built while indexing if requested.
+ *
+ * Project's secondary types cache is found using file location.
+ *
+ * @param file File to remove
+ */
+ public void secondaryTypesRemoving(IFile file, boolean cleanIndexCache) {
+ if (VERBOSE) {
+ StringBuffer buffer = new StringBuffer("JavaModelManager.removeFromSecondaryTypesCache("); //$NON-NLS-1$
+ buffer.append(file.getName());
+ buffer.append(')');
+ Util.verbose(buffer.toString());
+ }
+ if (file != null) {
+ PerProjectInfo projectInfo = getPerProjectInfo(file.getProject(), false);
+ if (projectInfo != null && projectInfo.secondaryTypes != null) {
+ if (VERBOSE) {
+ Util.verbose("-> remove file from cache of project: "+file.getProject().getName()); //$NON-NLS-1$
+ }
+
+ // Clean current cache
+ secondaryTypesRemoving(projectInfo.secondaryTypes, file);
+
+ // Clean indexing cache if necessary
+ if (!cleanIndexCache) return;
+ HashMap indexingCache = (HashMap) projectInfo.secondaryTypes.get(INDEXED_SECONDARY_TYPES);
+ if (indexingCache != null) {
+ Set keys = indexingCache.keySet();
+ int filesSize = keys.size(), filesCount = 0;
+ IFile[] removed = null;
+ Iterator cachedFiles = keys.iterator();
+ while (cachedFiles.hasNext()) {
+ IFile cachedFile = (IFile) cachedFiles.next();
+ if (file.equals(cachedFile)) {
+ if (removed == null) removed = new IFile[filesSize];
+ filesSize--;
+ removed[filesCount++] = cachedFile;
+ }
+ }
+ if (removed != null) {
+ for (int i=0; i<filesCount; i++) {
+ indexingCache.remove(removed[i]);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ * Remove from a given cache map all secondary types belonging to a given file.
+ * Note that there can have several secondary types per file...
+ */
+ private void secondaryTypesRemoving(Hashtable secondaryTypesMap, IFile file) {
+ if (VERBOSE) {
+ StringBuffer buffer = new StringBuffer("JavaModelManager.removeSecondaryTypesFromMap("); //$NON-NLS-1$
+ Iterator entries = secondaryTypesMap.entrySet().iterator();
+ while (entries.hasNext()) {
+ Map.Entry entry = (Map.Entry) entries.next();
+ String qualifiedName = (String) entry.getKey();
+ buffer.append(qualifiedName+':'+ entry.getValue());
+ }
+ buffer.append(',');
+ buffer.append(file.getFullPath());
+ buffer.append(')');
+ Util.verbose(buffer.toString());
+ }
+ Set packageEntries = secondaryTypesMap.entrySet();
+ int packagesSize = packageEntries.size(), removedPackagesCount = 0;
+ String[] removedPackages = null;
+ Iterator packages = packageEntries.iterator();
+ while (packages.hasNext()) {
+ Map.Entry entry = (Map.Entry) packages.next();
+ String packName = (String) entry.getKey();
+ if (packName != INDEXED_SECONDARY_TYPES) { // skip indexing cache entry if present (!= is intentional)
+ HashMap types = (HashMap) entry.getValue();
+ Set nameEntries = types.entrySet();
+ int namesSize = nameEntries.size(), removedNamesCount = 0;
+ String[] removedNames = null;
+ Iterator names = nameEntries.iterator();
+ while (names.hasNext()) {
+ Map.Entry entry2 = (Map.Entry) names.next();
+ String typeName = (String) entry2.getKey();
+ IType type = (IType) entry2.getValue();
+ if (file.equals(type.getResource())) {
+ if (removedNames == null) removedNames = new String[namesSize];
+ namesSize--;
+ removedNames[removedNamesCount++] = typeName;
+ }
+ }
+ if (removedNames != null) {
+ for (int i=0; i<removedNamesCount; i++) {
+ types.remove(removedNames[i]);
+ }
+ }
+ if (types.size() == 0) {
+ if (removedPackages == null) removedPackages = new String[packagesSize];
+ packagesSize--;
+ removedPackages[removedPackagesCount++] = packName;
+ }
+ }
+ }
+ if (removedPackages != null) {
+ for (int i=0; i<removedPackagesCount; i++) {
+ secondaryTypesMap.remove(removedPackages[i]);
+ }
+ }
+ if (VERBOSE) {
+ Util.verbose(" - new secondary types map:"); //$NON-NLS-1$
+ Iterator entries = secondaryTypesMap.entrySet().iterator();
+ while (entries.hasNext()) {
+ Map.Entry entry = (Map.Entry) entries.next();
+ String qualifiedName = (String) entry.getKey();
+ Util.verbose(" + "+qualifiedName+':'+ entry.getValue()); //$NON-NLS-1$
+ }
+ }
+ }
+
+ /**
* Record the order in which to build the java projects (batch build). This order is based
* on the projects classpath settings.
*/
@@ -2466,6 +4121,9 @@
public void startup() throws CoreException {
try {
configurePluginDebugOptions();
+
+ // initialize Java model cache
+ this.cache = new JavaModelCache();
// request state folder creation (workaround 19885)
JavaCore.getPlugin().getStateLocation();
@@ -2480,13 +4138,22 @@
}
};
JavaCore.getPlugin().getPluginPreferences().addPropertyChangeListener(propertyListener);
+
+ // Listen to content-type changes
+ Platform.getContentTypeManager().addContentTypeChangeListener(this);
// retrieve variable values
- loadVariablesAndContainers();
+ long start = -1;
+ if (VERBOSE)
+ start = System.currentTimeMillis();
+ loadVariablesAndContainers();
+ if (VERBOSE)
+ traceVariableAndContainers("Loaded", start); //$NON-NLS-1$
final IWorkspace workspace = ResourcesPlugin.getWorkspace();
workspace.addResourceChangeListener(
this.deltaState,
+ /* update spec in JavaCore#addPreProcessingResourceChangedListener(...) if adding more event types */
IResourceChangeEvent.PRE_BUILD
| IResourceChangeEvent.POST_BUILD
| IResourceChangeEvent.POST_CHANGE
@@ -2544,6 +4211,13 @@
IWorkspace workspace = ResourcesPlugin.getWorkspace();
workspace.removeResourceChangeListener(this.deltaState);
workspace.removeSaveParticipant(javaCore);
+
+ // Stop listening to content-type changes
+ Platform.getContentTypeManager().removeContentTypeChangeListener(this);
+
+ // Stop listening to user library changes
+ if (this.userLibraryManager != null)
+ getInstancePreferences().removePreferenceChangeListener(this.userLibraryManager);
if (this.indexManager != null){ // no more indexing
this.indexManager.shutdown();
@@ -2551,14 +4225,14 @@
// wait for the initialization job to finish
try {
- Platform.getJobManager().join(JavaCore.PLUGIN_ID, null);
+ Job.getJobManager().join(JavaCore.PLUGIN_ID, null);
} catch (InterruptedException e) {
// ignore
}
// Note: no need to close the Java model as this just removes Java element infos from the Java model cache
}
-
+
public synchronized IPath variableGet(String variableName){
// check initialization in progress first
HashSet initializations = variableInitializationInProgress();
@@ -2568,164 +4242,13 @@
return (IPath)this.variables.get(variableName);
}
- /*
- * Internal updating of a variable values (null path meaning removal), allowing to change multiple variable values at once.
- */
- public void updateVariableValues(
- String[] variableNames,
- IPath[] variablePaths,
- IProgressMonitor monitor) throws JavaModelException {
-
- if (monitor != null && monitor.isCanceled()) return;
-
- if (CP_RESOLVE_VERBOSE){
- Util.verbose(
- "CPVariable SET - setting variables\n" + //$NON-NLS-1$
- " variables: " + org.eclipse.jdt.internal.compiler.util.Util.toString(variableNames) + '\n' +//$NON-NLS-1$
- " values: " + org.eclipse.jdt.internal.compiler.util.Util.toString(variablePaths)); //$NON-NLS-1$
- }
-
- if (variablePutIfInitializingWithSameValue(variableNames, variablePaths))
- return;
-
- int varLength = variableNames.length;
-
- // gather classpath information for updating
- final HashMap affectedProjectClasspaths = new HashMap(5);
- IJavaModel model = getJavaModel();
-
- // filter out unmodified variables
- int discardCount = 0;
- for (int i = 0; i < varLength; i++){
- String variableName = variableNames[i];
- IPath oldPath = this.variableGet(variableName); // if reentering will provide previous session value
- if (oldPath == VARIABLE_INITIALIZATION_IN_PROGRESS){
-// IPath previousPath = (IPath)this.previousSessionVariables.get(variableName);
-// if (previousPath != null){
-// if (CP_RESOLVE_VERBOSE){
-// Util.verbose(
-// "CPVariable INIT - reentering access to variable during its initialization, will see previous value\n" + //$NON-NLS-1$
-// " variable: "+ variableName + '\n' + //$NON-NLS-1$
-// " previous value: " + previousPath); //$NON-NLS-1$
-// }
-// this.variablePut(variableName, previousPath); // replace value so reentering calls are seeing old value
-// }
- oldPath = null; //33695 - cannot filter out restored variable, must update affected project to reset cached CP
- }
- if (oldPath != null && oldPath.equals(variablePaths[i])){
- variableNames[i] = null;
- discardCount++;
- }
- }
- if (discardCount > 0){
- if (discardCount == varLength) return;
- int changedLength = varLength - discardCount;
- String[] changedVariableNames = new String[changedLength];
- IPath[] changedVariablePaths = new IPath[changedLength];
- for (int i = 0, index = 0; i < varLength; i++){
- if (variableNames[i] != null){
- changedVariableNames[index] = variableNames[i];
- changedVariablePaths[index] = variablePaths[i];
- index++;
- }
- }
- variableNames = changedVariableNames;
- variablePaths = changedVariablePaths;
- varLength = changedLength;
- }
-
- if (monitor != null && monitor.isCanceled()) return;
-
- if (model != null) {
- IJavaProject[] projects = model.getJavaProjects();
- nextProject : for (int i = 0, projectLength = projects.length; i < projectLength; i++){
- JavaProject project = (JavaProject) projects[i];
-
- // check to see if any of the modified variables is present on the classpath
- IClasspathEntry[] classpath = project.getRawClasspath();
- for (int j = 0, cpLength = classpath.length; j < cpLength; j++){
-
- IClasspathEntry entry = classpath[j];
- for (int k = 0; k < varLength; k++){
-
- String variableName = variableNames[k];
- if (entry.getEntryKind() == IClasspathEntry.CPE_VARIABLE){
-
- if (variableName.equals(entry.getPath().segment(0))){
- affectedProjectClasspaths.put(project, project.getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/));
- continue nextProject;
- }
- IPath sourcePath, sourceRootPath;
- if (((sourcePath = entry.getSourceAttachmentPath()) != null && variableName.equals(sourcePath.segment(0)))
- || ((sourceRootPath = entry.getSourceAttachmentRootPath()) != null && variableName.equals(sourceRootPath.segment(0)))) {
-
- affectedProjectClasspaths.put(project, project.getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/));
- continue nextProject;
- }
- }
- }
- }
- }
- }
- // update variables
- for (int i = 0; i < varLength; i++){
- this.variablePut(variableNames[i], variablePaths[i]);
- }
- final String[] dbgVariableNames = variableNames;
-
- // update affected project classpaths
- if (!affectedProjectClasspaths.isEmpty()) {
- try {
- final boolean canChangeResources = !ResourcesPlugin.getWorkspace().isTreeLocked();
- JavaCore.run(
- new IWorkspaceRunnable() {
- public void run(IProgressMonitor progressMonitor) throws CoreException {
- // propagate classpath change
- Iterator projectsToUpdate = affectedProjectClasspaths.keySet().iterator();
- while (projectsToUpdate.hasNext()) {
-
- if (progressMonitor != null && progressMonitor.isCanceled()) return;
-
- JavaProject affectedProject = (JavaProject) projectsToUpdate.next();
-
- if (CP_RESOLVE_VERBOSE){
- Util.verbose(
- "CPVariable SET - updating affected project due to setting variables\n" + //$NON-NLS-1$
- " project: " + affectedProject.getElementName() + '\n' + //$NON-NLS-1$
- " variables: " + org.eclipse.jdt.internal.compiler.util.Util.toString(dbgVariableNames)); //$NON-NLS-1$
- }
-
- affectedProject
- .setRawClasspath(
- affectedProject.getRawClasspath(),
- SetClasspathOperation.DO_NOT_SET_OUTPUT,
- null, // don't call beginTask on the monitor (see http://bugs.eclipse.org/bugs/show_bug.cgi?id=3717)
- canChangeResources,
- (IClasspathEntry[]) affectedProjectClasspaths.get(affectedProject),
- false, // updating - no need for early validation
- false); // updating - no need to save
- }
- }
- },
- null/*no need to lock anything*/,
- monitor);
- } catch (CoreException e) {
- if (CP_RESOLVE_VERBOSE){
- Util.verbose(
- "CPVariable SET - FAILED DUE TO EXCEPTION\n" + //$NON-NLS-1$
- " variables: " + org.eclipse.jdt.internal.compiler.util.Util.toString(dbgVariableNames), //$NON-NLS-1$
- System.err);
- e.printStackTrace();
- }
- if (e instanceof JavaModelException) {
- throw (JavaModelException)e;
- } else {
- throw new JavaModelException(e);
- }
- }
- }
+ private synchronized IPath variableGetDefaultToPreviousSession(String variableName){
+ IPath variablePath = (IPath)this.variables.get(variableName);
+ if (variablePath == null)
+ return getPreviousSessionVariable(variableName);
+ return variablePath;
}
-
+
/*
* Returns the set of variable names that are being initialized in the current thread.
*/
@@ -2748,7 +4271,7 @@
}
return result;
}
-
+
public synchronized void variablePut(String variableName, IPath variablePath){
// set/unset the initialization in progress
@@ -2763,26 +4286,32 @@
// update cache - do not only rely on listener refresh
if (variablePath == null) {
- this.variables.remove(variableName);
+ // if path is null, record that the variable was removed to avoid asking the initializer to initialize it again
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=112609
+ this.variables.put(variableName, CP_ENTRY_IGNORE_PATH);
} else {
this.variables.put(variableName, variablePath);
}
// discard obsoleted information about previous session
this.previousSessionVariables.remove(variableName);
}
-
+ }
+
+ public void variablePreferencesPut(String variableName, IPath variablePath) {
String variableKey = CP_VARIABLE_PREFERENCES_PREFIX+variableName;
- if (variablePath == null)
+ if (variablePath == null) {
+ this.variablesWithInitializer.remove(variableName);
getInstancePreferences().remove(variableKey);
- else
+ } else {
getInstancePreferences().put(variableKey, variablePath.toString());
+ }
try {
getInstancePreferences().flush();
} catch (BackingStoreException e) {
// ignore exception
}
}
-
+
/*
* Optimize startup case where 1 variable is initialized at a time with the same value as on shutdown.
*/
@@ -2790,7 +4319,7 @@
if (variableNames.length != 1)
return false;
String variableName = variableNames[0];
- IPath oldPath = getPreviousSessionVariable(variableName);
+ IPath oldPath = variableGetDefaultToPreviousSession(variableName);
if (oldPath == null)
return false;
IPath newPath = variablePaths[0];
@@ -2799,4 +4328,13 @@
variablePut(variableName, newPath);
return true;
}
+
+ public void contentTypeChanged(ContentTypeChangeEvent event) {
+ Util.resetJavaLikeExtensions();
+
+ }
+
+ public synchronized String cacheToString(String prefix) {
+ return this.cache.toStringFillingRation(prefix);
+ }
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelOperation.java
index 7a58ae6..b029e4c 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelOperation.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -61,8 +61,8 @@
protected HashMap attributes;
public static final String HAS_MODIFIED_RESOURCE_ATTR = "hasModifiedResource"; //$NON-NLS-1$
- public static final String TRUE = "true"; //$NON-NLS-1$
- //public static final String FALSE = "false"; //$NON-NLS-1$
+ public static final String TRUE = JavaModelManager.TRUE;
+ //public static final String FALSE = "false";
/**
* The elements this operation operates on,
@@ -93,7 +93,7 @@
/**
* The progress monitor passed into this operation
*/
- protected IProgressMonitor progressMonitor= null;
+ public IProgressMonitor progressMonitor= null;
/**
* A flag indicating whether this operation is nested.
*/
@@ -181,6 +181,12 @@
JavaElementDelta child = (JavaElementDelta)children[i];
previousDelta.insertDeltaTree(child.getElement(), child);
}
+ // note that the last delta's AST always takes precedence over the existing delta's AST
+ // since it is the result of the last reconcile operation
+ if ((delta.getFlags() & IJavaElementDelta.F_AST_AFFECTED) != 0) {
+ previousDelta.changedAST(delta.getCompilationUnitAST());
+ }
+
} else {
reconcileDeltas.put(workingCopy, delta);
}
@@ -241,7 +247,7 @@
IWorkspace workspace = resources[0].getWorkspace();
try {
workspace.copy(resources, destinationPath, false, subProgressMonitor);
- this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
+ setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
} catch (CoreException e) {
throw new JavaModelException(e);
}
@@ -256,7 +262,7 @@
contents,
forceFlag ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY,
getSubProgressMonitor(1));
- this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
+ setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
} catch (CoreException e) {
throw new JavaModelException(e);
}
@@ -272,7 +278,7 @@
forceFlag ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY,
true, // local
getSubProgressMonitor(1));
- this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
+ setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
} catch (CoreException e) {
throw new JavaModelException(e);
}
@@ -292,7 +298,7 @@
resource.delete(
forceFlag ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY,
getSubProgressMonitor(1));
- this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
+ setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
while (resource instanceof IFolder) {
// deleting a package: delete the parent if it is empty (eg. deleting x.y where folder x doesn't have resources but y)
// without deleting the package fragment root
@@ -301,7 +307,7 @@
resource.delete(
forceFlag ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY,
getSubProgressMonitor(1));
- this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
+ setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
}
}
} catch (CoreException e) {
@@ -314,7 +320,7 @@
protected void deleteResource(IResource resource,int flags) throws JavaModelException {
try {
resource.delete(flags, getSubProgressMonitor(1));
- this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
+ setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
} catch (CoreException e) {
throw new JavaModelException(e);
}
@@ -331,7 +337,7 @@
resources,
forceFlag ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY,
subProgressMonitor);
- this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
+ setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
} catch (CoreException e) {
throw new JavaModelException(e);
}
@@ -391,8 +397,8 @@
* Returns the attribute registered at the given key with the top level operation.
* Returns null if no such attribute is found.
*/
- protected Object getAttribute(Object key) {
- ArrayList stack = this.getCurrentOperationStack();
+ protected static Object getAttribute(Object key) {
+ ArrayList stack = getCurrentOperationStack();
if (stack.size() == 0) return null;
JavaModelOperation topLevelOp = (JavaModelOperation)stack.get(0);
if (topLevelOp.attributes == null) {
@@ -414,7 +420,7 @@
* Returns the stack of operations running in the current thread.
* Returns an empty stack if no operations are currently running in this thread.
*/
- protected ArrayList getCurrentOperationStack() {
+ protected static ArrayList getCurrentOperationStack() {
ArrayList stack = (ArrayList)operationStacks.get();
if (stack == null) {
stack = new ArrayList();
@@ -452,11 +458,7 @@
* Returns the Java Model this operation is operating in.
*/
public IJavaModel getJavaModel() {
- if (elementsToProcess == null || elementsToProcess.length == 0) {
- return getParentElement().getJavaModel();
- } else {
- return elementsToProcess[0].getJavaModel();
- }
+ return JavaModelManager.getJavaModelManager().getJavaModel();
}
protected IPath[] getNestedFolders(IPackageFragmentRoot root) throws JavaModelException {
IPath rootPath = root.getPath();
@@ -522,7 +524,7 @@
* Returns false if this operation has not been executed yet.
*/
public boolean hasModifiedResource() {
- return !this.isReadOnly() && this.getAttribute(HAS_MODIFIED_RESOURCE_ATTR) == TRUE;
+ return !this.isReadOnly() && getAttribute(HAS_MODIFIED_RESOURCE_ATTR) == TRUE;
}
public void internalWorked(double work) {
if (progressMonitor != null) {
@@ -551,7 +553,7 @@
protected boolean isTopLevelOperation() {
ArrayList stack;
return
- (stack = this.getCurrentOperationStack()).size() > 0
+ (stack = getCurrentOperationStack()).size() > 0
&& stack.get(0) == this;
}
/*
@@ -578,7 +580,7 @@
IWorkspace workspace = resources[0].getWorkspace();
try {
workspace.move(resources, destinationPath, false, subProgressMonitor);
- this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
+ setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
} catch (CoreException e) {
throw new JavaModelException(e);
}
@@ -743,10 +745,11 @@
switch (element.getElementType()) {
case IJavaElement.PACKAGE_FRAGMENT_ROOT:
case IJavaElement.PACKAGE_FRAGMENT:
- ((JavaProject) element.getJavaProject()).resetCaches();
+ deltaProcessor.projectCachesToReset.add(element.getJavaProject());
break;
}
}
+ deltaProcessor.resetProjectCaches();
// fire only iff:
// - the operation is a top level operation
@@ -807,8 +810,11 @@
/*
* Registers the given attribute at the given key with the top level operation.
*/
- protected void setAttribute(Object key, Object attribute) {
- JavaModelOperation topLevelOp = (JavaModelOperation)this.getCurrentOperationStack().get(0);
+ protected static void setAttribute(Object key, Object attribute) {
+ ArrayList operationStack = getCurrentOperationStack();
+ if (operationStack.size() == 0)
+ return;
+ JavaModelOperation topLevelOp = (JavaModelOperation) operationStack.get(0);
if (topLevelOp.attributes == null) {
topLevelOp.attributes = new HashMap();
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelStatus.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelStatus.java
index 5f2895b..e84d486 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelStatus.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelStatus.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -126,7 +126,7 @@
this(code, new IJavaElement[]{element});
this.string = string;
}
-
+
/**
* Constructs an Java model status with the given corresponding
* element and path
@@ -134,7 +134,8 @@
public JavaModelStatus(int code, IJavaElement element, IPath path) {
this(code, new IJavaElement[]{element});
this.path = path;
- }
+ }
+
/**
* Constructs an Java model status with the given corresponding
* element, path and string
@@ -144,7 +145,19 @@
this.path = path;
this.string = string;
}
+
/**
+ * Constructs an Java model status with the given corresponding
+ * element and path
+ */
+ public JavaModelStatus(int severity, int code, IJavaElement element, IPath path, String msg) {
+ super(severity, JavaCore.PLUGIN_ID, code, "JavaModelStatus", null); //$NON-NLS-1$
+ this.elements= new IJavaElement[]{element};
+ this.path = path;
+ this.string = msg;
+ }
+
+ /**
* Constructs an Java model status with no corresponding elements.
*/
public JavaModelStatus(CoreException coreException) {
@@ -326,45 +339,64 @@
if (description == null) description = path.makeRelative().toString();
return Messages.bind(Messages.classpath_invalidContainer, new String[] {description, javaProject.getElementName()});
- case CP_VARIABLE_PATH_UNBOUND:
- javaProject = (IJavaProject)elements[0];
- return Messages.bind(Messages.classpath_unboundVariablePath, new String[] {path.makeRelative().toString(), javaProject.getElementName()});
-
- case CLASSPATH_CYCLE:
- javaProject = (IJavaProject)elements[0];
- return Messages.bind(Messages.classpath_cycle, javaProject.getElementName());
-
- case DISABLED_CP_EXCLUSION_PATTERNS:
- javaProject = (IJavaProject)elements[0];
- String projectName = javaProject.getElementName();
- IPath newPath = path;
- if (path.segment(0).toString().equals(projectName)) {
- newPath = path.removeFirstSegments(1);
- }
- return Messages.bind(Messages.classpath_disabledInclusionExclusionPatterns, new String[] {newPath.makeRelative().toString(), projectName});
-
- case DISABLED_CP_MULTIPLE_OUTPUT_LOCATIONS:
- javaProject = (IJavaProject)elements[0];
- projectName = javaProject.getElementName();
- newPath = path;
- if (path.segment(0).toString().equals(projectName)) {
- newPath = path.removeFirstSegments(1);
- }
- return Messages.bind(Messages.classpath_disabledMultipleOutputLocations, new String[] {newPath.makeRelative().toString(), projectName});
-
- case INCOMPATIBLE_JDK_LEVEL:
+ case CP_VARIABLE_PATH_UNBOUND:
javaProject = (IJavaProject)elements[0];
- return Messages.bind(Messages.classpath_incompatibleLibraryJDKLevel, new String[]{
- javaProject.getElementName(),
- javaProject.getOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, true),
- path.makeRelative().toString(),
- string,
- });
+ return Messages.bind(Messages.classpath_unboundVariablePath, new String[] {path.makeRelative().toString(), javaProject.getElementName()});
+
+ case CLASSPATH_CYCLE:
+ javaProject = (IJavaProject)elements[0];
+ return Messages.bind(Messages.classpath_cycle, javaProject.getElementName());
+
+ case DISABLED_CP_EXCLUSION_PATTERNS:
+ javaProject = (IJavaProject)elements[0];
+ String projectName = javaProject.getElementName();
+ IPath newPath = path;
+ if (path.segment(0).toString().equals(projectName)) {
+ newPath = path.removeFirstSegments(1);
+ }
+ return Messages.bind(Messages.classpath_disabledInclusionExclusionPatterns, new String[] {newPath.makeRelative().toString(), projectName});
+
+ case DISABLED_CP_MULTIPLE_OUTPUT_LOCATIONS:
+ javaProject = (IJavaProject)elements[0];
+ projectName = javaProject.getElementName();
+ newPath = path;
+ if (path.segment(0).toString().equals(projectName)) {
+ newPath = path.removeFirstSegments(1);
+ }
+ return Messages.bind(Messages.classpath_disabledMultipleOutputLocations, new String[] {newPath.makeRelative().toString(), projectName});
+
+ case INCOMPATIBLE_JDK_LEVEL:
+ javaProject = (IJavaProject)elements[0];
+ return Messages.bind(Messages.classpath_incompatibleLibraryJDKLevel, new String[]{
+ javaProject.getElementName(),
+ javaProject.getOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, true),
+ path.makeRelative().toString(),
+ string,
+ });
+
+ case CANNOT_RETRIEVE_ATTACHED_JAVADOC :
+ if (elements != null && elements.length == 1) {
+ if (this.string != null) {
+ return Messages.bind(Messages.status_cannot_retrieve_attached_javadoc, ((JavaElement)elements[0]).toStringWithAncestors(), this.string);
+ }
+ return Messages.bind(Messages.status_cannot_retrieve_attached_javadoc, ((JavaElement)elements[0]).toStringWithAncestors(), ""); //$NON-NLS-1$
+ }
+ if (this.string != null) {
+ return Messages.bind(Messages.status_cannot_retrieve_attached_javadoc, this.string, "");//$NON-NLS-1$
+ }
+ break;
+
+ case UNKNOWN_JAVADOC_FORMAT :
+ return Messages.bind(Messages.status_unknown_javadoc_format, ((JavaElement)elements[0]).toStringWithAncestors());
+
+ case DEPRECATED_VARIABLE :
+ javaProject = (IJavaProject)elements[0];
+ return Messages.bind(Messages.classpath_deprecated_variable, new String[] {path.segment(0).toString(), javaProject.getElementName(), this.string});
}
if (string != null) {
return string;
} else {
- return ""; // //$NON-NLS-1$
+ return ""; //$NON-NLS-1$
}
} else {
String message = exception.getMessage();
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java
index a5ea949..a0c7dfc 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -11,12 +11,14 @@
package org.eclipse.jdt.internal.core;
import java.io.*;
+import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
+
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
@@ -32,9 +34,11 @@
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ProjectScope;
import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.AssertionFailedException;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Preferences;
import org.eclipse.core.runtime.QualifiedName;
@@ -56,10 +60,14 @@
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.WorkingCopyOwner;
+import org.eclipse.jdt.core.compiler.CategorizedProblem;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.eval.IEvaluationContext;
import org.eclipse.jdt.internal.compiler.util.ObjectVector;
import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
+import org.eclipse.jdt.internal.core.JavaModelManager.PerProjectInfo;
+import org.eclipse.jdt.internal.core.JavaProjectElementInfo.ProjectCache;
+import org.eclipse.jdt.internal.core.builder.JavaBuilder;
import org.eclipse.jdt.internal.core.eval.EvaluationContextWrapper;
import org.eclipse.jdt.internal.core.util.MementoTokenizer;
import org.eclipse.jdt.internal.core.util.Messages;
@@ -112,16 +120,23 @@
/**
* An empty array of strings indicating that a project doesn't have any prerequesite projects.
*/
- protected static final String[] NO_PREREQUISITES = new String[0];
+ protected static final String[] NO_PREREQUISITES = CharOperation.NO_STRINGS;
/**
* Name of file containing custom project preferences
- * @deprecated WARNING Visibility will be reduce to private before M9
- * If you use this variable, change your implementation to avoid future compilation error...
* @see <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=59258">bug 59258</a>
- * TODO (frederic) set visibility from public to private
*/
- public static final String PREF_FILENAME = ".jprefs"; //$NON-NLS-1$
+ private static final String PREF_FILENAME = ".jprefs"; //$NON-NLS-1$
+
+ /**
+ * Name of directory containing preferences file
+ */
+ public static final String DEFAULT_PREFERENCES_DIRNAME = ".settings"; //$NON-NLS-1$
+
+ /**
+ * Extension for file containing custom project preferences
+ */
+ public static final String JAVA_CORE_PREFS_FILE = JavaCore.PLUGIN_ID+".prefs"; //$NON-NLS-1$
/*
* Value of project's resolved classpath while it is being resolved
@@ -134,6 +149,66 @@
protected IProject project;
/**
+ * Constructor needed for <code>IProject.getNature()</code> and <code>IProject.addNature()</code>.
+ *
+ * @see #setProject(IProject)
+ */
+ public JavaProject() {
+ super(null);
+ }
+
+ public JavaProject(IProject project, JavaElement parent) {
+ super(parent);
+ this.project = project;
+ }
+
+ public static boolean areClasspathsEqual(
+ IClasspathEntry[] firstClasspath, IClasspathEntry[] secondClasspath,
+ IPath firstOutputLocation, IPath secondOutputLocation) {
+ int length = firstClasspath.length;
+ if (length != secondClasspath.length) return false;
+ for (int i = 0; i < length; i++) {
+ if (!firstClasspath[i].equals(secondClasspath[i]))
+ return false;
+ }
+ if (firstOutputLocation == null)
+ return secondOutputLocation == null;
+ return firstOutputLocation.equals(secondOutputLocation);
+ }
+
+ /**
+ * Compare current classpath with given one to see if any different.
+ * Note that the argument classpath contains its binary output.
+ * @param newClasspath IClasspathEntry[]
+ * @param newOutputLocation IPath
+ * @param otherClasspathWithOutput IClasspathEntry[]
+ * @return boolean
+ */
+ private static boolean areClasspathsEqual(IClasspathEntry[] newClasspath, IPath newOutputLocation, IClasspathEntry[] otherClasspathWithOutput) {
+
+ if (otherClasspathWithOutput == null || otherClasspathWithOutput.length == 0)
+ return false;
+
+ int length = otherClasspathWithOutput.length;
+ if (length != newClasspath.length + 1)
+ // output is amongst file entries (last one)
+ return false;
+
+
+ // compare classpath entries
+ for (int i = 0; i < length - 1; i++) {
+ if (!otherClasspathWithOutput[i].equals(newClasspath[i]))
+ return false;
+ }
+ // compare binary outputs
+ IClasspathEntry output = otherClasspathWithOutput[length - 1];
+ if (output.getContentKind() != ClasspathEntry.K_OUTPUT
+ || !output.getPath().equals(newOutputLocation))
+ return false;
+ return true;
+ }
+
+ /**
* Returns a canonicalized path from the given external path.
* Note that the return path contains the same number of segments
* and it contains a device only if the given path contained one.
@@ -147,12 +222,12 @@
return null;
// if (JavaModelManager.VERBOSE) {
-// System.out.println("JAVA MODEL - Canonicalizing " + externalPath.toString()); //$NON-NLS-1$
+// System.out.println("JAVA MODEL - Canonicalizing " + externalPath.toString());
// }
if (IS_CASE_SENSITIVE) {
// if (JavaModelManager.VERBOSE) {
-// System.out.println("JAVA MODEL - Canonical path is original path (file system is case sensitive)"); //$NON-NLS-1$
+// System.out.println("JAVA MODEL - Canonical path is original path (file system is case sensitive)");
// }
return externalPath;
}
@@ -162,7 +237,7 @@
if (workspace == null) return externalPath; // protection during shutdown (30487)
if (workspace.getRoot().findMember(externalPath) != null) {
// if (JavaModelManager.VERBOSE) {
-// System.out.println("JAVA MODEL - Canonical path is original path (member of workspace)"); //$NON-NLS-1$
+// System.out.println("JAVA MODEL - Canonical path is original path (member of workspace)");
// }
return externalPath;
}
@@ -174,7 +249,7 @@
} catch (IOException e) {
// default to original path
// if (JavaModelManager.VERBOSE) {
-// System.out.println("JAVA MODEL - Canonical path is original path (IOException)"); //$NON-NLS-1$
+// System.out.println("JAVA MODEL - Canonical path is original path (IOException)");
// }
return externalPath;
}
@@ -184,7 +259,7 @@
if (canonicalLength == 0) {
// the java.io.File canonicalization failed
// if (JavaModelManager.VERBOSE) {
-// System.out.println("JAVA MODEL - Canonical path is original path (canonical path is empty)"); //$NON-NLS-1$
+// System.out.println("JAVA MODEL - Canonical path is original path (canonical path is empty)");
// }
return externalPath;
} else if (externalPath.isAbsolute()) {
@@ -197,7 +272,7 @@
result = canonicalPath.removeFirstSegments(canonicalLength - externalLength);
} else {
// if (JavaModelManager.VERBOSE) {
-// System.out.println("JAVA MODEL - Canonical path is original path (canonical path is " + canonicalPath.toString() + ")"); //$NON-NLS-1$ //$NON-NLS-2$
+// System.out.println("JAVA MODEL - Canonical path is original path (canonical path is " + canonicalPath.toString() + ")");
// }
return externalPath;
}
@@ -208,11 +283,11 @@
result = result.setDevice(null);
}
// if (JavaModelManager.VERBOSE) {
-// System.out.println("JAVA MODEL - Canonical path is " + result.toString()); //$NON-NLS-1$
+// System.out.println("JAVA MODEL - Canonical path is " + result.toString());
// }
return result;
}
-
+
/**
* Returns true if the given project is accessible and it has
* a java nature, otherwise false.
@@ -223,17 +298,20 @@
try {
return project.hasNature(JavaCore.NATURE_ID);
} catch (CoreException e) {
+ if (ExternalJavaProject.EXTERNAL_PROJECT_NAME.equals(project.getName()))
+ return true;
// project does not exist or is not open
}
return false;
}
- /**
- * Update cycle markers for all java projects
+ /*
+ * Detect cycles in the classpath of the workspace's projects
+ * and create markers if necessary.
* @param preferredClasspaths Map
* @throws JavaModelException
*/
- public static void updateAllCycleMarkers(Map preferredClasspaths) throws JavaModelException {
+ public static void validateCycles(Map preferredClasspaths) throws JavaModelException {
//long start = System.currentTimeMillis();
@@ -288,20 +366,6 @@
}
/**
- * Constructor needed for <code>IProject.getNature()</code> and <code>IProject.addNature()</code>.
- *
- * @see #setProject(IProject)
- */
- public JavaProject() {
- super(null);
- }
-
- public JavaProject(IProject project, JavaElement parent) {
- super(parent);
- this.project = project;
- }
-
- /**
* Adds a builder to the build spec for the given project.
*/
protected void addToBuildSpec(String builderID) throws CoreException {
@@ -317,19 +381,18 @@
setJavaCommand(description, command);
}
}
-
/**
* @see Openable
*/
protected boolean buildStructure(OpenableElementInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource) throws JavaModelException {
// check whether the java project can be opened
- if (!underlyingResource.isAccessible()) {
+ if (!hasJavaNature((IProject) underlyingResource)) {
throw newNotPresentException();
}
// cannot refresh cp markers on opening (emulate cp check on startup) since can create deadlocks (see bug 37274)
- IClasspathEntry[] resolvedClasspath = getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/);
+ IClasspathEntry[] resolvedClasspath = getResolvedClasspath();
// compute the pkg fragment roots
info.setChildren(computePackageFragmentRoots(resolvedClasspath, false, null /*no reverse map*/));
@@ -340,19 +403,6 @@
return true;
}
- protected void closing(Object info) {
-
- // forget source attachment recommendations
- Object[] children = ((JavaElementInfo)info).children;
- for (int i = 0, length = children.length; i < length; i++) {
- Object child = children[i];
- if (child instanceof JarPackageFragmentRoot){
- ((JarPackageFragmentRoot)child).setSourceAttachmentProperty(null);
- }
- }
-
- super.closing(info);
- }
/**
* Computes the collection of package fragment roots (local ones) and set it on the given info.
* Need to check *all* package fragment roots in order to reset NameLookup
@@ -360,7 +410,7 @@
* @throws JavaModelException
*/
public void computeChildren(JavaProjectElementInfo info) throws JavaModelException {
- IClasspathEntry[] classpath = getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/);
+ IClasspathEntry[] classpath = getResolvedClasspath();
JavaProjectElementInfo.ProjectCache projectCache = info.projectCache;
if (projectCache != null) {
IPackageFragmentRoot[] newRoots = computePackageFragmentRoots(classpath, true, null /*no reverse map*/);
@@ -381,20 +431,14 @@
computePackageFragmentRoots(classpath, false, null /*no reverse map*/));
}
-
-
/**
* Internal computation of an expanded classpath. It will eliminate duplicates, and produce copies
* of exported or restricted classpath entries to avoid possible side-effects ever after.
*/
private void computeExpandedClasspath(
ClasspathEntry referringEntry,
- boolean ignoreUnresolvedVariable,
- boolean generateMarkerOnError,
HashSet rootIDs,
- ObjectVector accumulatedEntries,
- Map preferredClasspaths,
- Map preferredOutputs) throws JavaModelException {
+ ObjectVector accumulatedEntries) throws JavaModelException {
String projectRootId = this.rootID();
if (rootIDs.contains(projectRootId)){
@@ -402,17 +446,12 @@
}
rootIDs.add(projectRootId);
- IClasspathEntry[] preferredClasspath = preferredClasspaths != null ? (IClasspathEntry[])preferredClasspaths.get(this) : null;
- IPath preferredOutput = preferredOutputs != null ? (IPath)preferredOutputs.get(this) : null;
- IClasspathEntry[] immediateClasspath =
- preferredClasspath != null
- ? getResolvedClasspath(preferredClasspath, preferredOutput, ignoreUnresolvedVariable, generateMarkerOnError, null /*no reverse map*/)
- : getResolvedClasspath(ignoreUnresolvedVariable, generateMarkerOnError, false/*don't returnResolutionInProgress*/);
+ IClasspathEntry[] resolvedClasspath = getResolvedClasspath();
IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
boolean isInitialProject = referringEntry == null;
- for (int i = 0, length = immediateClasspath.length; i < length; i++){
- ClasspathEntry entry = (ClasspathEntry) immediateClasspath[i];
+ for (int i = 0, length = resolvedClasspath.length; i < length; i++){
+ ClasspathEntry entry = (ClasspathEntry) resolvedClasspath[i];
if (isInitialProject || entry.isExported()){
String rootID = entry.rootID();
if (rootIDs.contains(rootID)) {
@@ -431,12 +470,8 @@
JavaProject javaProject = (JavaProject) JavaCore.create(projRsc);
javaProject.computeExpandedClasspath(
combinedEntry,
- ignoreUnresolvedVariable,
- false /* no marker when recursing in prereq*/,
- rootIDs,
- accumulatedEntries,
- preferredClasspaths,
- preferredOutputs);
+ rootIDs,
+ accumulatedEntries);
}
}
} else {
@@ -445,7 +480,7 @@
}
}
}
-
+
/**
* Computes the package fragment roots identified by the given entry.
* Only works with resolved entry
@@ -464,7 +499,7 @@
return new IPackageFragmentRoot[] {};
}
}
-
+
/**
* Returns the package fragment roots identified by the given entry. In case it refers to
* a project, it will follow its classpath so as to find exported roots as well.
@@ -549,7 +584,7 @@
rootIDs.add(rootID);
JavaProject requiredProject = (JavaProject)JavaCore.create(requiredProjectRsc);
requiredProject.computePackageFragmentRoots(
- requiredProject.getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/),
+ requiredProject.getResolvedClasspath(),
accumulatedRoots,
rootIDs,
rootToResolvedEntries == null ? resolvedEntry : ((ClasspathEntry)resolvedEntry).combineWith((ClasspathEntry) referringEntry), // only combine if need to build the reverse map
@@ -566,7 +601,7 @@
if (rootToResolvedEntries != null) rootToResolvedEntries.put(root, ((ClasspathEntry)resolvedEntry).combineWith((ClasspathEntry) referringEntry));
}
}
-
+
/**
* Returns (local/all) the package fragment roots identified by the given project's classpath.
* Note: this follows project classpath references to find required project contributions,
@@ -595,7 +630,7 @@
accumulatedRoots.copyInto(rootArray);
return rootArray;
}
-
+
/**
* Returns (local/all) the package fragment roots identified by the given project's classpath.
* Note: this follows project classpath references to find required project contributions,
@@ -632,7 +667,6 @@
rootToResolvedEntries);
}
}
-
/**
* Compute the file name to use for a given shared property
* @param qName QualifiedName
@@ -642,7 +676,7 @@
return '.' + qName.getLocalName();
}
-
+
/**
* Configure the project with Java nature.
*/
@@ -651,6 +685,7 @@
// register Java builder
addToBuildSpec(JavaCore.BUILDER_ID);
}
+
/*
* Returns whether the given resource is accessible through the children or the non-Java resources of this project.
* Returns true if the resource is not in the project.
@@ -661,7 +696,7 @@
IClasspathEntry[] classpath;
IPath output;
try {
- classpath = getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/);
+ classpath = getResolvedClasspath();
output = getOutputLocation();
} catch (JavaModelException e) {
return false;
@@ -711,11 +746,11 @@
/**
* Record a new marker denoting a classpath problem
*/
- void createClasspathProblemMarker(IJavaModelStatus status) {
+ public void createClasspathProblemMarker(IJavaModelStatus status) {
IMarker marker = null;
int severity;
- String[] arguments = new String[0];
+ String[] arguments = CharOperation.NO_STRINGS;
boolean isCycleProblem = false, isClasspathFileFormatProblem = false;
switch (status.getCode()) {
@@ -747,7 +782,8 @@
default:
IPath path = status.getPath();
if (path != null) arguments = new String[] { path.toString() };
- if (JavaCore.ERROR.equals(getOption(JavaCore.CORE_INCOMPLETE_CLASSPATH, true))) {
+ if (JavaCore.ERROR.equals(getOption(JavaCore.CORE_INCOMPLETE_CLASSPATH, true)) &&
+ status.getSeverity() != IStatus.WARNING) {
severity = IMarker.SEVERITY_ERROR;
} else {
severity = IMarker.SEVERITY_WARNING;
@@ -766,6 +802,8 @@
IJavaModelMarker.CLASSPATH_FILE_FORMAT,
IJavaModelMarker.ID,
IJavaModelMarker.ARGUMENTS ,
+ IJavaModelMarker.CATEGORY_ID,
+ IMarker.SOURCE_ID,
},
new Object[] {
status.getMessage(),
@@ -775,6 +813,8 @@
isClasspathFileFormatProblem ? "true" : "false",//$NON-NLS-1$ //$NON-NLS-2$
new Integer(status.getCode()),
Util.getProblemArgumentsForMarker(arguments) ,
+ new Integer(CategorizedProblem.CAT_BUILDPATH),
+ JavaBuilder.SOURCE_ID,
}
);
} catch (CoreException e) {
@@ -784,7 +824,7 @@
}
}
}
-
+
/**
* Returns a new element info for this element.
*/
@@ -792,84 +832,83 @@
return new JavaProjectElementInfo();
}
- /**
+ /*
* Reads and decode an XML classpath string
*/
- protected IClasspathEntry[] decodeClasspath(String xmlClasspath, boolean createMarker, boolean logProblems) {
-
+ public IClasspathEntry[] decodeClasspath(String xmlClasspath, Map unknownElements) throws IOException, AssertionFailedException {
+
ArrayList paths = new ArrayList();
IClasspathEntry defaultOutput = null;
+ StringReader reader = new StringReader(xmlClasspath);
+ Element cpElement;
try {
- if (xmlClasspath == null) return null;
- StringReader reader = new StringReader(xmlClasspath);
- Element cpElement;
-
- try {
- DocumentBuilder parser =
- DocumentBuilderFactory.newInstance().newDocumentBuilder();
- cpElement = parser.parse(new InputSource(reader)).getDocumentElement();
- } catch (SAXException e) {
- throw new IOException(Messages.file_badFormat);
- } catch (ParserConfigurationException e) {
- throw new IOException(Messages.file_badFormat);
- } finally {
- reader.close();
- }
-
- if (!cpElement.getNodeName().equalsIgnoreCase("classpath")) { //$NON-NLS-1$
- throw new IOException(Messages.file_badFormat);
- }
- NodeList list = cpElement.getElementsByTagName("classpathentry"); //$NON-NLS-1$
- int length = list.getLength();
-
- for (int i = 0; i < length; ++i) {
- Node node = list.item(i);
- if (node.getNodeType() == Node.ELEMENT_NODE) {
- IClasspathEntry entry = ClasspathEntry.elementDecode((Element)node, this);
- if (entry != null){
- if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) {
- defaultOutput = entry; // separate output
- } else {
- paths.add(entry);
- }
- }
- }
- }
- } catch (IOException e) {
- // bad format
- if (createMarker && this.project.isAccessible()) {
- this.createClasspathProblemMarker(new JavaModelStatus(
- IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
- Messages.bind(Messages.classpath_xmlFormatError, new String[] {this.getElementName(), e.getMessage()})));
- }
- if (logProblems) {
- Util.log(e,
- "Exception while retrieving "+ this.getPath() //$NON-NLS-1$
- +"/.classpath, will mark classpath as invalid"); //$NON-NLS-1$
- }
- return INVALID_CLASSPATH;
- } catch (Assert.AssertionFailedException e) {
- // failed creating CP entries from file
- if (createMarker && this.project.isAccessible()) {
- this.createClasspathProblemMarker(new JavaModelStatus(
- IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
- Messages.bind(Messages.classpath_illegalEntryInClasspathFile, new String[] {this.getElementName(), e.getMessage()})));
- }
- if (logProblems) {
- Util.log(e,
- "Exception while retrieving "+ this.getPath() //$NON-NLS-1$
- +"/.classpath, will mark classpath as invalid"); //$NON-NLS-1$
- }
- return INVALID_CLASSPATH;
+ DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ cpElement = parser.parse(new InputSource(reader)).getDocumentElement();
+ } catch (SAXException e) {
+ throw new IOException(Messages.file_badFormat);
+ } catch (ParserConfigurationException e) {
+ throw new IOException(Messages.file_badFormat);
+ } finally {
+ reader.close();
}
- // return an empty classpath is it size is 0, to differenciate from a null classpath
+
+ if (!cpElement.getNodeName().equalsIgnoreCase("classpath")) { //$NON-NLS-1$
+ throw new IOException(Messages.file_badFormat);
+ }
+ NodeList list = cpElement.getElementsByTagName("classpathentry"); //$NON-NLS-1$
+ int length = list.getLength();
+
+ for (int i = 0; i < length; ++i) {
+ Node node = list.item(i);
+ if (node.getNodeType() == Node.ELEMENT_NODE) {
+ IClasspathEntry entry = ClasspathEntry.elementDecode((Element)node, this, unknownElements);
+ if (entry != null){
+ if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) {
+ defaultOutput = entry; // separate output
+ } else {
+ paths.add(entry);
+ }
+ }
+ }
+ }
+ // return a new empty classpath is it size is 0, to differenciate from an INVALID_CLASSPATH
int pathSize = paths.size();
IClasspathEntry[] entries = new IClasspathEntry[pathSize + (defaultOutput == null ? 0 : 1)];
paths.toArray(entries);
if (defaultOutput != null) entries[pathSize] = defaultOutput; // ensure output is last item
return entries;
}
+
+ public IClasspathEntry decodeClasspathEntry(String encodedEntry) {
+ try {
+ if (encodedEntry == null) return null;
+ StringReader reader = new StringReader(encodedEntry);
+ Element node;
+
+ try {
+ DocumentBuilder parser =
+ DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ node = parser.parse(new InputSource(reader)).getDocumentElement();
+ } catch (SAXException e) {
+ return null;
+ } catch (ParserConfigurationException e) {
+ return null;
+ } finally {
+ reader.close();
+ }
+
+ if (!node.getNodeName().equalsIgnoreCase("classpathentry") //$NON-NLS-1$
+ || node.getNodeType() != Node.ELEMENT_NODE) {
+ return null;
+ }
+ return ClasspathEntry.elementDecode(node, this, null/*not interested in unknown elements*/);
+ } catch (IOException e) {
+ // bad format
+ return null;
+ }
+ }
+
/**
/**
* Removes the Java nature from the project.
@@ -878,6 +917,9 @@
// deregister Java builder
removeFromBuildSpec(JavaCore.BUILDER_ID);
+
+ // remove .classpath file
+// getProject().getFile(ClasspathHelper.CLASSPATH_FILENAME).delete(false, null);
}
/**
@@ -889,7 +931,7 @@
return new IClasspathEntry[] {
JavaCore.newSourceEntry(this.project.getFullPath())};
}
-
+
/**
* Returns a default output location.
* This is the project bin folder
@@ -901,15 +943,15 @@
/**
* Returns the XML String encoding of the class path.
*/
- protected String encodeClasspath(IClasspathEntry[] classpath, IPath outputLocation, boolean indent) throws JavaModelException {
+ protected String encodeClasspath(IClasspathEntry[] classpath, IPath outputLocation, boolean indent, Map unknownElements) throws JavaModelException {
try {
ByteArrayOutputStream s = new ByteArrayOutputStream();
OutputStreamWriter writer = new OutputStreamWriter(s, "UTF8"); //$NON-NLS-1$
- XMLWriter xmlWriter = new XMLWriter(writer, this);
+ XMLWriter xmlWriter = new XMLWriter(writer, this, true/*print XML version*/);
xmlWriter.startTag(ClasspathEntry.TAG_CLASSPATH, indent);
for (int i = 0; i < classpath.length; ++i) {
- ((ClasspathEntry)classpath[i]).elementEncode(xmlWriter, this.project.getFullPath(), indent, true);
+ ((ClasspathEntry)classpath[i]).elementEncode(xmlWriter, this.project.getFullPath(), indent, true, unknownElements);
}
if (outputLocation != null) {
@@ -921,15 +963,31 @@
xmlWriter.printTag(ClasspathEntry.TAG_CLASSPATHENTRY, parameters, indent, true, true);
}
- xmlWriter.endTag(ClasspathEntry.TAG_CLASSPATH, indent);
+ xmlWriter.endTag(ClasspathEntry.TAG_CLASSPATH, indent, true/*insert new line*/);
writer.flush();
writer.close();
return s.toString("UTF8");//$NON-NLS-1$
} catch (IOException e) {
throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
}
- }
+ }
+
+ public String encodeClasspathEntry(IClasspathEntry classpathEntry) {
+ try {
+ ByteArrayOutputStream s = new ByteArrayOutputStream();
+ OutputStreamWriter writer = new OutputStreamWriter(s, "UTF8"); //$NON-NLS-1$
+ XMLWriter xmlWriter = new XMLWriter(writer, this, false/*don't print XML version*/);
+
+ ((ClasspathEntry)classpathEntry).elementEncode(xmlWriter, this.project.getFullPath(), true/*indent*/, true/*insert new line*/, null/*not interested in unknown elements*/);
+ writer.flush();
+ writer.close();
+ return s.toString("UTF8");//$NON-NLS-1$
+ } catch (IOException e) {
+ return null; // never happens since all is done in memory
+ }
+ }
+
/**
* Returns true if this handle represents the same Java project
* as the given handle. Two handles represent the same
@@ -951,18 +1009,23 @@
}
public boolean exists() {
- return hasJavaNature(this.project);
- }
+ try {
+ return this.project.hasNature(JavaCore.NATURE_ID);
+ } catch (CoreException e) {
+ // project does not exist or is not open
+ }
+ return false;
+ }
/**
- * @see IJavaProject
+ * @see IJavaProject#findElement(IPath)
*/
public IJavaElement findElement(IPath path) throws JavaModelException {
return findElement(path, DefaultWorkingCopyOwner.PRIMARY);
}
/**
- * @see IJavaProject
+ * @see IJavaProject#findElement(IPath, WorkingCopyOwner)
*/
public IJavaElement findElement(IPath path, WorkingCopyOwner owner) throws JavaModelException {
@@ -1008,13 +1071,17 @@
// lookup type
NameLookup lookup = newNameLookup(owner);
- IType type = lookup.findType(
+ NameLookup.Answer answer = lookup.findType(
qualifiedName,
false,
- NameLookup.ACCEPT_ALL);
+ NameLookup.ACCEPT_ALL,
+ true/* consider secondary types */,
+ false/* do NOT wait for indexes */,
+ false/*don't check restrictions*/,
+ null);
- if (type != null) {
- return type.getParent();
+ if (answer != null) {
+ return answer.type.getParent();
} else {
return null;
}
@@ -1040,7 +1107,6 @@
return findPackageFragment0(JavaProject.canonicalizedPath(path));
}
-
/*
* non path canonicalizing version
*/
@@ -1059,7 +1125,6 @@
return findPackageFragmentRoot0(JavaProject.canonicalizedPath(path));
}
-
/*
* no path canonicalization
*/
@@ -1088,7 +1153,7 @@
if (classpath[i].equals(entry)) { // entry may need to be resolved
return
computePackageFragmentRoots(
- getResolvedClasspath(new IClasspathEntry[] {entry}, null, true, false, null/*no reverse map*/),
+ resolveClasspath(new IClasspathEntry[] {entry}),
false, // don't retrieve exported roots
null); /*no reverse map*/
}
@@ -1098,59 +1163,116 @@
}
return new IPackageFragmentRoot[] {};
}
-
/**
* @see IJavaProject#findType(String)
*/
public IType findType(String fullyQualifiedName) throws JavaModelException {
return findType(fullyQualifiedName, DefaultWorkingCopyOwner.PRIMARY);
}
-
/**
- * @see IJavaProject#findType(String, String)
+ * @see IJavaProject#findType(String, IProgressMonitor)
*/
- public IType findType(String packageName, String typeQualifiedName) throws JavaModelException {
- return findType(packageName, typeQualifiedName, DefaultWorkingCopyOwner.PRIMARY);
+ public IType findType(String fullyQualifiedName, IProgressMonitor progressMonitor) throws JavaModelException {
+ return findType(fullyQualifiedName, DefaultWorkingCopyOwner.PRIMARY, progressMonitor);
}
- /**
- * @see IJavaProject#findType(String, String, WorkingCopyOwner)
+ /*
+ * Internal findType with instanciated name lookup
*/
- public IType findType(String packageName, String typeQualifiedName, WorkingCopyOwner owner) throws JavaModelException {
- NameLookup lookup = newNameLookup(owner);
- return lookup.findType(
- typeQualifiedName,
- packageName,
- false,
- NameLookup.ACCEPT_ALL);
- }
-
- /**
- * @see IJavaProject#findType(String, WorkingCopyOwner)
- */
- public IType findType(String fullyQualifiedName, WorkingCopyOwner owner) throws JavaModelException {
-
- NameLookup lookup = newNameLookup(owner);
- IType type = lookup.findType(
+ IType findType(String fullyQualifiedName, NameLookup lookup, boolean considerSecondaryTypes, IProgressMonitor progressMonitor) throws JavaModelException {
+ NameLookup.Answer answer = lookup.findType(
fullyQualifiedName,
false,
- NameLookup.ACCEPT_ALL);
- if (type == null) {
+ NameLookup.ACCEPT_ALL,
+ considerSecondaryTypes,
+ true, /* wait for indexes (only if consider secondary types)*/
+ false/*don't check restrictions*/,
+ progressMonitor);
+ if (answer == null) {
// try to find enclosing type
int lastDot = fullyQualifiedName.lastIndexOf('.');
if (lastDot == -1) return null;
- type = this.findType(fullyQualifiedName.substring(0, lastDot));
+ IType type = findType(fullyQualifiedName.substring(0, lastDot), lookup, considerSecondaryTypes, progressMonitor);
if (type != null) {
type = type.getType(fullyQualifiedName.substring(lastDot+1));
if (!type.exists()) {
return null;
}
}
+ return type;
}
- return type;
+ return answer.type;
}
+ /**
+ * @see IJavaProject#findType(String, String)
+ */
+ public IType findType(String packageName, String typeQualifiedName) throws JavaModelException {
+ return findType(packageName, typeQualifiedName, DefaultWorkingCopyOwner.PRIMARY);
+ }
+ /**
+ * @see IJavaProject#findType(String, String, IProgressMonitor)
+ */
+ public IType findType(String packageName, String typeQualifiedName, IProgressMonitor progressMonitor) throws JavaModelException {
+ return findType(packageName, typeQualifiedName, DefaultWorkingCopyOwner.PRIMARY, progressMonitor);
+ }
+ /*
+ * Internal findType with instanciated name lookup
+ */
+ IType findType(String packageName, String typeQualifiedName, NameLookup lookup, boolean considerSecondaryTypes, IProgressMonitor progressMonitor) throws JavaModelException {
+ NameLookup.Answer answer = lookup.findType(
+ typeQualifiedName,
+ packageName,
+ false,
+ NameLookup.ACCEPT_ALL,
+ considerSecondaryTypes,
+ true, // wait for indexes (in case we need to consider secondary types)
+ false/*don't check restrictions*/,
+ progressMonitor);
+ return answer == null ? null : answer.type;
+ }
+ /**
+ * @see IJavaProject#findType(String, String, WorkingCopyOwner)
+ */
+ public IType findType(String packageName, String typeQualifiedName, WorkingCopyOwner owner) throws JavaModelException {
+ NameLookup lookup = newNameLookup(owner);
+ return findType(
+ packageName,
+ typeQualifiedName,
+ lookup,
+ false, // do not consider secondary types
+ null);
+ }
/**
+ * @see IJavaProject#findType(String, String, WorkingCopyOwner, IProgressMonitor)
+ */
+ public IType findType(String packageName, String typeQualifiedName, WorkingCopyOwner owner, IProgressMonitor progressMonitor) throws JavaModelException {
+ NameLookup lookup = newNameLookup(owner);
+ return findType(
+ packageName,
+ typeQualifiedName,
+ lookup,
+ true, // consider secondary types
+ progressMonitor);
+ }
+
+ /**
+ * @see IJavaProject#findType(String, WorkingCopyOwner)
+ */
+ public IType findType(String fullyQualifiedName, WorkingCopyOwner owner) throws JavaModelException {
+ NameLookup lookup = newNameLookup(owner);
+ return findType(fullyQualifiedName, lookup, false, null);
+ }
+
+ /**
+ * @see IJavaProject#findType(String, WorkingCopyOwner, IProgressMonitor)
+ */
+ public IType findType(String fullyQualifiedName, WorkingCopyOwner owner, IProgressMonitor progressMonitor) throws JavaModelException {
+ NameLookup lookup = newNameLookup(owner);
+ return findType(fullyQualifiedName, lookup, true, progressMonitor);
+ }
+
+ /**
* Remove all markers denoting classpath problems
*/ //TODO (philippe) should improve to use a bitmask instead of booleans (CYCLE, FORMAT, VALID)
protected void flushClasspathProblemMarkers(boolean flushCycleMarkers, boolean flushClasspathFormatMarkers) {
@@ -1178,108 +1300,7 @@
}
}
}
-
- /*
- * Force the project to reload its <code>.classpath</code> file from disk and update the classpath accordingly.
- * Usually, a change to the <code>.classpath</code> file is automatically noticed and reconciled at the next
- * resource change notification event. If required to consider such a change prior to the next automatic
- * refresh, then this functionnality should be used to trigger a refresh. In particular, if a change to the file is performed,
- * during an operation where this change needs to be reflected before the operation ends, then an explicit refresh is
- * necessary.
- * Note that classpath markers are NOT created.
- *
- * @param monitor a progress monitor for reporting operation progress
- * @exception JavaModelException if the classpath could not be updated. 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>
- */
- protected void forceClasspathReload(IProgressMonitor monitor) throws JavaModelException {
-
- if (monitor != null && monitor.isCanceled()) return;
-
- // check if any actual difference
- boolean wasSuccessful = false; // flag recording if .classpath file change got reflected
- try {
- // force to (re)read the property file
- IClasspathEntry[] fileEntries = readClasspathFile(false/*don't create markers*/, false/*don't log problems*/);
- if (fileEntries == null) {
- return; // could not read, ignore
- }
- JavaModelManager.PerProjectInfo info = getPerProjectInfo();
- if (info.rawClasspath != null) { // if there is an in-memory classpath
- if (isClasspathEqualsTo(info.rawClasspath, info.outputLocation, fileEntries)) {
- wasSuccessful = true;
- return;
- }
- }
-
- // will force an update of the classpath/output location based on the file information
- // extract out the output location
- IPath outputLocation = SetClasspathOperation.DO_NOT_SET_OUTPUT;
- if (fileEntries != null && fileEntries.length > 0) {
- IClasspathEntry entry = fileEntries[fileEntries.length - 1];
- if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) {
- outputLocation = entry.getPath();
- IClasspathEntry[] copy = new IClasspathEntry[fileEntries.length - 1];
- System.arraycopy(fileEntries, 0, copy, 0, copy.length);
- fileEntries = copy;
- }
- }
- IClasspathEntry[] oldResolvedClasspath = info.resolvedClasspath;
- setRawClasspath(
- fileEntries,
- outputLocation,
- monitor,
- !ResourcesPlugin.getWorkspace().isTreeLocked(), // canChangeResource
- oldResolvedClasspath != null ? oldResolvedClasspath : getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/),
- true, // needValidation
- false); // no need to save
-
- // if reach that far, the classpath file change got absorbed
- wasSuccessful = true;
- } catch (RuntimeException e) {
- // setRawClasspath might fire a delta, and a listener may throw an exception
- if (this.project.isAccessible()) {
- Util.log(e, "Could not set classpath for "+ getPath()); //$NON-NLS-1$
- }
- throw e; // rethrow
- } catch (JavaModelException e) { // CP failed validation
- if (!ResourcesPlugin.getWorkspace().isTreeLocked()) {
- if (this.project.isAccessible()) {
- if (e.getJavaModelStatus().getException() instanceof CoreException) {
- // happens if the .classpath could not be written to disk
- createClasspathProblemMarker(new JavaModelStatus(
- IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
- Messages.bind(Messages.classpath_couldNotWriteClasspathFile, new String[] {getElementName(), e.getMessage()})));
- } else {
- createClasspathProblemMarker(new JavaModelStatus(
- IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
- Messages.bind(Messages.classpath_invalidClasspathInClasspathFile, new String[] {getElementName(), e.getMessage()})));
- }
- }
- }
- throw e; // rethrow
- } finally {
- if (!wasSuccessful) {
- try {
- this.getPerProjectInfo().updateClasspathInformation(JavaProject.INVALID_CLASSPATH);
- updatePackageFragmentRoots();
- } catch (JavaModelException e) {
- // ignore
- }
- }
- }
- }
-
+
/**
* Returns the set of patterns corresponding to this project visibility given rules
* @return an array of IPath or null if none
@@ -1307,10 +1328,10 @@
return getAllPackageFragmentRoots(null /*no reverse map*/);
}
-
+
public IPackageFragmentRoot[] getAllPackageFragmentRoots(Map rootToResolvedEntries) throws JavaModelException {
- return computePackageFragmentRoots(getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/), true/*retrieveExportedRoots*/, rootToResolvedEntries);
+ return computePackageFragmentRoots(getResolvedClasspath(), true/*retrieveExportedRoots*/, rootToResolvedEntries);
}
/**
@@ -1320,18 +1341,17 @@
* @return IClasspathEntry
* @throws JavaModelException
*/
- public IClasspathEntry getClasspathEntryFor(IPath path)
- throws JavaModelException {
-
- IClasspathEntry[] entries = getExpandedClasspath(true);
- for (int i = 0; i < entries.length; i++) {
- if (entries[i].getPath().equals(path)) {
- return entries[i];
- }
- }
- return null;
+ public IClasspathEntry getClasspathEntryFor(IPath path) throws JavaModelException {
+ getResolvedClasspath(); // force resolution
+ PerProjectInfo perProjectInfo = getPerProjectInfo();
+ if (perProjectInfo == null)
+ return null;
+ Map rootPathToResolvedEntries = perProjectInfo.rootPathToResolvedEntries;
+ if (rootPathToResolvedEntries == null)
+ return null;
+ return (IClasspathEntry) rootPathToResolvedEntries.get(path);
}
-
+
/*
* Returns the cycle marker associated with this project or null if none.
*/
@@ -1353,49 +1373,66 @@
return null;
}
- /**
- * Returns the project custom preference pool.
- * Project preferences may include custom encoding.
- * @return IEclipsePreferences
- */
- public IEclipsePreferences getEclipsePreferences(){
- if (!JavaProject.hasJavaNature(this.project)) return null;
- // Get cached preferences if exist
- JavaModelManager.PerProjectInfo perProjectInfo = JavaModelManager.getJavaModelManager().getPerProjectInfo(this.project, true);
- if (perProjectInfo.preferences != null) return perProjectInfo.preferences;
- // Init project preferences
- IScopeContext context = new ProjectScope(getProject());
- final IEclipsePreferences eclipsePreferences = context.getNode(JavaCore.PLUGIN_ID);
- updatePreferences(eclipsePreferences);
- perProjectInfo.preferences = eclipsePreferences;
-
- // Listen to node removal from parent in order to reset cache (see bug 68993)
- IEclipsePreferences.INodeChangeListener nodeListener = new IEclipsePreferences.INodeChangeListener() {
- public void added(IEclipsePreferences.NodeChangeEvent event) {
- // do nothing
- }
- public void removed(IEclipsePreferences.NodeChangeEvent event) {
- if (event.getChild() == eclipsePreferences) {
- JavaModelManager.getJavaModelManager().resetProjectPreferences(JavaProject.this);
- }
- }
- };
- ((IEclipsePreferences) eclipsePreferences.parent()).addNodeChangeListener(nodeListener);
-
- // Listen to preference changes
- IEclipsePreferences.IPreferenceChangeListener preferenceListener = new IEclipsePreferences.IPreferenceChangeListener() {
- public void preferenceChange(IEclipsePreferences.PreferenceChangeEvent event) {
- JavaModelManager.getJavaModelManager().resetProjectOptions(JavaProject.this);
- }
- };
- eclipsePreferences.addPreferenceChangeListener(preferenceListener);
- return eclipsePreferences;
- }
-
+ /**
+ * Returns the project custom preference pool.
+ * Project preferences may include custom encoding.
+ * @return IEclipsePreferences
+ */
+ public IEclipsePreferences getEclipsePreferences(){
+ if (!JavaProject.hasJavaNature(this.project)) return null;
+ // Get cached preferences if exist
+ JavaModelManager.PerProjectInfo perProjectInfo = JavaModelManager.getJavaModelManager().getPerProjectInfo(this.project, true);
+ if (perProjectInfo.preferences != null) return perProjectInfo.preferences;
+ // Init project preferences
+ IScopeContext context = new ProjectScope(getProject());
+ final IEclipsePreferences eclipsePreferences = context.getNode(JavaCore.PLUGIN_ID);
+ updatePreferences(eclipsePreferences);
+ perProjectInfo.preferences = eclipsePreferences;
+
+ // Listen to node removal from parent in order to reset cache (see bug 68993)
+ IEclipsePreferences.INodeChangeListener nodeListener = new IEclipsePreferences.INodeChangeListener() {
+ public void added(IEclipsePreferences.NodeChangeEvent event) {
+ // do nothing
+ }
+ public void removed(IEclipsePreferences.NodeChangeEvent event) {
+ if (event.getChild() == eclipsePreferences) {
+ JavaModelManager.getJavaModelManager().resetProjectPreferences(JavaProject.this);
+ }
+ }
+ };
+ ((IEclipsePreferences) eclipsePreferences.parent()).addNodeChangeListener(nodeListener);
+
+ // Listen to preference changes
+ IEclipsePreferences.IPreferenceChangeListener preferenceListener = new IEclipsePreferences.IPreferenceChangeListener() {
+ public void preferenceChange(IEclipsePreferences.PreferenceChangeEvent event) {
+ String propertyName = event.getKey();
+ JavaModelManager manager = JavaModelManager.getJavaModelManager();
+ if (propertyName.startsWith(JavaCore.PLUGIN_ID)) {
+ if (propertyName.equals(JavaCore.CORE_JAVA_BUILD_CLEAN_OUTPUT_FOLDER) ||
+ propertyName.equals(JavaCore.CORE_JAVA_BUILD_RESOURCE_COPY_FILTER) ||
+ propertyName.equals(JavaCore.CORE_JAVA_BUILD_DUPLICATE_RESOURCE) ||
+ propertyName.equals(JavaCore.CORE_JAVA_BUILD_RECREATE_MODIFIED_CLASS_FILES_IN_OUTPUT_FOLDER) ||
+ propertyName.equals(JavaCore.CORE_JAVA_BUILD_INVALID_CLASSPATH) ||
+ propertyName.equals(JavaCore.CORE_ENABLE_CLASSPATH_EXCLUSION_PATTERNS) ||
+ propertyName.equals(JavaCore.CORE_ENABLE_CLASSPATH_MULTIPLE_OUTPUT_LOCATIONS) ||
+ propertyName.equals(JavaCore.CORE_INCOMPLETE_CLASSPATH) ||
+ propertyName.equals(JavaCore.CORE_CIRCULAR_CLASSPATH) ||
+ propertyName.equals(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL))
+ {
+ manager.deltaState.addClasspathValidation(JavaProject.this);
+ }
+ manager.resetProjectOptions(JavaProject.this);
+ }
+ }
+ };
+ eclipsePreferences.addPreferenceChangeListener(preferenceListener);
+ return eclipsePreferences;
+ }
+
public String getElementName() {
return this.project.getName();
}
-
+
/**
* @see IJavaElement
*/
@@ -1407,39 +1444,18 @@
* This is a helper method returning the expanded 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.
* All project exports have been appended to project entries.
- * @param ignoreUnresolvedVariable boolean
* @return IClasspathEntry[]
* @throws JavaModelException
*/
- public IClasspathEntry[] getExpandedClasspath(boolean ignoreUnresolvedVariable) throws JavaModelException {
+ public IClasspathEntry[] getExpandedClasspath() throws JavaModelException {
- return getExpandedClasspath(ignoreUnresolvedVariable, false/*don't create markers*/, null, null);
- }
-
- /**
- * Internal variant which can create marker on project for invalid entries,
- * it will also perform classpath expansion in presence of project prerequisites
- * exporting their entries.
- * @param ignoreUnresolvedVariable boolean
- * @param generateMarkerOnError boolean
- * @param preferredClasspaths Map
- * @param preferredOutputs Map
- * @return IClasspathEntry[]
- * @throws JavaModelException
- */
- public IClasspathEntry[] getExpandedClasspath(
- boolean ignoreUnresolvedVariable,
- boolean generateMarkerOnError,
- Map preferredClasspaths,
- Map preferredOutputs) throws JavaModelException {
-
- ObjectVector accumulatedEntries = new ObjectVector();
- computeExpandedClasspath(null, ignoreUnresolvedVariable, generateMarkerOnError, new HashSet(5), accumulatedEntries, preferredClasspaths, preferredOutputs);
-
- IClasspathEntry[] expandedPath = new IClasspathEntry[accumulatedEntries.size()];
- accumulatedEntries.copyInto(expandedPath);
-
- return expandedPath;
+ ObjectVector accumulatedEntries = new ObjectVector();
+ computeExpandedClasspath(null, new HashSet(5), accumulatedEntries);
+
+ IClasspathEntry[] expandedPath = new IClasspathEntry[accumulatedEntries.size()];
+ accumulatedEntries.copyInto(expandedPath);
+
+ return expandedPath;
}
/**
@@ -1503,7 +1519,7 @@
}
return -1;
}
-
+
/**
* Convenience method that returns the specific type of info for a Java project.
*/
@@ -1520,7 +1536,7 @@
return ((JavaProjectElementInfo) getElementInfo()).getNonJavaResources(this);
}
-
+
/**
* @see org.eclipse.jdt.core.IJavaProject#getOption(String, boolean)
*/
@@ -1577,10 +1593,11 @@
// Inherit from JavaCore options if specified
if (inheritJavaCoreOptions) {
- Iterator propertyNames = projectOptions.keySet().iterator();
+ Iterator propertyNames = projectOptions.entrySet().iterator();
while (propertyNames.hasNext()) {
- String propertyName = (String) propertyNames.next();
- String propertyValue = (String) projectOptions.get(propertyName);
+ Map.Entry entry = (Map.Entry) propertyNames.next();
+ String propertyName = (String) entry.getKey();
+ String propertyValue = (String) entry.getValue();
if (propertyValue != null && optionNames.contains(propertyName)){
options.put(propertyName, propertyValue.trim());
}
@@ -1594,31 +1611,21 @@
* @see IJavaProject
*/
public IPath getOutputLocation() throws JavaModelException {
- // Do not create marker but log problems while getting output location
- return this.getOutputLocation(false, true);
- }
-
- /**
- * @param createMarkers boolean
- * @param logProblems boolean
- * @return IPath
- * @throws JavaModelException
- */
- public IPath getOutputLocation(boolean createMarkers, boolean logProblems) throws JavaModelException {
-
- JavaModelManager.PerProjectInfo perProjectInfo = getPerProjectInfo();
+ // Do not create marker while getting output location
+ JavaModelManager.PerProjectInfo perProjectInfo = this.getPerProjectInfo();
IPath outputLocation = perProjectInfo.outputLocation;
if (outputLocation != null) return outputLocation;
-
+
// force to read classpath - will position output location as well
- this.getRawClasspath(createMarkers, logProblems);
+ getRawClasspath();
+
outputLocation = perProjectInfo.outputLocation;
if (outputLocation == null) {
- return defaultOutputLocation();
+ return this.defaultOutputLocation();
}
return outputLocation;
}
-
+
/**
* @param path IPath
* @return A handle to the package fragment root identified by the given path.
@@ -1649,12 +1656,16 @@
return getPackageFragmentRoot(resource);
}
return getPackageFragmentRoot0(path);
+ } else if (segmentCount == 1) {
+ // lib being another project
+ return getPackageFragmentRoot(this.project.getWorkspace().getRoot().getProject(path.lastSegment()));
} else {
+ // lib being a folder
return getPackageFragmentRoot(this.project.getWorkspace().getRoot().getFolder(path));
}
}
}
-
+
/**
* @see IJavaProject
*/
@@ -1670,7 +1681,7 @@
case IResource.FOLDER:
return new PackageFragmentRoot(resource, this);
case IResource.PROJECT:
- return new PackageFragmentRoot(resource, this); //$NON-NLS-1$
+ return new PackageFragmentRoot(resource, this);
default:
return null;
}
@@ -1683,7 +1694,7 @@
return getPackageFragmentRoot0(JavaProject.canonicalizedPath(new Path(jarPath)));
}
-
+
/*
* no path canonicalization
*/
@@ -1719,27 +1730,7 @@
public IPackageFragmentRoot[] getPackageFragmentRoots(IClasspathEntry entry) {
return findPackageFragmentRoots(entry);
}
-
- /**
- * Returns the package fragment root prefixed by the given path, or
- * an empty collection if there are no such elements in the model.
- */
- protected IPackageFragmentRoot[] getPackageFragmentRoots(IPath path)
-
- throws JavaModelException {
- IPackageFragmentRoot[] roots = getAllPackageFragmentRoots();
- ArrayList matches = new ArrayList();
-
- for (int i = 0; i < roots.length; ++i) {
- if (path.isPrefixOf(roots[i].getPath())) {
- matches.add(roots[i]);
- }
- }
- IPackageFragmentRoot[] copy = new IPackageFragmentRoot[matches.size()];
- matches.toArray(copy);
- return copy;
- }
-
+
/**
* @see IJavaProject
*/
@@ -1772,22 +1763,22 @@
IPackageFragment[] fragments = new IPackageFragment[frags.size()];
frags.toArray(fragments);
return fragments;
- }
-
+ }
+
/**
* @see IJavaElement
*/
public IPath getPath() {
return this.project.getFullPath();
}
-
+
public JavaModelManager.PerProjectInfo getPerProjectInfo() throws JavaModelException {
return JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(this.project);
}
private IPath getPluginWorkingLocation() {
return this.project.getWorkingLocation(JavaCore.PLUGIN_ID);
- }
+ }
/**
* Returns the project custom preference pool.
@@ -1812,273 +1803,90 @@
*/
return new Preferences();
}
-
+
/**
* @see IJavaProject#getProject()
*/
public IProject getProject() {
return this.project;
}
+
+ public ProjectCache getProjectCache() throws JavaModelException {
+ return ((JavaProjectElementInfo) getElementInfo()).getProjectCache(this);
+ }
/**
* @see IJavaProject
*/
public IClasspathEntry[] getRawClasspath() throws JavaModelException {
- // Do not create marker but log problems while getting raw classpath
- return getRawClasspath(false, true);
- }
+ JavaModelManager.PerProjectInfo perProjectInfo = getPerProjectInfo();
+ IClasspathEntry[] classpath = perProjectInfo.rawClasspath;
+ if (classpath != null) return classpath;
+
+ classpath = perProjectInfo.readAndCacheClasspath(this);
- /*
- * Internal variant allowing to parameterize problem creation/logging
- */
- public IClasspathEntry[] getRawClasspath(boolean createMarkers, boolean logProblems) throws JavaModelException {
-
- JavaModelManager.PerProjectInfo perProjectInfo = null;
- IClasspathEntry[] classpath;
- if (createMarkers) {
- this.flushClasspathProblemMarkers(false/*cycle*/, true/*format*/);
- classpath = this.readClasspathFile(createMarkers, logProblems);
- } else {
- perProjectInfo = getPerProjectInfo();
- classpath = perProjectInfo.rawClasspath;
- if (classpath != null) return classpath;
- classpath = this.readClasspathFile(createMarkers, logProblems);
- }
- // extract out the output location
- IPath outputLocation = null;
- if (classpath != null && classpath.length > 0) {
- IClasspathEntry entry = classpath[classpath.length - 1];
- if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) {
- outputLocation = entry.getPath();
- IClasspathEntry[] copy = new IClasspathEntry[classpath.length - 1];
- System.arraycopy(classpath, 0, copy, 0, copy.length);
- classpath = copy;
- }
- }
- if (classpath == null) {
+ if (classpath == JavaProject.INVALID_CLASSPATH)
return defaultClasspath();
- }
- /* Disable validate: classpath can contain CP variables and container that need to be resolved
- if (classpath != INVALID_CLASSPATH
- && !JavaConventions.validateClasspath(this, classpath, outputLocation).isOK()) {
- classpath = INVALID_CLASSPATH;
- }
- */
- if (!createMarkers) {
- perProjectInfo.rawClasspath = classpath;
- perProjectInfo.outputLocation = outputLocation;
- }
+
return classpath;
}
+
/**
* @see IJavaProject#getRequiredProjectNames()
*/
public String[] getRequiredProjectNames() throws JavaModelException {
- return this.projectPrerequisites(getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/));
- }
-
- /**
- * @see IJavaProject
- */
- public IClasspathEntry[] getResolvedClasspath(boolean ignoreUnresolvedEntry)
- throws JavaModelException {
-
- return
- getResolvedClasspath(
- ignoreUnresolvedEntry,
- false, // don't generateMarkerOnError
- true // returnResolutionInProgress
- );
- }
-
- /**
- * @see IJavaProject
- */
- public IClasspathEntry[] getResolvedClasspath(boolean ignoreUnresolvedEntry, boolean generateMarkerOnError)
- throws JavaModelException {
-
- return
- getResolvedClasspath(
- ignoreUnresolvedEntry,
- generateMarkerOnError,
- true // returnResolutionInProgress
- );
- }
-
- /*
- * Internal variant which can create marker on project for invalid entries
- * and caches the resolved classpath on perProjectInfo.
- * If requested, return a special classpath (RESOLUTION_IN_PROGRESS) if the classpath is being resolved.
- */
- public IClasspathEntry[] getResolvedClasspath(
- boolean ignoreUnresolvedEntry,
- boolean generateMarkerOnError,
- boolean returnResolutionInProgress)
- throws JavaModelException {
-
- JavaModelManager manager = JavaModelManager.getJavaModelManager();
- JavaModelManager.PerProjectInfo perProjectInfo = null;
- if (ignoreUnresolvedEntry && !generateMarkerOnError) {
- perProjectInfo = getPerProjectInfo();
- if (perProjectInfo != null) {
- // resolved path is cached on its info
- IClasspathEntry[] infoPath = perProjectInfo.resolvedClasspath;
- if (infoPath != null) {
- return infoPath;
- } else if (returnResolutionInProgress && manager.isClasspathBeingResolved(this)) {
- if (JavaModelManager.CP_RESOLVE_VERBOSE) {
- Util.verbose(
- "CPResolution: reentering raw classpath resolution, will use empty classpath instead" + //$NON-NLS-1$
- " project: " + getElementName() + '\n' + //$NON-NLS-1$
- " invocation stack trace:"); //$NON-NLS-1$
- new Exception("<Fake exception>").printStackTrace(System.out); //$NON-NLS-1$
- }
- return RESOLUTION_IN_PROGRESS;
- }
- }
- }
- Map rawReverseMap = perProjectInfo == null ? null : new HashMap(5);
- IClasspathEntry[] resolvedPath = null;
- boolean nullOldResolvedCP = perProjectInfo != null && perProjectInfo.resolvedClasspath == null;
- try {
- // protect against misbehaving clients (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=61040)
- if (nullOldResolvedCP) manager.setClasspathBeingResolved(this, true);
- resolvedPath = getResolvedClasspath(
- getRawClasspath(generateMarkerOnError, !generateMarkerOnError),
- generateMarkerOnError ? getOutputLocation() : null,
- ignoreUnresolvedEntry,
- generateMarkerOnError,
- rawReverseMap);
- } finally {
- if (nullOldResolvedCP) perProjectInfo.resolvedClasspath = null;
- }
-
- if (perProjectInfo != null){
- if (perProjectInfo.rawClasspath == null // .classpath file could not be read
- && generateMarkerOnError
- && JavaProject.hasJavaNature(this.project)) {
- // flush .classpath format markers (bug 39877), but only when file cannot be read (bug 42366)
- this.flushClasspathProblemMarkers(false, true);
- this.createClasspathProblemMarker(new JavaModelStatus(
- IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
- Messages.bind(Messages.classpath_cannotReadClasspathFile, this.getElementName())));
- }
-
- perProjectInfo.resolvedClasspath = resolvedPath;
- perProjectInfo.resolvedPathToRawEntries = rawReverseMap;
- manager.setClasspathBeingResolved(this, false);
- }
- return resolvedPath;
+ return this.projectPrerequisites(getResolvedClasspath());
}
- /**
- * Internal variant which can process any arbitrary classpath
- * @param classpathEntries IClasspathEntry[]
- * @param projectOutputLocation IPath
- * @param ignoreUnresolvedEntry boolean
- * @param generateMarkerOnError boolean
- * @param rawReverseMap Map
- * @return IClasspathEntry[]
- * @throws JavaModelException
+ /*
+ * Returns the cached resolved classpath, or compute it ignoring unresolved entries and cache it.
*/
- public IClasspathEntry[] getResolvedClasspath(
- IClasspathEntry[] classpathEntries,
- IPath projectOutputLocation, // only set if needing full classpath validation (and markers)
- boolean ignoreUnresolvedEntry, // if unresolved entries are met, should it trigger initializations
- boolean generateMarkerOnError,
- Map rawReverseMap) // can be null if not interested in reverse mapping
- throws JavaModelException {
+ public IClasspathEntry[] getResolvedClasspath() throws JavaModelException {
+ PerProjectInfo perProjectInfo = getPerProjectInfo();
+ if (perProjectInfo.resolvedClasspath == null)
+ resolveClasspath(perProjectInfo);
+ return perProjectInfo.resolvedClasspath;
+ }
- IJavaModelStatus status;
- if (generateMarkerOnError){
- flushClasspathProblemMarkers(false, false);
+ /**
+ * @see IJavaProject
+ */
+ public IClasspathEntry[] getResolvedClasspath(boolean ignoreUnresolvedEntry) throws JavaModelException {
+ if (JavaModelManager.getJavaModelManager().isClasspathBeingResolved(this)) {
+ if (JavaModelManager.CP_RESOLVE_VERBOSE_ADVANCED)
+ verbose_reentering_classpath_resolution();
+ return RESOLUTION_IN_PROGRESS;
}
+ PerProjectInfo perProjectInfo = getPerProjectInfo();
- int length = classpathEntries.length;
- ArrayList resolvedEntries = new ArrayList();
+ // use synchronized block to ensure consistency
+ IClasspathEntry[] resolvedClasspath;
+ IJavaModelStatus unresolvedEntryStatus;
+ synchronized (perProjectInfo) {
+ resolvedClasspath = perProjectInfo.resolvedClasspath;
+ unresolvedEntryStatus = perProjectInfo.unresolvedEntryStatus;
+ }
- for (int i = 0; i < length; i++) {
-
- IClasspathEntry rawEntry = classpathEntries[i];
- IPath resolvedPath;
- status = null;
-
- /* validation if needed */
- if (generateMarkerOnError || !ignoreUnresolvedEntry) {
- status = ClasspathEntry.validateClasspathEntry(this, rawEntry, false /*ignore src attach*/, false /*do not recurse in containers, done later to accumulate*/);
- if (generateMarkerOnError && !status.isOK()) createClasspathProblemMarker(status);
+ if (resolvedClasspath == null
+ || (unresolvedEntryStatus != null && !unresolvedEntryStatus.isOK())) { // force resolution to ensure initializers are run again
+ resolveClasspath(perProjectInfo);
+ synchronized (perProjectInfo) {
+ resolvedClasspath = perProjectInfo.resolvedClasspath;
+ unresolvedEntryStatus = perProjectInfo.unresolvedEntryStatus;
}
-
- switch (rawEntry.getEntryKind()){
-
- case IClasspathEntry.CPE_VARIABLE :
-
- IClasspathEntry resolvedEntry = null;
- try {
- resolvedEntry = JavaCore.getResolvedClasspathEntry(rawEntry);
- } catch (Assert.AssertionFailedException e) {
- // Catch the assertion failure and throw java model exception instead
- // see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=55992
- // if ignoredUnresolvedEntry is false, status is set by by ClasspathEntry.validateClasspathEntry
- // called above as validation was needed
- if (!ignoreUnresolvedEntry) throw new JavaModelException(status);
- }
- if (resolvedEntry == null) {
- if (!ignoreUnresolvedEntry) throw new JavaModelException(status);
- } else {
- if (rawReverseMap != null) {
- if (rawReverseMap.get(resolvedPath = resolvedEntry.getPath()) == null) rawReverseMap.put(resolvedPath , rawEntry);
- }
- resolvedEntries.add(resolvedEntry);
- }
- break;
-
- case IClasspathEntry.CPE_CONTAINER :
-
- IClasspathContainer container = JavaCore.getClasspathContainer(rawEntry.getPath(), this);
- if (container == null){
- if (!ignoreUnresolvedEntry) throw new JavaModelException(status);
- break;
- }
-
- IClasspathEntry[] containerEntries = container.getClasspathEntries();
- if (containerEntries == null) break;
-
- // container was bound
- for (int j = 0, containerLength = containerEntries.length; j < containerLength; j++){
- ClasspathEntry cEntry = (ClasspathEntry) containerEntries[j];
- if (generateMarkerOnError) {
- IJavaModelStatus containerStatus = ClasspathEntry.validateClasspathEntry(this, cEntry, false, true /*recurse*/);
- if (!containerStatus.isOK()) createClasspathProblemMarker(containerStatus);
- }
- // if container is exported or restricted, then its nested entries must in turn be exported (21749) and/or propagate restrictions
- cEntry = cEntry.combineWith((ClasspathEntry) rawEntry);
- if (rawReverseMap != null) {
- if (rawReverseMap.get(resolvedPath = cEntry.getPath()) == null) rawReverseMap.put(resolvedPath , rawEntry);
- }
- resolvedEntries.add(cEntry);
- }
- break;
-
- default :
-
- if (rawReverseMap != null) {
- if (rawReverseMap.get(resolvedPath = rawEntry.getPath()) == null) rawReverseMap.put(resolvedPath , rawEntry);
- }
- resolvedEntries.add(rawEntry);
-
- }
}
+ if (!ignoreUnresolvedEntry && unresolvedEntryStatus != null && !unresolvedEntryStatus.isOK())
+ throw new JavaModelException(unresolvedEntryStatus);
+ return resolvedClasspath;
+ }
- IClasspathEntry[] resolvedPath = new IClasspathEntry[resolvedEntries.size()];
- resolvedEntries.toArray(resolvedPath);
-
- if (generateMarkerOnError && projectOutputLocation != null) {
- status = ClasspathEntry.validateClasspath(this, resolvedPath, projectOutputLocation);
- if (!status.isOK()) createClasspathProblemMarker(status);
- }
- return resolvedPath;
+ private void verbose_reentering_classpath_resolution() {
+ Util.verbose(
+ "CPResolution: reentering raw classpath resolution, will use empty classpath instead" + //$NON-NLS-1$
+ " project: " + getElementName() + '\n' + //$NON-NLS-1$
+ " invocation stack trace:"); //$NON-NLS-1$
+ new Exception("<Fake exception>").printStackTrace(System.out); //$NON-NLS-1$
}
/**
@@ -2106,7 +1914,7 @@
if (rscFile.exists()) {
byte[] bytes = Util.getResourceContentsAsByteArray(rscFile);
try {
- property = new String(bytes, "UTF-8"); //$NON-NLS-1$ // .classpath always encoded with UTF-8
+ property = new String(bytes, org.eclipse.jdt.internal.compiler.util.Util.UTF_8); // .classpath always encoded with UTF-8
} catch (UnsupportedEncodingException e) {
Util.log(e, "Could not read .classpath with UTF-8 encoding"); //$NON-NLS-1$
// fallback to default
@@ -2116,26 +1924,29 @@
// when a project is imported, we get a first delta for the addition of the .project, but the .classpath is not accessible
// so default to using java.io.File
// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=96258
- File file = rscFile.getLocation().toFile();
- if (file.exists()) {
- byte[] bytes;
- try {
- bytes = org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(file);
- } catch (IOException e) {
- return null;
- }
- try {
- property = new String(bytes, "UTF-8"); //$NON-NLS-1$ // .classpath always encoded with UTF-8
- } catch (UnsupportedEncodingException e) {
- Util.log(e, "Could not read .classpath with UTF-8 encoding"); //$NON-NLS-1$
- // fallback to default
- property = new String(bytes);
+ URI location = rscFile.getLocationURI();
+ if (location != null) {
+ File file = Util.toLocalFile(location, null/*no progress monitor available*/);
+ if (file != null && file.exists()) {
+ byte[] bytes;
+ try {
+ bytes = org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(file);
+ } catch (IOException e) {
+ return null;
+ }
+ try {
+ property = new String(bytes, org.eclipse.jdt.internal.compiler.util.Util.UTF_8); // .classpath always encoded with UTF-8
+ } catch (UnsupportedEncodingException e) {
+ Util.log(e, "Could not read .classpath with UTF-8 encoding"); //$NON-NLS-1$
+ // fallback to default
+ property = new String(bytes);
+ }
}
}
}
return property;
}
-
+
/**
* @see JavaElement
*/
@@ -2143,7 +1954,7 @@
return null;
}
-
+
/**
* @see IJavaElement
*/
@@ -2159,7 +1970,7 @@
return JavaModelManager.getJavaModelManager().getLastBuiltState(this.project, null) != null;
}
-
+
/**
* @see IJavaProject
*/
@@ -2170,15 +1981,15 @@
updateCycleParticipants(new ArrayList(2), cycleParticipants, ResourcesPlugin.getWorkspace().getRoot(), new HashSet(2), preferredClasspaths);
return !cycleParticipants.isEmpty();
}
-
+
public boolean hasCycleMarker(){
return this.getCycleMarker() != null;
}
-
+
public int hashCode() {
return this.project.hashCode();
}
-
+
/**
* Answers true if the project potentially contains any source. A project which has no source is immutable.
* @return boolean
@@ -2200,38 +2011,6 @@
}
return false;
}
-
- /**
- * Compare current classpath with given one to see if any different.
- * Note that the argument classpath contains its binary output.
- * @param newClasspath IClasspathEntry[]
- * @param newOutputLocation IPath
- * @param otherClasspathWithOutput IClasspathEntry[]
- * @return boolean
- */
- public boolean isClasspathEqualsTo(IClasspathEntry[] newClasspath, IPath newOutputLocation, IClasspathEntry[] otherClasspathWithOutput) {
-
- if (otherClasspathWithOutput == null || otherClasspathWithOutput.length == 0)
- return false;
-
- int length = otherClasspathWithOutput.length;
- if (length != newClasspath.length + 1)
- // output is amongst file entries (last one)
- return false;
-
-
- // compare classpath entries
- for (int i = 0; i < length - 1; i++) {
- if (!otherClasspathWithOutput[i].equals(newClasspath[i]))
- return false;
- }
- // compare binary outputs
- IClasspathEntry output = otherClasspathWithOutput[length - 1];
- if (output.getContentKind() != ClasspathEntry.K_OUTPUT
- || !output.getPath().equals(newOutputLocation))
- return false;
- return true;
- }
@@ -2307,6 +2086,12 @@
// container was bound
for (int j = 0, containerLength = containerEntries.length; j < containerLength; j++){
IClasspathEntry resolvedEntry = containerEntries[j];
+ if (resolvedEntry == null) {
+ if (JavaModelManager.CP_RESOLVE_VERBOSE) {
+ JavaModelManager.getJavaModelManager().verbose_missbehaving_container(this, rawEntry.getPath(), containerEntries);
+ }
+ return false;
+ }
if (isOnClasspathEntry(elementPath, isFolderPath, isPackageFragmentRoot, resolvedEntry))
return true;
}
@@ -2324,20 +2109,6 @@
return false;
}
- private boolean isOnClasspathEntry(IPath elementPath, boolean isFolderPath, boolean isPackageFragmentRoot, IClasspathEntry entry) {
- IPath entryPath = entry.getPath();
- if (isPackageFragmentRoot) {
- // package fragment roots must match exactly entry pathes (no exclusion there)
- if (entryPath.equals(elementPath))
- return true;
- } else {
- if (entryPath.isPrefixOf(elementPath)
- && !Util.isExcluded(elementPath, ((ClasspathEntry)entry).fullInclusionPatternChars(), ((ClasspathEntry)entry).fullExclusionPatternChars(), isFolderPath))
- return true;
- }
- return false;
- }
-
/*
* @see IJavaProject
*/
@@ -2346,11 +2117,12 @@
IPath path = exactPath;
// ensure that folders are only excluded if all of their children are excluded
- boolean isFolderPath = resource.getType() == IResource.FOLDER;
+ int resourceType = resource.getType();
+ boolean isFolderPath = resourceType == IResource.FOLDER || resourceType == IResource.PROJECT;
IClasspathEntry[] classpath;
try {
- classpath = this.getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/);
+ classpath = this.getResolvedClasspath();
} catch(JavaModelException e){
return false; // not a Java project
}
@@ -2368,14 +2140,24 @@
return false;
}
+ private boolean isOnClasspathEntry(IPath elementPath, boolean isFolderPath, boolean isPackageFragmentRoot, IClasspathEntry entry) {
+ IPath entryPath = entry.getPath();
+ if (isPackageFragmentRoot) {
+ // package fragment roots must match exactly entry pathes (no exclusion there)
+ if (entryPath.equals(elementPath))
+ return true;
+ } else {
+ if (entryPath.isPrefixOf(elementPath)
+ && !Util.isExcluded(elementPath, ((ClasspathEntry)entry).fullInclusionPatternChars(), ((ClasspathEntry)entry).fullExclusionPatternChars(), isFolderPath))
+ return true;
+ }
+ return false;
+ }
+
/**
* load preferences from a shareable format (VCM-wise)
- * @deprecated WARNING, visibility of this method will be decreased soon
- * to private and won't be usable in the future.
- * @see <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=59258">bug 59258</a>
- * TODO (frederic) set visibility from public to private
*/
- public Preferences loadPreferences() {
+ private Preferences loadPreferences() {
Preferences preferences = new Preferences();
IPath projectMetaLocation = getPluginWorkingLocation();
@@ -2513,7 +2295,7 @@
ArrayList prerequisites = new ArrayList();
// need resolution
- entries = getResolvedClasspath(entries, null, true, false, null/*no reverse map*/);
+ entries = resolveClasspath(entries);
for (int i = 0, length = entries.length; i < length; i++) {
IClasspathEntry entry = entries[i];
if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) {
@@ -2530,51 +2312,85 @@
}
}
-
- /**
- * Reads the .classpath file from disk and returns the list of entries it contains (including output location entry)
- * Returns null if .classfile is not present.
- * Returns INVALID_CLASSPATH if it has a format problem.
+ /*
+ * Reads the classpath file entries of this project's .classpath file.
+ * This includes the output entry.
+ * As a side effect, unknown elements are stored in the given map (if not null)
+ * Throws exceptions if the file cannot be accessed or is malformed.
*/
- protected IClasspathEntry[] readClasspathFile(boolean createMarker, boolean logProblems) {
-
- try {
- String xmlClasspath = getSharedProperty(CLASSPATH_FILENAME);
- if (xmlClasspath == null) {
- if (createMarker && this.project.isAccessible()) {
- this.createClasspathProblemMarker(new JavaModelStatus(
- IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
- Messages.bind(Messages.classpath_cannotReadClasspathFile, this.getElementName())));
- }
- return null;
+ public IClasspathEntry[] readFileEntriesWithException(Map unknownElements) throws CoreException, IOException, AssertionFailedException {
+ String xmlClasspath;
+ IFile rscFile = this.project.getFile(JavaProject.CLASSPATH_FILENAME);
+ if (rscFile.exists()) {
+ byte[] bytes = Util.getResourceContentsAsByteArray(rscFile);
+ try {
+ xmlClasspath = new String(bytes, org.eclipse.jdt.internal.compiler.util.Util.UTF_8); // .classpath always encoded with UTF-8
+ } catch (UnsupportedEncodingException e) {
+ Util.log(e, "Could not read .classpath with UTF-8 encoding"); //$NON-NLS-1$
+ // fallback to default
+ xmlClasspath = new String(bytes);
}
- return decodeClasspath(xmlClasspath, createMarker, logProblems);
- } catch(CoreException e) {
- // file does not exist (or not accessible)
- if (createMarker && this.project.isAccessible()) {
- this.createClasspathProblemMarker(new JavaModelStatus(
- IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
- Messages.bind(Messages.classpath_cannotReadClasspathFile, this.getElementName())));
+ } else {
+ // when a project is imported, we get a first delta for the addition of the .project, but the .classpath is not accessible
+ // so default to using java.io.File
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=96258
+ URI location = rscFile.getLocationURI();
+ if (location == null)
+ throw new IOException("Cannot obtain a location URI for " + rscFile); //$NON-NLS-1$
+ File file = Util.toLocalFile(location, null/*no progress monitor available*/);
+ if (file == null)
+ throw new IOException("Unable to fetch file from " + location); //$NON-NLS-1$
+ byte[] bytes;
+ try {
+ bytes = org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(file);
+ } catch (IOException e) {
+ if (!file.exists())
+ return defaultClasspath();
+ throw e;
}
- if (logProblems) {
- Util.log(e,
- "Exception while retrieving "+ this.getPath() //$NON-NLS-1$
- +"/.classpath, will revert to default classpath"); //$NON-NLS-1$
+ try {
+ xmlClasspath = new String(bytes, org.eclipse.jdt.internal.compiler.util.Util.UTF_8); // .classpath always encoded with UTF-8
+ } catch (UnsupportedEncodingException e) {
+ Util.log(e, "Could not read .classpath with UTF-8 encoding"); //$NON-NLS-1$
+ // fallback to default
+ xmlClasspath = new String(bytes);
}
}
- return null;
+ return decodeClasspath(xmlClasspath, unknownElements);
+ }
+
+ /*
+ * Reads the classpath file entries of this project's .classpath file.
+ * This includes the output entry.
+ * As a side effect, unknown elements are stored in the given map (if not null)
+ */
+ private IClasspathEntry[] readFileEntries(Map unkwownElements) {
+ try {
+ return readFileEntriesWithException(unkwownElements);
+ } catch (CoreException e) {
+ Util.log(e, "Exception while reading " + getPath().append(JavaProject.CLASSPATH_FILENAME)); //$NON-NLS-1$
+ return JavaProject.INVALID_CLASSPATH;
+ } catch (IOException e) {
+ Util.log(e, "Exception while reading " + getPath().append(JavaProject.CLASSPATH_FILENAME)); //$NON-NLS-1$
+ return JavaProject.INVALID_CLASSPATH;
+ } catch (AssertionFailedException e) {
+ Util.log(e, "Exception while reading " + getPath().append(JavaProject.CLASSPATH_FILENAME)); //$NON-NLS-1$
+ return JavaProject.INVALID_CLASSPATH;
+ }
}
/**
* @see IJavaProject
*/
public IPath readOutputLocation() {
-
// Read classpath file without creating markers nor logging problems
- IClasspathEntry[] classpath = this.readClasspathFile(false, false);
+ IClasspathEntry[] classpath = readFileEntries(null/*not interested in unknown elements*/);
+ if (classpath == JavaProject.INVALID_CLASSPATH)
+ return defaultOutputLocation();
+
// extract the output location
IPath outputLocation = null;
- if (classpath != null && classpath.length > 0) {
+ if (classpath.length > 0) {
IClasspathEntry entry = classpath[classpath.length - 1];
if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) {
outputLocation = entry.getPath();
@@ -2582,16 +2398,18 @@
}
return outputLocation;
}
-
+
/**
* @see IJavaProject
*/
public IClasspathEntry[] readRawClasspath() {
-
// Read classpath file without creating markers nor logging problems
- IClasspathEntry[] classpath = this.readClasspathFile(false, false);
+ IClasspathEntry[] classpath = readFileEntries(null/*not interested in unknown elements*/);
+ if (classpath == JavaProject.INVALID_CLASSPATH)
+ return defaultClasspath();
+
// discard the output location
- if (classpath != null && classpath.length > 0) {
+ if (classpath.length > 0) {
IClasspathEntry entry = classpath[classpath.length - 1];
if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) {
IClasspathEntry[] copy = new IClasspathEntry[classpath.length - 1];
@@ -2631,6 +2449,159 @@
}
}
+ /*
+ * Resolve the given raw classpath.
+ */
+ public IClasspathEntry[] resolveClasspath(IClasspathEntry[] rawClasspath) throws JavaModelException {
+ ArrayList resolvedEntries = new ArrayList();
+ for (int i = 0, length = rawClasspath.length; i < length; i++) {
+ IClasspathEntry rawEntry = rawClasspath[i];
+ switch (rawEntry.getEntryKind()){
+ case IClasspathEntry.CPE_VARIABLE:
+ IClasspathEntry resolvedEntry = null;
+ try {
+ resolvedEntry = JavaCore.getResolvedClasspathEntry(rawEntry);
+ } catch (AssertionFailedException e) {
+ // Catch the assertion failure
+ // see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=55992
+ break;
+ }
+ if (resolvedEntry != null)
+ resolvedEntries.add(resolvedEntry);
+ break;
+ case IClasspathEntry.CPE_CONTAINER:
+ IClasspathContainer container = JavaCore.getClasspathContainer(rawEntry.getPath(), this);
+ if (container == null)
+ break;
+ IClasspathEntry[] containerEntries = container.getClasspathEntries();
+ if (containerEntries == null)
+ break;
+
+ // container was bound
+ for (int j = 0, containerLength = containerEntries.length; j < containerLength; j++){
+ ClasspathEntry cEntry = (ClasspathEntry) containerEntries[j];
+ if (cEntry == null) {
+ if (JavaModelManager.CP_RESOLVE_VERBOSE) {
+ JavaModelManager.getJavaModelManager().verbose_missbehaving_container(this, rawEntry.getPath(), containerEntries);
+ }
+ break;
+ }
+ // if container is exported or restricted, then its nested entries must in turn be exported (21749) and/or propagate restrictions
+ cEntry = cEntry.combineWith((ClasspathEntry) rawEntry);
+ resolvedEntries.add(cEntry);
+ }
+ break;
+ default:
+ resolvedEntries.add(rawEntry);
+ }
+ }
+ IClasspathEntry[] result = new IClasspathEntry[resolvedEntries.size()];
+ resolvedEntries.toArray(result);
+ return result;
+ }
+
+ /*
+ * Resolve the given perProjectInfo's raw classpath and store the resolved classpath in the perProjectInfo.
+ */
+ public void resolveClasspath(PerProjectInfo perProjectInfo) throws JavaModelException {
+ JavaModelManager manager = JavaModelManager.getJavaModelManager();
+ try {
+ manager.setClasspathBeingResolved(this, true);
+
+ // get raw info inside a synchronized block to ensure that it is consistent
+ IClasspathEntry[] rawClasspath;
+ IPath outputLocation;
+ IJavaModelStatus rawClasspathStatus;
+ synchronized (perProjectInfo) {
+ rawClasspath= perProjectInfo.rawClasspath;
+ if (rawClasspath == null)
+ rawClasspath = perProjectInfo.readAndCacheClasspath(this);
+ outputLocation = perProjectInfo.outputLocation;
+ rawClasspathStatus = perProjectInfo.rawClasspathStatus;
+ }
+
+ IJavaModelStatus unresolvedEntryStatus = JavaModelStatus.VERIFIED_OK;
+ HashMap rawReverseMap = new HashMap();
+ Map rootPathToResolvedEntries = new HashMap();
+
+ ArrayList resolvedEntries = new ArrayList();
+ int length = rawClasspath.length;
+ for (int i = 0; i < length; i++) {
+
+ IClasspathEntry rawEntry = rawClasspath[i];
+ IPath resolvedPath;
+
+ switch (rawEntry.getEntryKind()){
+
+ case IClasspathEntry.CPE_VARIABLE :
+ IClasspathEntry resolvedEntry = null;
+ try {
+ resolvedEntry = JavaCore.getResolvedClasspathEntry(rawEntry);
+ } catch (AssertionFailedException e) {
+ // Catch the assertion failure and set ststus instead
+ // see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=55992
+ unresolvedEntryStatus = new JavaModelStatus(IJavaModelStatusConstants.INVALID_PATH, e.getMessage());
+ break;
+ }
+ if (resolvedEntry == null) {
+ unresolvedEntryStatus = new JavaModelStatus(IJavaModelStatusConstants.CP_VARIABLE_PATH_UNBOUND, this, rawEntry.getPath());
+ } else {
+ if (rawReverseMap.get(resolvedPath = resolvedEntry.getPath()) == null) {
+ rawReverseMap.put(resolvedPath , rawEntry);
+ rootPathToResolvedEntries.put(resolvedPath, resolvedEntry);
+ }
+ resolvedEntries.add(resolvedEntry);
+ }
+ break;
+
+ case IClasspathEntry.CPE_CONTAINER :
+ IClasspathContainer container = JavaCore.getClasspathContainer(rawEntry.getPath(), this);
+ if (container == null){
+ unresolvedEntryStatus = new JavaModelStatus(IJavaModelStatusConstants.CP_CONTAINER_PATH_UNBOUND, this, rawEntry.getPath());
+ break;
+ }
+
+ IClasspathEntry[] containerEntries = container.getClasspathEntries();
+ if (containerEntries == null) break;
+
+ // container was bound
+ for (int j = 0, containerLength = containerEntries.length; j < containerLength; j++){
+ ClasspathEntry cEntry = (ClasspathEntry) containerEntries[j];
+ if (cEntry == null) {
+ if (JavaModelManager.CP_RESOLVE_VERBOSE) {
+ JavaModelManager.getJavaModelManager().verbose_missbehaving_container(this, rawEntry.getPath(), containerEntries);
+ }
+ break;
+ }
+ // if container is exported or restricted, then its nested entries must in turn be exported (21749) and/or propagate restrictions
+ cEntry = cEntry.combineWith((ClasspathEntry) rawEntry);
+ if (rawReverseMap.get(resolvedPath = cEntry.getPath()) == null) {
+ rawReverseMap.put(resolvedPath , rawEntry);
+ rootPathToResolvedEntries.put(resolvedPath, cEntry);
+ }
+ resolvedEntries.add(cEntry);
+ }
+ break;
+
+ default :
+ if (rawReverseMap.get(resolvedPath = rawEntry.getPath()) == null) {
+ rawReverseMap.put(resolvedPath , rawEntry);
+ rootPathToResolvedEntries.put(resolvedPath, rawEntry);
+ }
+ resolvedEntries.add(rawEntry);
+
+ }
+ }
+
+ // store resolved info along with the raw info to ensure consistency
+ IClasspathEntry[] resolvedClasspath = new IClasspathEntry[resolvedEntries.size()];
+ resolvedEntries.toArray(resolvedClasspath);
+ perProjectInfo.setClasspath(rawClasspath, outputLocation, rawClasspathStatus, resolvedClasspath, rawReverseMap, rootPathToResolvedEntries, unresolvedEntryStatus);
+ } finally {
+ manager.setClasspathBeingResolved(this, false);
+ }
+ }
+
/**
* Answers an ID which is used to distinguish project/entries during package
* fragment root computations
@@ -2639,7 +2610,7 @@
public String rootID(){
return "[PRJ]"+this.project.getFullPath(); //$NON-NLS-1$
}
-
+
/**
* Saves the classpath in a shareable format (VCM-wise) only when necessary, that is, if it is semantically different
* from the existing one in file. Will never write an identical one.
@@ -2653,15 +2624,16 @@
if (!this.project.isAccessible()) return false;
- IClasspathEntry[] fileEntries = readClasspathFile(false /*don't create markers*/, false/*don't log problems*/);
- if (fileEntries != null && isClasspathEqualsTo(newClasspath, newOutputLocation, fileEntries)) {
+ Map unknownElements = new HashMap();
+ IClasspathEntry[] fileEntries = readFileEntries(unknownElements);
+ if (fileEntries != JavaProject.INVALID_CLASSPATH && areClasspathsEqual(newClasspath, newOutputLocation, fileEntries)) {
// no need to save it, it is the same
return false;
}
// actual file saving
try {
- setSharedProperty(CLASSPATH_FILENAME, encodeClasspath(newClasspath, newOutputLocation, true));
+ setSharedProperty(JavaProject.CLASSPATH_FILENAME, encodeClasspath(newClasspath, newOutputLocation, true, unknownElements));
return true;
} catch (CoreException e) {
throw new JavaModelException(e);
@@ -2701,15 +2673,21 @@
*/
public void setOption(String optionName, String optionValue) {
if (!JavaModelManager.getJavaModelManager().optionNames.contains(optionName)) return; // unrecognized option
+ if (optionValue == null) return; // invalid value
IEclipsePreferences projectPreferences = getEclipsePreferences();
String defaultValue = JavaCore.getOption(optionName);
- if (defaultValue == null || !defaultValue.equals(optionValue)) {
+ if (optionValue.equals(defaultValue)) {
+ // set default value => remove preference
+ projectPreferences.remove(optionName);
+ } else {
projectPreferences.put(optionName, optionValue);
- try {
- projectPreferences.flush();
- } catch (BackingStoreException e) {
- // problem with pref store - quietly ignore
- }
+ }
+
+ // Dump changes
+ try {
+ projectPreferences.flush();
+ } catch (BackingStoreException e) {
+ // problem with pref store - quietly ignore
}
}
@@ -2723,13 +2701,13 @@
if (newOptions == null){
projectPreferences.clear();
} else {
- Iterator keys = newOptions.keySet().iterator();
- while (keys.hasNext()){
- String key = (String)keys.next();
+ Iterator entries = newOptions.entrySet().iterator();
+ while (entries.hasNext()){
+ Map.Entry entry = (Map.Entry) entries.next();
+ String key = (String) entry.getKey();
if (!JavaModelManager.getJavaModelManager().optionNames.contains(key)) continue; // unrecognized option
// no filtering for encoding (custom encoding for project is allowed)
- String value = (String)newOptions.get(key);
- projectPreferences.put(key, value);
+ projectPreferences.put(key, (String) entry.getValue());
}
// reset to default all options not in new map
@@ -2758,20 +2736,17 @@
// problem with pref store - quietly ignore
}
}
-
/**
* @see IJavaProject
*/
- public void setOutputLocation(IPath path, IProgressMonitor monitor)
- throws JavaModelException {
-
+ public void setOutputLocation(IPath path, IProgressMonitor monitor) throws JavaModelException {
if (path == null) {
throw new IllegalArgumentException(Messages.path_nullPath);
}
if (path.equals(getOutputLocation())) {
return;
}
- this.setRawClasspath(SetClasspathOperation.DO_NOT_SET_ENTRIES, path, monitor);
+ setRawClasspath(getRawClasspath(), path, monitor);
}
/**
@@ -2788,6 +2763,49 @@
}
/**
+ * @see IJavaProject#setRawClasspath(IClasspathEntry[],boolean,IProgressMonitor)
+ */
+ public void setRawClasspath(
+ IClasspathEntry[] entries,
+ boolean canModifyResources,
+ IProgressMonitor monitor)
+ throws JavaModelException {
+
+ setRawClasspath(
+ entries,
+ getOutputLocation()/*don't change output*/,
+ canModifyResources,
+ monitor);
+ }
+
+ /**
+ * @see IJavaProject#setRawClasspath(IClasspathEntry[],IPath,boolean,IProgressMonitor)
+ */
+ public void setRawClasspath(
+ IClasspathEntry[] newRawClasspath,
+ IPath newOutputLocation,
+ boolean canModifyResources,
+ IProgressMonitor monitor)
+ throws JavaModelException {
+
+ try {
+ if (newRawClasspath == null) //are we already with the default classpath
+ newRawClasspath = defaultClasspath();
+
+ SetClasspathOperation op =
+ new SetClasspathOperation(
+ this,
+ newRawClasspath,
+ newOutputLocation,
+ canModifyResources);
+ op.runOperation(monitor);
+ } catch (JavaModelException e) {
+ JavaModelManager.getJavaModelManager().getDeltaProcessor().flush();
+ throw e;
+ }
+ }
+
+ /**
* @see IJavaProject#setRawClasspath(IClasspathEntry[],IPath,IProgressMonitor)
*/
public void setRawClasspath(
@@ -2799,46 +2817,10 @@
setRawClasspath(
entries,
outputLocation,
- monitor,
- true, // canChangeResource (as per API contract)
- getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/),
- true, // needValidation
- true); // need to save
+ true/*can change resource (as per API contract)*/,
+ monitor);
}
-
- public void setRawClasspath(
- IClasspathEntry[] newEntries,
- IPath newOutputLocation,
- IProgressMonitor monitor,
- boolean canChangeResource,
- IClasspathEntry[] oldResolvedPath,
- boolean needValidation,
- boolean needSave)
- throws JavaModelException {
-
- JavaModelManager manager = JavaModelManager.getJavaModelManager();
- try {
- IClasspathEntry[] newRawPath = newEntries;
- if (newRawPath == null) { //are we already with the default classpath
- newRawPath = defaultClasspath();
- }
- SetClasspathOperation op =
- new SetClasspathOperation(
- this,
- oldResolvedPath,
- newRawPath,
- newOutputLocation,
- canChangeResource,
- needValidation,
- needSave);
- op.runOperation(monitor);
-
- } catch (JavaModelException e) {
- manager.getDeltaProcessor().flush();
- throw e;
- }
- }
-
+
/**
* @see IJavaProject
*/
@@ -2849,12 +2831,9 @@
setRawClasspath(
entries,
- SetClasspathOperation.DO_NOT_SET_OUTPUT,
- monitor,
- true, // canChangeResource (as per API contract)
- getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/),
- true, // needValidation
- true); // need to save
+ getOutputLocation()/*don't change output*/,
+ true/*can change resource (as per API contract)*/,
+ monitor);
}
/**
@@ -2876,7 +2855,7 @@
IFile rscFile = this.project.getFile(key);
byte[] bytes = null;
try {
- bytes = value.getBytes("UTF-8"); //$NON-NLS-1$ // .classpath always encoded with UTF-8
+ bytes = value.getBytes(org.eclipse.jdt.internal.compiler.util.Util.UTF_8); // .classpath always encoded with UTF-8
} catch (UnsupportedEncodingException e) {
Util.log(e, "Could not write .classpath with UTF-8 encoding "); //$NON-NLS-1$
// fallback to default
@@ -2894,45 +2873,6 @@
rscFile.create(inputStream, IResource.FORCE, null);
}
}
-
- /*
- * Update .classpath format markers.
- */
- public void updateClasspathMarkers(Map preferredClasspaths, Map preferredOutputs) {
-
- this.flushClasspathProblemMarkers(false/*cycle*/, true/*format*/);
- this.flushClasspathProblemMarkers(false/*cycle*/, false/*format*/);
-
- IClasspathEntry[] classpath = this.readClasspathFile(true/*marker*/, false/*log*/);
- IPath output = null;
- // discard the output location
- if (classpath != null && classpath.length > 0) {
- IClasspathEntry entry = classpath[classpath.length - 1];
- if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) {
- IClasspathEntry[] copy = new IClasspathEntry[classpath.length - 1];
- System.arraycopy(classpath, 0, copy, 0, copy.length);
- classpath = copy;
- output = entry.getPath();
- }
- }
- // remember invalid path so as to avoid reupdating it again later on
- if (preferredClasspaths != null) {
- preferredClasspaths.put(this, classpath == null ? INVALID_CLASSPATH : classpath);
- }
- if (preferredOutputs != null) {
- preferredOutputs.put(this, output == null ? defaultOutputLocation() : output);
- }
-
- // force classpath marker refresh
- if (classpath != null && output != null) {
- for (int i = 0; i < classpath.length; i++) {
- IJavaModelStatus status = ClasspathEntry.validateClasspathEntry(this, classpath[i], false/*src attach*/, true /*recurse in container*/);
- if (!status.isOK()) this.createClasspathProblemMarker(status);
- }
- IJavaModelStatus status = ClasspathEntry.validateClasspath(this, classpath, output);
- if (!status.isOK()) this.createClasspathProblemMarker(status);
- }
- }
/**
* If a cycle is detected, then cycleParticipants contains all the paths of projects involved in this cycle (directly and indirectly),
@@ -2956,7 +2896,7 @@
try {
IClasspathEntry[] classpath = null;
if (preferredClasspaths != null) classpath = (IClasspathEntry[])preferredClasspaths.get(this);
- if (classpath == null) classpath = getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/);
+ if (classpath == null) classpath = getResolvedClasspath();
for (int i = 0, length = classpath.length; i < length; i++) {
IClasspathEntry entry = classpath[i];
@@ -2983,7 +2923,7 @@
}
prereqChain.remove(path);
}
-
+
/**
* Reset the collection of package fragment roots (local ones) - only if opened.
*/
@@ -3020,7 +2960,7 @@
}
}
try {
- // save immediately old preferences
+ // save immediately new preferences
preferences.flush();
} catch (BackingStoreException e) {
// fails silently
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProjectElementInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProjectElementInfo.java
index ca3bb9a..69b1c82 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProjectElementInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProjectElementInfo.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -18,9 +18,7 @@
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jdt.core.*;
-import org.eclipse.jdt.core.IClasspathEntry;
-import org.eclipse.jdt.core.IPackageFragmentRoot;
-import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.internal.core.util.HashSetOfArray;
import org.eclipse.jdt.internal.core.util.Util;
import org.eclipse.jdt.internal.core.util.HashtableOfArrayToObject;
@@ -36,12 +34,14 @@
/* package */
class JavaProjectElementInfo extends OpenableElementInfo {
+
+ static final IPackageFragmentRoot[] NO_ROOTS = new IPackageFragmentRoot[0];
static class ProjectCache {
- ProjectCache(IPackageFragmentRoot[] allPkgFragmentRootsCache, HashtableOfArrayToObject allPkgFragmentsCache, Map pathToResolvedEntries) {
+ ProjectCache(IPackageFragmentRoot[] allPkgFragmentRootsCache, Map rootToResolvedEntries, Map pkgFragmentsCaches) {
this.allPkgFragmentRootsCache = allPkgFragmentRootsCache;
- this.allPkgFragmentsCache = allPkgFragmentsCache;
- this.pathToResolvedEntries = pathToResolvedEntries;
+ this.rootToResolvedEntries = rootToResolvedEntries;
+ this.pkgFragmentsCaches = pkgFragmentsCaches;
}
/*
@@ -51,11 +51,17 @@
/*
* A cache of all package fragments in this project.
- * (a map from String[] (the package name) to IPackageFragmentRoot[] (the package fragment roots that contain a package fragment with this name)
+ * (a map from String[] (the package name) to IPackageFragmentRoot[] (the package fragment roots that contain a package fragment with this name))
*/
public HashtableOfArrayToObject allPkgFragmentsCache;
-
- public Map pathToResolvedEntries;
+
+ /*
+ * A cache of package fragments for each package fragment root of this project
+ * (a map from IPackageFragmentRoot to a set of String[] (the package name))
+ */
+ public Map pkgFragmentsCaches;
+
+ public Map rootToResolvedEntries;
}
/**
@@ -65,6 +71,19 @@
ProjectCache projectCache;
+ /*
+ * Adds the given name and its super names to the given set
+ * (e.g. for {"a", "b", "c"}, adds {"a", "b", "c"}, {"a", "b"}, and {"a"})
+ */
+ static void addSuperPackageNames(String[] pkgName, HashtableOfArrayToObject packageFragments) {
+ for (int i = pkgName.length-1; i > 0; i--) {
+ if (packageFragments.getKey(pkgName, i) == null) {
+ System.arraycopy(pkgName, 0, pkgName = new String[i], 0, i);
+ packageFragments.put(pkgName, NO_ROOTS);
+ }
+ }
+ }
+
/**
* Create and initialize a new instance of the receiver
*/
@@ -83,81 +102,83 @@
boolean binIsProject = false;
char[][] inclusionPatterns = null;
char[][] exclusionPatterns = null;
- IClasspathEntry[] classpath = null;
IPath projectOutput = null;
+ boolean isClasspathResolved = true;
try {
- classpath = project.getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/);
- for (int i = 0; i < classpath.length; i++) {
- IClasspathEntry entry = classpath[i];
- if (projectPath.equals(entry.getPath())) {
- srcIsProject = true;
- inclusionPatterns = ((ClasspathEntry)entry).fullInclusionPatternChars();
- exclusionPatterns = ((ClasspathEntry)entry).fullExclusionPatternChars();
- break;
- }
+ IClasspathEntry entry = project.getClasspathEntryFor(projectPath);
+ if (entry != null) {
+ srcIsProject = true;
+ inclusionPatterns = ((ClasspathEntry)entry).fullInclusionPatternChars();
+ exclusionPatterns = ((ClasspathEntry)entry).fullExclusionPatternChars();
}
projectOutput = project.getOutputLocation();
binIsProject = projectPath.equals(projectOutput);
} catch (JavaModelException e) {
- // ignore
+ isClasspathResolved = false;
}
Object[] resources = new IResource[5];
int resourcesCounter = 0;
try {
IResource[] members = ((IContainer) project.getResource()).members();
- for (int i = 0, max = members.length; i < max; i++) {
- IResource res = members[i];
- switch (res.getType()) {
- case IResource.FILE :
- IPath resFullPath = res.getFullPath();
- String resName = res.getName();
+ int length = members.length;
+ if (length > 0) {
+ String sourceLevel = project.getOption(JavaCore.COMPILER_SOURCE, true);
+ String complianceLevel = project.getOption(JavaCore.COMPILER_COMPLIANCE, true);
+ IClasspathEntry[] classpath = project.getResolvedClasspath();
+ for (int i = 0; i < length; i++) {
+ IResource res = members[i];
+ switch (res.getType()) {
+ case IResource.FILE :
+ IPath resFullPath = res.getFullPath();
+ String resName = res.getName();
- // ignore a jar file on the classpath
- if (org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(resName) && this.isClasspathEntryOrOutputLocation(resFullPath, classpath, projectOutput)) {
+ // ignore a jar file on the classpath
+ if (isClasspathResolved && org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(resName) && this.isClasspathEntryOrOutputLocation(resFullPath, classpath, projectOutput)) {
+ break;
+ }
+ // ignore .java file if src == project
+ if (srcIsProject
+ && Util.isValidCompilationUnitName(resName, sourceLevel, complianceLevel)
+ && !Util.isExcluded(res, inclusionPatterns, exclusionPatterns)) {
+ break;
+ }
+ // ignore .class file if bin == project
+ if (binIsProject && Util.isValidClassFileName(resName, sourceLevel, complianceLevel)) {
+ break;
+ }
+ // else add non java resource
+ if (resources.length == resourcesCounter) {
+ // resize
+ System.arraycopy(
+ resources,
+ 0,
+ (resources = new IResource[resourcesCounter * 2]),
+ 0,
+ resourcesCounter);
+ }
+ resources[resourcesCounter++] = res;
break;
- }
- // ignore .java file if src == project
- if (srcIsProject
- && Util.isValidCompilationUnitName(resName)
- && !Util.isExcluded(res, inclusionPatterns, exclusionPatterns)) {
- break;
- }
- // ignore .class file if bin == project
- if (binIsProject && Util.isValidClassFileName(resName)) {
- break;
- }
- // else add non java resource
- if (resources.length == resourcesCounter) {
- // resize
- System.arraycopy(
- resources,
- 0,
- (resources = new IResource[resourcesCounter * 2]),
- 0,
- resourcesCounter);
- }
- resources[resourcesCounter++] = res;
- break;
- case IResource.FOLDER :
- resFullPath = res.getFullPath();
+ case IResource.FOLDER :
+ resFullPath = res.getFullPath();
- // ignore non-excluded folders on the classpath or that correspond to an output location
- if ((srcIsProject && !Util.isExcluded(res, inclusionPatterns, exclusionPatterns) && Util.isValidFolderNameForPackage(res.getName()))
- || this.isClasspathEntryOrOutputLocation(resFullPath, classpath, projectOutput)) {
- break;
- }
- // else add non java resource
- if (resources.length == resourcesCounter) {
- // resize
- System.arraycopy(
- resources,
- 0,
- (resources = new IResource[resourcesCounter * 2]),
- 0,
- resourcesCounter);
- }
- resources[resourcesCounter++] = res;
+ // ignore non-excluded folders on the classpath or that correspond to an output location
+ if ((srcIsProject && !Util.isExcluded(res, inclusionPatterns, exclusionPatterns) && Util.isValidFolderNameForPackage(res.getName(), sourceLevel, complianceLevel))
+ || (isClasspathResolved && this.isClasspathEntryOrOutputLocation(resFullPath, classpath, projectOutput))) {
+ break;
+ }
+ // else add non java resource
+ if (resources.length == resourcesCounter) {
+ // resize
+ System.arraycopy(
+ resources,
+ 0,
+ (resources = new IResource[resourcesCounter * 2]),
+ 0,
+ resourcesCounter);
+ }
+ resources[resourcesCounter++] = res;
+ }
}
}
if (resources.length != resourcesCounter) {
@@ -187,36 +208,22 @@
roots = new IPackageFragmentRoot[0];
reverseMap.clear();
}
- HashtableOfArrayToObject fragmentsCache = new HashtableOfArrayToObject();
- for (int i = 0, length = roots.length; i < length; i++) {
+
+ HashMap rootInfos = JavaModelManager.getJavaModelManager().deltaState.roots;
+ HashMap pkgFragmentsCaches = new HashMap();
+ int length = roots.length;
+ for (int i = 0; i < length; i++) {
IPackageFragmentRoot root = roots[i];
- IJavaElement[] frags = null;
- try {
- frags = root.getChildren();
- } catch (JavaModelException e) {
- // root doesn't exist: ignore
- continue;
- }
- for (int j = 0, length2 = frags.length; j < length2; j++) {
- PackageFragment fragment= (PackageFragment) frags[j];
- String[] pkgName = fragment.names;
- Object existing = fragmentsCache.get(pkgName);
- if (existing == null) {
- fragmentsCache.put(pkgName, root);
- } else {
- if (existing instanceof PackageFragmentRoot) {
- fragmentsCache.put(pkgName, new IPackageFragmentRoot[] {(PackageFragmentRoot) existing, root});
- } else {
- IPackageFragmentRoot[] entry= (IPackageFragmentRoot[]) existing;
- IPackageFragmentRoot[] copy= new IPackageFragmentRoot[entry.length + 1];
- System.arraycopy(entry, 0, copy, 0, entry.length);
- copy[entry.length]= root;
- fragmentsCache.put(pkgName, copy);
- }
- }
+ DeltaProcessor.RootInfo rootInfo = (DeltaProcessor.RootInfo) rootInfos.get(root.getPath());
+ if (rootInfo == null || rootInfo.project.equals(project)) {
+ // compute fragment cache
+ HashSetOfArray fragmentsCache = new HashSetOfArray();
+ initializePackageNames(root, fragmentsCache);
+ pkgFragmentsCaches.put(root, fragmentsCache);
}
}
- cache = new ProjectCache(roots, fragmentsCache, reverseMap);
+
+ cache = new ProjectCache(roots, reverseMap, pkgFragmentsCaches);
this.projectCache = cache;
}
return cache;
@@ -232,6 +239,24 @@
}
return this.nonJavaResources;
}
+
+ private void initializePackageNames(IPackageFragmentRoot root, HashSetOfArray fragmentsCache) {
+ IJavaElement[] frags = null;
+ try {
+ if (!root.isOpen()) {
+ PackageFragmentRootInfo info = root.isArchive() ? new JarPackageFragmentRootInfo() : new PackageFragmentRootInfo();
+ ((PackageFragmentRoot) root).computeChildren(info, new HashMap());
+ frags = info.children;
+ } else
+ frags = root.getChildren();
+ } catch (JavaModelException e) {
+ // root doesn't exist: ignore
+ return;
+ }
+ for (int j = 0, length2 = frags.length; j < length2; j++) {
+ fragmentsCache.add(((PackageFragment) frags[j]).names);
+ }
+ }
/*
* Returns whether the given path is a classpath entry or an output location.
@@ -258,7 +283,62 @@
*/
NameLookup newNameLookup(JavaProject project, ICompilationUnit[] workingCopies) {
ProjectCache cache = getProjectCache(project);
- return new NameLookup(cache.allPkgFragmentRootsCache, cache.allPkgFragmentsCache, workingCopies, cache.pathToResolvedEntries);
+ HashtableOfArrayToObject allPkgFragmentsCache = cache.allPkgFragmentsCache;
+ if (allPkgFragmentsCache == null) {
+ HashMap rootInfos = JavaModelManager.getJavaModelManager().deltaState.roots;
+ IPackageFragmentRoot[] allRoots = cache.allPkgFragmentRootsCache;
+ int length = allRoots.length;
+ allPkgFragmentsCache = new HashtableOfArrayToObject();
+ for (int i = 0; i < length; i++) {
+ IPackageFragmentRoot root = allRoots[i];
+ DeltaProcessor.RootInfo rootInfo = (DeltaProcessor.RootInfo) rootInfos.get(root.getPath());
+ JavaProject rootProject = rootInfo == null ? project : rootInfo.project;
+ HashSetOfArray fragmentsCache;
+ if (rootProject.equals(project)) {
+ // retrieve package fragments cache from this project
+ fragmentsCache = (HashSetOfArray) cache.pkgFragmentsCaches.get(root);
+ } else {
+ // retrieve package fragments cache from the root's project
+ ProjectCache rootProjectCache;
+ try {
+ rootProjectCache = rootProject.getProjectCache();
+ } catch (JavaModelException e) {
+ // project doesn't exit
+ continue;
+ }
+ fragmentsCache = (HashSetOfArray) rootProjectCache.pkgFragmentsCaches.get(root);
+ }
+ if (fragmentsCache == null) { // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=183833
+ fragmentsCache = new HashSetOfArray();
+ initializePackageNames(root, fragmentsCache);
+ }
+ Object[][] set = fragmentsCache.set;
+ for (int j = 0, length2 = set.length; j < length2; j++) {
+ String[] pkgName = (String[]) set[j];
+ if (pkgName == null)
+ continue;
+ Object existing = allPkgFragmentsCache.get(pkgName);
+ if (existing == null || existing == NO_ROOTS) {
+ allPkgFragmentsCache.put(pkgName, root);
+ // ensure super packages (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=119161)
+ // are also in the map
+ addSuperPackageNames(pkgName, allPkgFragmentsCache);
+ } else {
+ if (existing instanceof PackageFragmentRoot) {
+ allPkgFragmentsCache.put(pkgName, new IPackageFragmentRoot[] {(PackageFragmentRoot) existing, root});
+ } else {
+ IPackageFragmentRoot[] roots = (IPackageFragmentRoot[]) existing;
+ int rootLength = roots.length;
+ System.arraycopy(roots, 0, roots = new IPackageFragmentRoot[rootLength+1], 0, rootLength);
+ roots[rootLength] = root;
+ allPkgFragmentsCache.put(pkgName, roots);
+ }
+ }
+ }
+ }
+ cache.allPkgFragmentsCache = allPkgFragmentsCache;
+ }
+ return new NameLookup(cache.allPkgFragmentRootsCache, cache.allPkgFragmentsCache, workingCopies, cache.rootToResolvedEntries);
}
/*
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavadocConstants.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavadocConstants.java
new file mode 100755
index 0000000..bb9f4ba
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavadocConstants.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core;
+
+public interface JavadocConstants {
+
+ String ANCHOR_PREFIX_END = "\""; //$NON-NLS-1$
+ String ANCHOR_PREFIX_START = "<A NAME=\""; //$NON-NLS-1$
+ String ANCHOR_SUFFIX = "</A>"; //$NON-NLS-1$
+ int ANCHOR_SUFFIX_LENGTH = JavadocConstants.ANCHOR_SUFFIX.length();
+ String CONSTRUCTOR_DETAIL = "<!-- ========= CONSTRUCTOR DETAIL ======== -->"; //$NON-NLS-1$
+ String CONSTRUCTOR_SUMMARY = "<!-- ======== CONSTRUCTOR SUMMARY ======== -->"; //$NON-NLS-1$
+ String FIELD_SUMMARY = "<!-- =========== FIELD SUMMARY =========== -->"; //$NON-NLS-1$
+ String ENUM_CONSTANT_SUMMARY = "<!-- =========== ENUM CONSTANT SUMMARY =========== -->"; //$NON-NLS-1$
+ String ANNOTATION_TYPE_REQUIRED_MEMBER_SUMMARY = "<!-- =========== ANNOTATION TYPE REQUIRED MEMBER SUMMARY =========== -->"; //$NON-NLS-1$
+ String ANNOTATION_TYPE_OPTIONAL_MEMBER_SUMMARY = "<!-- =========== ANNOTATION TYPE OPTIONAL MEMBER SUMMARY =========== -->"; //$NON-NLS-1$
+ String END_OF_CLASS_DATA = "<!-- ========= END OF CLASS DATA ========= -->"; //$NON-NLS-1$
+ String HTML_EXTENSION = ".html"; //$NON-NLS-1$
+ String INDEX_FILE_NAME = "index.html"; //$NON-NLS-1$
+ String METHOD_DETAIL = "<!-- ============ METHOD DETAIL ========== -->"; //$NON-NLS-1$
+ String METHOD_SUMMARY = "<!-- ========== METHOD SUMMARY =========== -->"; //$NON-NLS-1$
+ String NESTED_CLASS_SUMMARY = "<!-- ======== NESTED CLASS SUMMARY ======== -->"; //$NON-NLS-1$
+ String PACKAGE_FILE_NAME = "package-summary.html"; //$NON-NLS-1$
+ String START_OF_CLASS_DATA = "<!-- ======== START OF CLASS DATA ======== -->"; //$NON-NLS-1$
+ int START_OF_CLASS_DATA_LENGTH = JavadocConstants.START_OF_CLASS_DATA.length();
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LRUCacheEnumerator.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LRUCacheEnumerator.java
index a1b8cf8..631670e 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LRUCacheEnumerator.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LRUCacheEnumerator.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LocalVariable.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LocalVariable.java
index c70d140..6d89f76 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LocalVariable.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LocalVariable.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Member.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Member.java
index e30ad29..4d8054e 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Member.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Member.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -11,17 +11,13 @@
package org.eclipse.jdt.internal.core;
import java.util.ArrayList;
+import java.util.HashMap;
import org.eclipse.jdt.core.*;
-import org.eclipse.jdt.core.Flags;
-import org.eclipse.jdt.core.IClassFile;
-import org.eclipse.jdt.core.IJavaElement;
-import org.eclipse.jdt.core.IMember;
-import org.eclipse.jdt.core.IMethod;
-import org.eclipse.jdt.core.ISourceRange;
-import org.eclipse.jdt.core.IType;
-import org.eclipse.jdt.core.JavaModelException;
-import org.eclipse.jdt.core.Signature;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.compiler.IScanner;
+import org.eclipse.jdt.core.compiler.ITerminalSymbols;
+import org.eclipse.jdt.core.compiler.InvalidInputException;
import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
import org.eclipse.jdt.internal.core.util.MementoTokenizer;
@@ -31,7 +27,7 @@
*/
public abstract class Member extends SourceRefElement implements IMember {
-
+
protected Member(JavaElement parent) {
super(parent);
}
@@ -104,7 +100,7 @@
simpleNames[i] = Signature.getSimpleName(Signature.toString(erasure));
}
ArrayList list = new ArrayList();
- next: for (int i = 0, length = methods.length; i < length; i++) {
+ for (int i = 0, length = methods.length; i < length; i++) {
IMethod existingMethod = methods[i];
if (areSimilarMethods(
elementName,
@@ -124,11 +120,32 @@
return result;
}
}
+public String[] getCategories() throws JavaModelException {
+ IType type = (IType) getAncestor(IJavaElement.TYPE);
+ if (type == null) return CharOperation.NO_STRINGS;
+ if (type.isBinary()) {
+ return CharOperation.NO_STRINGS;
+ } else {
+ SourceTypeElementInfo info = (SourceTypeElementInfo) ((SourceType) type).getElementInfo();
+ HashMap map = info.getCategories();
+ if (map == null) return CharOperation.NO_STRINGS;
+ String[] categories = (String[]) map.get(this);
+ if (categories == null) return CharOperation.NO_STRINGS;
+ return categories;
+ }
+}
/**
* @see IMember
*/
public IClassFile getClassFile() {
- return ((JavaElement)getParent()).getClassFile();
+ IJavaElement element = getParent();
+ while (element instanceof IMember) {
+ element= element.getParent();
+ }
+ if (element instanceof IClassFile) {
+ return (IClassFile) element;
+ }
+ return null;
}
/**
* @see IMember
@@ -240,6 +257,53 @@
}
return lastLocalContext;
}
+public ISourceRange getJavadocRange() throws JavaModelException {
+ ISourceRange range= this.getSourceRange();
+ if (range == null) return null;
+ IBuffer buf= null;
+ if (this.isBinary()) {
+ buf = this.getClassFile().getBuffer();
+ } else {
+ ICompilationUnit compilationUnit = this.getCompilationUnit();
+ if (!compilationUnit.isConsistent()) {
+ return null;
+ }
+ buf = compilationUnit.getBuffer();
+ }
+ final int start= range.getOffset();
+ final int length= range.getLength();
+ if (length > 0 && buf.getChar(start) == '/') {
+ IScanner scanner= ToolFactory.createScanner(true, false, false, false);
+ scanner.setSource(buf.getText(start, length).toCharArray());
+ try {
+ int docOffset= -1;
+ int docEnd= -1;
+
+ int terminal= scanner.getNextToken();
+ loop: while (true) {
+ switch(terminal) {
+ case ITerminalSymbols.TokenNameCOMMENT_JAVADOC :
+ docOffset= scanner.getCurrentTokenStartPosition();
+ docEnd= scanner.getCurrentTokenEndPosition() + 1;
+ terminal= scanner.getNextToken();
+ break;
+ case ITerminalSymbols.TokenNameCOMMENT_LINE :
+ case ITerminalSymbols.TokenNameCOMMENT_BLOCK :
+ terminal= scanner.getNextToken();
+ continue loop;
+ default :
+ break loop;
+ }
+ }
+ if (docOffset != -1) {
+ return new SourceRange(docOffset + start, docEnd - docOffset + 1);
+ }
+ } catch (InvalidInputException ex) {
+ // try if there is inherited Javadoc
+ }
+ }
+ return null;
+}
/**
* @see IMember
*/
@@ -260,6 +324,16 @@
}
}
/**
+ * @see IMember#getTypeRoot()
+ */
+public ITypeRoot getTypeRoot() {
+ IJavaElement element = getParent();
+ while (element instanceof IMember) {
+ element= element.getParent();
+ }
+ return (ITypeRoot) element;
+}
+/**
* @see IMember
*/
public boolean isBinary() {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MemberElementInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MemberElementInfo.java
index 9dbb32c..26ec1a2 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MemberElementInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MemberElementInfo.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -17,7 +17,7 @@
/**
* The modifiers associated with this member.
*
- * @see org.eclipse.jdt.internal.compiler.env.IConstants
+ * @see org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants
*/
protected int flags;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModelUpdater.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModelUpdater.java
index edd4215..d9c2834 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModelUpdater.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModelUpdater.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -128,8 +128,10 @@
JavaModelManager.getJavaModelManager().getIndexManager().reset();
break;
case IJavaElement.JAVA_PROJECT :
- JavaModelManager.getJavaModelManager().removePerProjectInfo(
- (JavaProject) element);
+ JavaModelManager manager = JavaModelManager.getJavaModelManager();
+ JavaProject javaProject = (JavaProject) element;
+ manager.removePerProjectInfo(javaProject);
+ manager.containerRemove(javaProject);
break;
case IJavaElement.PACKAGE_FRAGMENT_ROOT :
this.projectsToUpdate.add(element.getJavaProject());
@@ -150,7 +152,7 @@
public void processJavaDelta(IJavaElementDelta delta) {
// if (DeltaProcessor.VERBOSE){
-// System.out.println("UPDATING Model with Delta: ["+Thread.currentThread()+":" + delta + "]:");//$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
+// System.out.println("UPDATING Model with Delta: ["+Thread.currentThread()+":" + delta + "]:");
// }
try {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MoveElementsOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MoveElementsOperation.java
index e613044..e1271d7 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MoveElementsOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MoveElementsOperation.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MovePackageFragmentRootOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MovePackageFragmentRootOperation.java
index 1e669d4..5ac70c0 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MovePackageFragmentRootOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MovePackageFragmentRootOperation.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -45,6 +45,27 @@
System.arraycopy(classpath, 0, newClasspath, 0, i);
newCPIndex = i;
}
+ } else if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
+ // update exclusion/inclusion patterns
+ IPath projectRelativePath = rootPath.removeFirstSegments(1);
+ IPath[] newExclusionPatterns = renamePatterns(projectRelativePath, entry.getExclusionPatterns());
+ IPath[] newInclusionPatterns = renamePatterns(projectRelativePath, entry.getInclusionPatterns());
+ if (newExclusionPatterns != null || newInclusionPatterns != null) {
+ if (newClasspath == null) {
+ newClasspath = new IClasspathEntry[cpLength];
+ System.arraycopy(classpath, 0, newClasspath, 0, i);
+ newCPIndex = i;
+ }
+ newClasspath[newCPIndex++] =
+ JavaCore.newSourceEntry(
+ entry.getPath(),
+ newInclusionPatterns == null ? entry.getInclusionPatterns() : newInclusionPatterns,
+ newExclusionPatterns == null ? entry.getExclusionPatterns() : newExclusionPatterns,
+ entry.getOutputLocation(),
+ entry.getExtraAttributes());
+ } else if (newClasspath != null) {
+ newClasspath[newCPIndex++] = entry;
+ }
} else if (newClasspath != null) {
newClasspath[newCPIndex++] = entry;
}
@@ -54,10 +75,33 @@
if (newCPIndex < newClasspath.length) {
System.arraycopy(newClasspath, 0, newClasspath = new IClasspathEntry[newCPIndex], 0, newCPIndex);
}
- project.setRawClasspath(newClasspath, progressMonitor);
+ IJavaModelStatus status = JavaConventions.validateClasspath(project, newClasspath, project.getOutputLocation());
+ if (status.isOK())
+ project.setRawClasspath(newClasspath, progressMonitor);
+ // don't update classpath if status is not ok to avoid JavaModelException (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=129991)
}
}
+ private IPath[] renamePatterns(IPath rootPath, IPath[] patterns) {
+ IPath[] newPatterns = null;
+ int newPatternsIndex = -1;
+ for (int i = 0, length = patterns.length; i < length; i++) {
+ IPath pattern = patterns[i];
+ if (pattern.equals(rootPath)) {
+ if (newPatterns == null) {
+ newPatterns = new IPath[length];
+ System.arraycopy(patterns, 0, newPatterns, 0, i);
+ newPatternsIndex = i;
+ }
+ IPath newPattern = this.destination.removeFirstSegments(1);
+ if (pattern.hasTrailingSeparator())
+ newPattern = newPattern.addTrailingSeparator();
+ newPatterns[newPatternsIndex++] = newPattern;
+ }
+ }
+ return newPatterns;
+ }
+
public MovePackageFragmentRootOperation(
IPackageFragmentRoot root,
IPath destination,
@@ -180,7 +224,7 @@
throw new JavaModelException(e);
}
}
- this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
+ setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
}
/*
* Renames the classpath entries equal to the given path in all Java projects.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MoveResourceElementsOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MoveResourceElementsOperation.java
index 3cde822..bbc99e5 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MoveResourceElementsOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MoveResourceElementsOperation.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MultiOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MultiOperation.java
index 898192e..4eef804 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MultiOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MultiOperation.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -153,32 +153,35 @@
* be completed.
*/
protected void processElements() throws JavaModelException {
- beginTask(getMainTaskName(), this.elementsToProcess.length);
- IJavaModelStatus[] errors = new IJavaModelStatus[3];
- int errorsCounter = 0;
- for (int i = 0; i < this.elementsToProcess.length; i++) {
- try {
- verify(this.elementsToProcess[i]);
- processElement(this.elementsToProcess[i]);
- } catch (JavaModelException jme) {
- if (errorsCounter == errors.length) {
- // resize
- System.arraycopy(errors, 0, (errors = new IJavaModelStatus[errorsCounter*2]), 0, errorsCounter);
+ try {
+ beginTask(getMainTaskName(), this.elementsToProcess.length);
+ IJavaModelStatus[] errors = new IJavaModelStatus[3];
+ int errorsCounter = 0;
+ for (int i = 0; i < this.elementsToProcess.length; i++) {
+ try {
+ verify(this.elementsToProcess[i]);
+ processElement(this.elementsToProcess[i]);
+ } catch (JavaModelException jme) {
+ if (errorsCounter == errors.length) {
+ // resize
+ System.arraycopy(errors, 0, (errors = new IJavaModelStatus[errorsCounter*2]), 0, errorsCounter);
+ }
+ errors[errorsCounter++] = jme.getJavaModelStatus();
+ } finally {
+ worked(1);
}
- errors[errorsCounter++] = jme.getJavaModelStatus();
- } finally {
- worked(1);
}
- }
- done();
- if (errorsCounter == 1) {
- throw new JavaModelException(errors[0]);
- } else if (errorsCounter > 1) {
- if (errorsCounter != errors.length) {
- // resize
- System.arraycopy(errors, 0, (errors = new IJavaModelStatus[errorsCounter]), 0, errorsCounter);
+ if (errorsCounter == 1) {
+ throw new JavaModelException(errors[0]);
+ } else if (errorsCounter > 1) {
+ if (errorsCounter != errors.length) {
+ // resize
+ System.arraycopy(errors, 0, (errors = new IJavaModelStatus[errorsCounter]), 0, errorsCounter);
+ }
+ throw new JavaModelException(JavaModelStatus.newMultiStatus(errors));
}
- throw new JavaModelException(JavaModelStatus.newMultiStatus(errors));
+ } finally {
+ done();
}
}
/**
@@ -266,23 +269,25 @@
protected void verifyRenaming(IJavaElement element) throws JavaModelException {
String newName = getNewNameFor(element);
boolean isValid = true;
-
+ IJavaProject project = element.getJavaProject();
+ String sourceLevel = project.getOption(JavaCore.COMPILER_SOURCE, true);
+ String complianceLevel = project.getOption(JavaCore.COMPILER_COMPLIANCE, true);
switch (element.getElementType()) {
case IJavaElement.PACKAGE_FRAGMENT :
if (((IPackageFragment) element).isDefaultPackage()) {
// don't allow renaming of default package (see PR #1G47GUM)
throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.NAME_COLLISION, element));
}
- isValid = JavaConventions.validatePackageName(newName).getSeverity() != IStatus.ERROR;
+ isValid = JavaConventions.validatePackageName(newName, sourceLevel, complianceLevel).getSeverity() != IStatus.ERROR;
break;
case IJavaElement.COMPILATION_UNIT :
- isValid = JavaConventions.validateCompilationUnitName(newName).getSeverity() != IStatus.ERROR;
+ isValid = JavaConventions.validateCompilationUnitName(newName,sourceLevel, complianceLevel).getSeverity() != IStatus.ERROR;
break;
case IJavaElement.INITIALIZER :
isValid = false; //cannot rename initializers
break;
default :
- isValid = JavaConventions.validateIdentifier(newName).getSeverity() != IStatus.ERROR;
+ isValid = JavaConventions.validateIdentifier(newName, sourceLevel, complianceLevel).getSeverity() != IStatus.ERROR;
break;
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java
index da25a32..73f2309 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -12,34 +12,26 @@
import java.io.File;
import java.util.*;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Map;
import org.eclipse.core.resources.*;
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.Path;
-import org.eclipse.core.runtime.OperationCanceledException;
-import org.eclipse.jdt.core.IClassFile;
+import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.core.search.*;
-import org.eclipse.jdt.core.search.IJavaSearchConstants;
-import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
+import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
import org.eclipse.jdt.internal.compiler.env.IBinaryType;
-import org.eclipse.jdt.internal.compiler.env.IConstants;
-import org.eclipse.jdt.internal.compiler.env.IGenericType;
+import org.eclipse.jdt.internal.compiler.parser.ScannerHelper;
import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
import org.eclipse.jdt.internal.core.util.HashtableOfArrayToObject;
import org.eclipse.jdt.internal.core.util.Messages;
@@ -62,6 +54,29 @@
*
*/
public class NameLookup implements SuffixConstants {
+ public static class Answer {
+ public IType type;
+ AccessRestriction restriction;
+ Answer(IType type, AccessRestriction restriction) {
+ this.type = type;
+ this.restriction = restriction;
+ }
+ public boolean ignoreIfBetter() {
+ return this.restriction != null && this.restriction.ignoreIfBetter();
+ }
+ /*
+ * Returns whether this answer is better than the other awswer.
+ * (accessible is better than discouraged, which is better than
+ * non-accessible)
+ */
+ public boolean isBetter(Answer otherAnswer) {
+ if (otherAnswer == null) return true;
+ if (this.restriction == null) return true;
+ return otherAnswer.restriction != null
+ && this.restriction.getProblemId() < otherAnswer.restriction.getProblemId();
+ }
+ }
+
// TODO (jerome) suppress the accept flags (qualified name is sufficient to find a type)
/**
* Accept flag for specifying classes.
@@ -89,6 +104,8 @@
public static final int ACCEPT_ALL = ACCEPT_CLASSES | ACCEPT_INTERFACES | ACCEPT_ENUMS | ACCEPT_ANNOTATIONS;
public static boolean VERBOSE = false;
+
+ private static final IType[] NO_TYPES = {};
/**
* The <code>IPackageFragmentRoot</code>'s associated
@@ -107,7 +124,7 @@
* replaces the array.
*/
protected HashtableOfArrayToObject packageFragments;
-
+
/**
* Reverse map from root path to corresponding resolved CP entry
* (so as to be able to figure inclusion/exclusion rules)
@@ -115,55 +132,68 @@
protected Map rootToResolvedEntries;
/**
- * A map from package handles to a map from type name to an IType of an IType[].
+ * A map from package handles to a map from type name to an IType or an IType[].
* Allows working copies to take precedence over compilation units.
*/
- protected HashMap unitsToLookInside;
-
+ protected HashMap typesInWorkingCopies;
+
public long timeSpentInSeekTypesInSourcePackage = 0;
public long timeSpentInSeekTypesInBinaryPackage = 0;
- public NameLookup(IPackageFragmentRoot[] packageFragmentRoots, HashtableOfArrayToObject packageFragments, ICompilationUnit[] workingCopies, Map rootToResolvedEntries) {
+ public NameLookup(
+ IPackageFragmentRoot[] packageFragmentRoots,
+ HashtableOfArrayToObject packageFragments,
+ ICompilationUnit[] workingCopies,
+ Map rootToResolvedEntries) {
long start = -1;
if (VERBOSE) {
- System.out.println(Thread.currentThread() + " BUILDING NameLoopkup"); //$NON-NLS-1$
- System.out.println(Thread.currentThread() + " -> pkg roots size: " + (packageFragmentRoots == null ? 0 : packageFragmentRoots.length)); //$NON-NLS-1$
- System.out.println(Thread.currentThread() + " -> pkgs size: " + (packageFragments == null ? 0 : packageFragments.size())); //$NON-NLS-1$
- System.out.println(Thread.currentThread() + " -> working copy size: " + (workingCopies == null ? 0 : workingCopies.length)); //$NON-NLS-1$
+ Util.verbose(" BUILDING NameLoopkup"); //$NON-NLS-1$
+ Util.verbose(" -> pkg roots size: " + (packageFragmentRoots == null ? 0 : packageFragmentRoots.length)); //$NON-NLS-1$
+ Util.verbose(" -> pkgs size: " + (packageFragments == null ? 0 : packageFragments.size())); //$NON-NLS-1$
+ Util.verbose(" -> working copy size: " + (workingCopies == null ? 0 : workingCopies.length)); //$NON-NLS-1$
start = System.currentTimeMillis();
}
this.packageFragmentRoots = packageFragmentRoots;
- try {
- this.packageFragments = (HashtableOfArrayToObject) packageFragments.clone();
- } catch (CloneNotSupportedException e1) {
- // ignore (implementation of HashtableOfArrayToObject supports cloning)
- }
- if (workingCopies != null) {
- this.unitsToLookInside = new HashMap();
+ if (workingCopies == null) {
+ this.packageFragments = packageFragments;
+ } else {
+ // clone tables as we're adding packages from working copies
+ try {
+ this.packageFragments = (HashtableOfArrayToObject) packageFragments.clone();
+ } catch (CloneNotSupportedException e1) {
+ // ignore (implementation of HashtableOfArrayToObject supports cloning)
+ }
+ this.typesInWorkingCopies = new HashMap();
for (int i = 0, length = workingCopies.length; i < length; i++) {
ICompilationUnit workingCopy = workingCopies[i];
PackageFragment pkg = (PackageFragment) workingCopy.getParent();
- HashMap typeMap = (HashMap) this.unitsToLookInside.get(pkg);
+ HashMap typeMap = (HashMap) this.typesInWorkingCopies.get(pkg);
if (typeMap == null) {
typeMap = new HashMap();
- this.unitsToLookInside.put(pkg, typeMap);
+ this.typesInWorkingCopies.put(pkg, typeMap);
}
try {
IType[] types = workingCopy.getTypes();
- for (int j = 0, typeLength = types.length; j < typeLength; j++) {
- IType type = types[j];
- String typeName = type.getElementName();
- Object existing = typeMap.get(typeName);
- if (existing == null) {
- typeMap.put(typeName, type);
- } else if (existing instanceof IType) {
- typeMap.put(typeName, new IType[] {(IType) existing, type});
- } else {
- IType[] existingTypes = (IType[]) existing;
- int existingTypeLength = existingTypes.length;
- System.arraycopy(existingTypes, 0, existingTypes = new IType[existingTypeLength+1], 0, existingTypeLength);
- existingTypes[existingTypeLength] = type;
- typeMap.put(typeName, existingTypes);
+ int typeLength = types.length;
+ if (typeLength == 0) {
+ String typeName = Util.getNameWithoutJavaLikeExtension(workingCopy.getElementName());
+ typeMap.put(typeName, NO_TYPES);
+ } else {
+ for (int j = 0; j < typeLength; j++) {
+ IType type = types[j];
+ String typeName = type.getElementName();
+ Object existing = typeMap.get(typeName);
+ if (existing == null) {
+ typeMap.put(typeName, type);
+ } else if (existing instanceof IType) {
+ typeMap.put(typeName, new IType[] {(IType) existing, type});
+ } else {
+ IType[] existingTypes = (IType[]) existing;
+ int existingTypeLength = existingTypes.length;
+ System.arraycopy(existingTypes, 0, existingTypes = new IType[existingTypeLength+1], 0, existingTypeLength);
+ existingTypes[existingTypeLength] = type;
+ typeMap.put(typeName, existingTypes);
+ }
}
}
} catch (JavaModelException e) {
@@ -174,8 +204,11 @@
IPackageFragmentRoot root = (IPackageFragmentRoot) pkg.getParent();
String[] pkgName = pkg.names;
Object existing = this.packageFragments.get(pkgName);
- if (existing == null) {
+ if (existing == null || existing == JavaProjectElementInfo.NO_ROOTS) {
this.packageFragments.put(pkgName, root);
+ // ensure super packages (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=119161)
+ // are also in the map
+ JavaProjectElementInfo.addSuperPackageNames(pkgName, this.packageFragments);
} else {
if (existing instanceof PackageFragmentRoot) {
if (!existing.equals(root))
@@ -199,9 +232,10 @@
}
}
}
+
this.rootToResolvedEntries = rootToResolvedEntries;
if (VERBOSE) {
- System.out.println(Thread.currentThread() + " -> spent: " + (start - System.currentTimeMillis()) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
+ Util.verbose(" -> spent: " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
}
}
@@ -221,14 +255,14 @@
return true; // no flags or all flags, always accepted
try {
int kind = isSourceType
- ? ((SourceTypeElementInfo) ((SourceType) type).getElementInfo()).getKind()
- : ((IBinaryType) ((BinaryType) type).getElementInfo()).getKind();
+ ? TypeDeclaration.kind(((SourceTypeElementInfo) ((SourceType) type).getElementInfo()).getModifiers())
+ : TypeDeclaration.kind(((IBinaryType) ((BinaryType) type).getElementInfo()).getModifiers());
switch (kind) {
- case IGenericType.CLASS_DECL :
+ case TypeDeclaration.CLASS_DECL :
return (acceptFlags & ACCEPT_CLASSES) != 0;
- case IGenericType.INTERFACE_DECL :
+ case TypeDeclaration.INTERFACE_DECL :
return (acceptFlags & ACCEPT_INTERFACES) != 0;
- case IGenericType.ENUM_DECL :
+ case TypeDeclaration.ENUM_DECL :
return (acceptFlags & ACCEPT_ENUMS) != 0;
default:
//case IGenericType.ANNOTATION_TYPE :
@@ -389,13 +423,18 @@
if (entry != null) {
IPackageFragmentRoot root =
project.getPackageFragmentRoot(project.getResource());
- IPackageFragmentRoot[] roots = (IPackageFragmentRoot[]) this.packageFragments.get(CharOperation.NO_STRINGS);
- if (roots == null) {
+ Object defaultPkgRoot = this.packageFragments.get(CharOperation.NO_STRINGS);
+ if (defaultPkgRoot == null) {
return null;
}
- for (int i = 0; i < roots.length; i++) {
- if (roots[i].equals(root)) {
- return ((PackageFragmentRoot) root).getPackageFragment(CharOperation.NO_STRINGS);
+ if (defaultPkgRoot instanceof PackageFragmentRoot && defaultPkgRoot.equals(root))
+ return ((PackageFragmentRoot) root).getPackageFragment(CharOperation.NO_STRINGS);
+ else {
+ IPackageFragmentRoot[] roots = (IPackageFragmentRoot[]) defaultPkgRoot;
+ for (int i = 0; i < roots.length; i++) {
+ if (roots[i].equals(root)) {
+ return ((PackageFragmentRoot) root).getPackageFragment(CharOperation.NO_STRINGS);
+ }
}
}
}
@@ -415,37 +454,48 @@
* (qualified) name, or <code>null</code> if none exist.
*
* The name can be:
- * - empty: ""
- * - qualified: "pack.pack1.pack2"
+ * <ul>
+ * <li>empty: ""</li>
+ * <li>qualified: "pack.pack1.pack2"</li>
+ * </ul>
* @param partialMatch partial name matches qualify when <code>true</code>,
* only exact name matches qualify when <code>false</code>
*/
public IPackageFragment[] findPackageFragments(String name, boolean partialMatch) {
- if (partialMatch) {
+ return findPackageFragments(name, partialMatch, false);
+ }
+
+ /**
+ * Returns the package fragments whose name matches the given
+ * (qualified) name or pattern, or <code>null</code> if none exist.
+ *
+ * The name can be:
+ * <ul>
+ * <li>empty: ""</li>
+ * <li>qualified: "pack.pack1.pack2"</li>
+ * <li>a pattern: "pack.*.util"</li>
+ * </ul>
+ * @param partialMatch partial name matches qualify when <code>true</code>,
+ * @param patternMatch <code>true</code> when the given name might be a pattern,
+ * <code>false</code> otherwise.
+ */
+ public IPackageFragment[] findPackageFragments(String name, boolean partialMatch, boolean patternMatch) {
+ boolean hasPatternChars = patternMatch && (name.indexOf('*') >= 0 || name.indexOf('?') >= 0);
+ if (partialMatch || hasPatternChars) {
String[] splittedName = Util.splitOn('.', name, 0, name.length());
IPackageFragment[] oneFragment = null;
ArrayList pkgs = null;
Object[][] keys = this.packageFragments.keyTable;
for (int i = 0, length = keys.length; i < length; i++) {
String[] pkgName = (String[]) keys[i];
- if (pkgName != null && Util.startsWithIgnoreCase(pkgName, splittedName)) {
- Object value = this.packageFragments.valueTable[i];
- if (value instanceof PackageFragmentRoot) {
- IPackageFragment pkg = ((PackageFragmentRoot) value).getPackageFragment(pkgName);
- if (oneFragment == null) {
- oneFragment = new IPackageFragment[] {pkg};
- } else {
- if (pkgs == null) {
- pkgs = new ArrayList();
- pkgs.add(oneFragment[0]);
- }
- pkgs.add(pkg);
- }
- } else {
- IPackageFragmentRoot[] roots = (IPackageFragmentRoot[]) value;
- for (int j = 0, length2 = roots.length; j < length2; j++) {
- PackageFragmentRoot root = (PackageFragmentRoot) roots[j];
- IPackageFragment pkg = root.getPackageFragment(pkgName);
+ if (pkgName != null) {
+ boolean match = hasPatternChars
+ ? Util.matchesWithIgnoreCase(pkgName, name)
+ : Util.startsWithIgnoreCase(pkgName, splittedName, partialMatch);
+ if (match) {
+ Object value = this.packageFragments.valueTable[i];
+ if (value instanceof PackageFragmentRoot) {
+ IPackageFragment pkg = ((PackageFragmentRoot) value).getPackageFragment(pkgName);
if (oneFragment == null) {
oneFragment = new IPackageFragment[] {pkg};
} else {
@@ -455,6 +505,21 @@
}
pkgs.add(pkg);
}
+ } else {
+ IPackageFragmentRoot[] roots = (IPackageFragmentRoot[]) value;
+ for (int j = 0, length2 = roots.length; j < length2; j++) {
+ PackageFragmentRoot root = (PackageFragmentRoot) roots[j];
+ IPackageFragment pkg = root.getPackageFragment(pkgName);
+ if (oneFragment == null) {
+ oneFragment = new IPackageFragment[] {pkg};
+ } else {
+ if (pkgs == null) {
+ pkgs = new ArrayList();
+ pkgs.add(oneFragment[0]);
+ }
+ pkgs.add(pkg);
+ }
+ }
}
}
}
@@ -467,50 +532,187 @@
} else {
String[] splittedName = Util.splitOn('.', name, 0, name.length());
Object value = this.packageFragments.get(splittedName);
+ if (value == null)
+ return null;
if (value instanceof PackageFragmentRoot) {
return new IPackageFragment[] {((PackageFragmentRoot) value).getPackageFragment(splittedName)};
} else {
IPackageFragmentRoot[] roots = (IPackageFragmentRoot[]) value;
- if (roots != null) {
- IPackageFragment[] result = new IPackageFragment[roots.length];
- for (int i= 0; i < roots.length; i++) {
- result[i] = ((PackageFragmentRoot) roots[i]).getPackageFragment(splittedName);
+ IPackageFragment[] result = new IPackageFragment[roots.length];
+ for (int i= 0; i < roots.length; i++) {
+ result[i] = ((PackageFragmentRoot) roots[i]).getPackageFragment(splittedName);
+ }
+ return result;
+ }
+ }
+ }
+
+ /*
+ * Find secondary type for a project.
+ */
+ private IType findSecondaryType(String packageName, String typeName, IJavaProject project, boolean waitForIndexes, IProgressMonitor monitor) {
+ if (JavaModelManager.VERBOSE) {
+ Util.verbose("NameLookup FIND SECONDARY TYPES:"); //$NON-NLS-1$
+ Util.verbose(" -> pkg name: " + packageName); //$NON-NLS-1$
+ Util.verbose(" -> type name: " + typeName); //$NON-NLS-1$
+ Util.verbose(" -> project: "+project.getElementName()); //$NON-NLS-1$
+ }
+ JavaModelManager manager = JavaModelManager.getJavaModelManager();
+ try {
+ IJavaProject javaProject = project;
+ Map secondaryTypePaths = manager.secondaryTypes(javaProject, waitForIndexes, monitor);
+ if (secondaryTypePaths.size() > 0) {
+ Map types = (Map) secondaryTypePaths.get(packageName==null?"":packageName); //$NON-NLS-1$
+ if (types != null && types.size() > 0) {
+ IType type = (IType) types.get(typeName);
+ if (type != null) {
+ if (JavaModelManager.VERBOSE) {
+ Util.verbose(" -> type: " + type.getElementName()); //$NON-NLS-1$
+ }
+ return type;
}
- return result;
}
}
}
+ catch (JavaModelException jme) {
+ // give up
+ }
return null;
}
/**
- *
+ * Find type considering secondary types but without waiting for indexes.
+ * It means that secondary types may be not found under certain circumstances...
+ * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=118789"
*/
- public IType findType(String typeName, String packageName, boolean partialMatch, int acceptFlags) {
+ public Answer findType(String typeName, String packageName, boolean partialMatch, int acceptFlags, boolean checkRestrictions) {
+ return findType(typeName,
+ packageName,
+ partialMatch,
+ acceptFlags,
+ true/* consider secondary types */,
+ false/* do NOT wait for indexes */,
+ checkRestrictions,
+ null);
+ }
+
+ /**
+ * Find type. Considering secondary types and waiting for indexes depends on given corresponding parameters.
+ */
+ public Answer findType(
+ String typeName,
+ String packageName,
+ boolean partialMatch,
+ int acceptFlags,
+ boolean considerSecondaryTypes,
+ boolean waitForIndexes,
+ boolean checkRestrictions,
+ IProgressMonitor monitor) {
if (packageName == null || packageName.length() == 0) {
packageName= IPackageFragment.DEFAULT_PACKAGE_NAME;
- } else if (typeName.length() > 0 && Character.isLowerCase(typeName.charAt(0))) {
+ } else if (typeName.length() > 0 && ScannerHelper.isLowerCase(typeName.charAt(0))) {
// see if this is a known package and not a type
if (findPackageFragments(packageName + "." + typeName, false) != null) return null; //$NON-NLS-1$
}
+
+ // Look for concerned package fragments
JavaElementRequestor elementRequestor = new JavaElementRequestor();
seekPackageFragments(packageName, false, elementRequestor);
IPackageFragment[] packages= elementRequestor.getPackageFragments();
- for (int i= 0, length= packages.length; i < length; i++) {
- IType type= findType(typeName, packages[i], partialMatch, acceptFlags);
- if (type != null)
- return type;
+ // Try to find type in package fragments list
+ IType type = null;
+ int length= packages.length;
+ HashSet projects = null;
+ IJavaProject javaProject = null;
+ Answer suggestedAnswer = null;
+ for (int i= 0; i < length; i++) {
+ type = findType(typeName, packages[i], partialMatch, acceptFlags);
+ if (type != null) {
+ AccessRestriction accessRestriction = null;
+ if (checkRestrictions) {
+ accessRestriction = getViolatedRestriction(typeName, packageName, type, accessRestriction);
+ }
+ Answer answer = new Answer(type, accessRestriction);
+ if (!answer.ignoreIfBetter()) {
+ if (answer.isBetter(suggestedAnswer))
+ return answer;
+ } else if (answer.isBetter(suggestedAnswer))
+ // remember suggestion and keep looking
+ suggestedAnswer = answer;
+ }
+ else if (suggestedAnswer == null && considerSecondaryTypes) {
+ if (javaProject == null) {
+ javaProject = packages[i].getJavaProject();
+ } else if (projects == null) {
+ if (!javaProject.equals(packages[i].getJavaProject())) {
+ projects = new HashSet(3);
+ projects.add(javaProject);
+ projects.add(packages[i].getJavaProject());
+ }
+ } else {
+ projects.add(packages[i].getJavaProject());
+ }
+ }
}
- return null;
+ if (suggestedAnswer != null)
+ // no better answer was found
+ return suggestedAnswer;
+
+ // If type was not found, try to find it as secondary in source folders
+ if (considerSecondaryTypes && javaProject != null) {
+ if (projects == null) {
+ type = findSecondaryType(packageName, typeName, javaProject, waitForIndexes, monitor);
+ } else {
+ Iterator allProjects = projects.iterator();
+ while (type == null && allProjects.hasNext()) {
+ type = findSecondaryType(packageName, typeName, (IJavaProject) allProjects.next(), waitForIndexes, monitor);
+ }
+ }
+ }
+ return type == null ? null : new Answer(type, null);
}
-
- private IType getMemberType(IType type, String name, int dot) {
- while (dot != -1) {
- int start = dot+1;
- dot = name.indexOf('.', start);
- String typeName = name.substring(start, dot == -1 ? name.length() : dot);
- type = type.getType(typeName);
+
+ private AccessRestriction getViolatedRestriction(String typeName, String packageName, IType type, AccessRestriction accessRestriction) {
+ PackageFragmentRoot root = (PackageFragmentRoot) type.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
+ ClasspathEntry entry = (ClasspathEntry) this.rootToResolvedEntries.get(root);
+ if (entry != null) { // reverse map always contains resolved CP entry
+ AccessRuleSet accessRuleSet = entry.getAccessRuleSet();
+ if (accessRuleSet != null) {
+ // TODO (philippe) improve char[] <-> String conversions to avoid performing them on the fly
+ char[][] packageChars = CharOperation.splitOn('.', packageName.toCharArray());
+ char[] typeChars = typeName.toCharArray();
+ accessRestriction = accessRuleSet.getViolatedRestriction(CharOperation.concatWith(packageChars, typeChars, '/'));
+ }
+ }
+ return accessRestriction;
+ }
+
+ /**
+ * Returns the first type in the given package whose name
+ * matches the given (unqualified) name, or <code>null</code> if none
+ * exist. Specifying a <code>null</code> package will result in no matches.
+ * The domain of the search is bounded by the Java project from which
+ * this name lookup was obtained.
+ *
+ * @param name the name of the type to find
+ * @param pkg the package to search
+ * @param partialMatch partial name matches qualify when <code>true</code>,
+ * only exact name matches qualify when <code>false</code>
+ * @param acceptFlags a bit mask describing if classes, interfaces or both classes and interfaces
+ * are desired results. If no flags are specified, all types are returned.
+ * @param considerSecondaryTypes flag to know whether secondary types has to be considered
+ * during the search
+ *
+ * @see #ACCEPT_CLASSES
+ * @see #ACCEPT_INTERFACES
+ * @see #ACCEPT_ENUMS
+ * @see #ACCEPT_ANNOTATIONS
+ */
+ public IType findType(String name, IPackageFragment pkg, boolean partialMatch, int acceptFlags, boolean considerSecondaryTypes) {
+ IType type = findType(name, pkg, partialMatch, acceptFlags);
+ if (type == null && considerSecondaryTypes) {
+ type = findSecondaryType(pkg.getElementName(), name, pkg.getJavaProject(), false, null);
}
return type;
}
@@ -521,7 +723,9 @@
* exist. Specifying a <code>null</code> package will result in no matches.
* The domain of the search is bounded by the Java project from which
* this name lookup was obtained.
- *
+ * <br>
+ * Note that this method does not find secondary types.
+ * <br>
* @param name the name of the type to find
* @param pkg the package to search
* @param partialMatch partial name matches qualify when <code>true</code>,
@@ -540,68 +744,7 @@
// Return first found (ignore duplicates).
SingleTypeRequestor typeRequestor = new SingleTypeRequestor();
seekTypes(name, pkg, partialMatch, acceptFlags, typeRequestor);
- IType type = typeRequestor.getType();
-// if (type == null)
-// type = findSecondaryType(name, pkg, partialMatch, acceptFlags);
- return type;
- }
-
- // TODO (kent) enable once index support is in
- IType findSecondaryType(String typeName, IPackageFragment pkg, boolean partialMatch, final int acceptFlags) {
- try {
- final ArrayList paths = new ArrayList();
- TypeNameRequestor nameRequestor = new TypeNameRequestor() {
- public void acceptType(int modifiers, char[] packageName, char[] simpleTypeName, char[][] enclosingTypeNames, String path) {
- if (enclosingTypeNames == null || enclosingTypeNames.length == 0) { // accept only top level types
- int kind = modifiers & (IConstants.AccInterface+IConstants.AccEnum+IConstants.AccAnnotation);
- switch (kind) {
- case IConstants.AccAnnotation:
- case IConstants.AccAnnotation+IConstants.AccInterface:
- if ((acceptFlags & ACCEPT_ANNOTATIONS) != 0) paths.add(path);
- break;
- case IConstants.AccEnum:
- if ((acceptFlags & ACCEPT_ENUMS) != 0) paths.add(path);
- break;
- case IConstants.AccInterface:
- if ((acceptFlags & ACCEPT_INTERFACES) != 0) paths.add(path);
- break;
- default:
- if ((acceptFlags & ACCEPT_CLASSES) != 0) paths.add(path);
- break;
- }
- }
- }
- };
-
- int matchMode = partialMatch ? SearchPattern.R_PREFIX_MATCH : SearchPattern.R_EXACT_MATCH;
- int matchRule = !partialMatch ? matchMode | SearchPattern.R_CASE_SENSITIVE : matchMode;
- new SearchEngine().searchAllTypeNames(
- pkg.getElementName().toCharArray(),
- typeName.toCharArray(),
- matchRule,
- IJavaSearchConstants.TYPE,
- SearchEngine.createJavaSearchScope(new IJavaElement[] {pkg}, false),
- nameRequestor,
- IJavaSearchConstants.CANCEL_IF_NOT_READY_TO_SEARCH,
- null);
-
- if (!paths.isEmpty()) {
- IWorkspace workspace = ResourcesPlugin.getWorkspace();
- for (int i = 0, l = paths.size(); i < l; i++) {
- String pathname = (String) paths.get(i);
- if (org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(pathname)) {
- IFile file = workspace.getRoot().getFile(new Path(pathname));
- ICompilationUnit unit = JavaCore.createCompilationUnitFrom(file);
- return unit.getType(typeName);
- }
- }
- }
- } catch (JavaModelException e) {
- // ignore
- } catch (OperationCanceledException ignore) {
- // ignore
- }
- return null;
+ return typeRequestor.getType();
}
/**
@@ -621,6 +764,14 @@
* @see #ACCEPT_ANNOTATIONS
*/
public IType findType(String name, boolean partialMatch, int acceptFlags) {
+ NameLookup.Answer answer = findType(name, partialMatch, acceptFlags, false/*don't check restrictions*/);
+ return answer == null ? null : answer.type;
+ }
+
+ public Answer findType(String name, boolean partialMatch, int acceptFlags, boolean checkRestrictions) {
+ return findType(name, partialMatch, acceptFlags, true/*consider secondary types*/, true/*wait for indexes*/, checkRestrictions, null);
+ }
+ public Answer findType(String name, boolean partialMatch, int acceptFlags, boolean considerSecondaryTypes, boolean waitForIndexes, boolean checkRestrictions, IProgressMonitor monitor) {
int index= name.lastIndexOf('.');
String className= null, packageName= null;
if (index == -1) {
@@ -630,7 +781,21 @@
packageName= name.substring(0, index);
className= name.substring(index + 1);
}
- return findType(className, packageName, partialMatch, acceptFlags);
+ return findType(className, packageName, partialMatch, acceptFlags, considerSecondaryTypes, waitForIndexes, checkRestrictions, monitor);
+ }
+
+ private IType getMemberType(IType type, String name, int dot) {
+ while (dot != -1) {
+ int start = dot+1;
+ dot = name.indexOf('.', start);
+ String typeName = name.substring(start, dot == -1 ? name.length() : dot);
+ type = type.getType(typeName);
+ }
+ return type;
+ }
+
+ public boolean isPackage(String[] pkgName) {
+ return this.packageFragments.get(pkgName) != null;
}
/**
@@ -681,9 +846,9 @@
*/
public void seekPackageFragments(String name, boolean partialMatch, IJavaElementRequestor requestor) {
/* if (VERBOSE) {
- System.out.println(Thread.currentThread() + " SEEKING PACKAGE FRAGMENTS"); //$NON-NLS-1$
- System.out.println(Thread.currentThread() + " -> name: " + name); //$NON-NLS-1$
- System.out.println(Thread.currentThread() + " -> partial match:" + partialMatch); //$NON-NLS-1$
+ Util.verbose(" SEEKING PACKAGE FRAGMENTS"); //$NON-NLS-1$
+ Util.verbose(" -> name: " + name); //$NON-NLS-1$
+ Util.verbose(" -> partial match:" + partialMatch); //$NON-NLS-1$
}
*/ if (partialMatch) {
String[] splittedName = Util.splitOn('.', name, 0, name.length());
@@ -692,7 +857,7 @@
if (requestor.isCanceled())
return;
String[] pkgName = (String[]) keys[i];
- if (pkgName != null && Util.startsWithIgnoreCase(pkgName, splittedName)) {
+ if (pkgName != null && Util.startsWithIgnoreCase(pkgName, splittedName, partialMatch)) {
Object value = this.packageFragments.valueTable[i];
if (value instanceof PackageFragmentRoot) {
PackageFragmentRoot root = (PackageFragmentRoot) value;
@@ -749,10 +914,10 @@
*/
public void seekTypes(String name, IPackageFragment pkg, boolean partialMatch, int acceptFlags, IJavaElementRequestor requestor) {
/* if (VERBOSE) {
- System.out.println(Thread.currentThread() + " SEEKING TYPES"); //$NON-NLS-1$
- System.out.println(Thread.currentThread() + " -> name: " + name); //$NON-NLS-1$
- System.out.println(Thread.currentThread() + " -> pkg: " + ((JavaElement) pkg).toStringWithAncestors()); //$NON-NLS-1$
- System.out.println(Thread.currentThread() + " -> partial match:" + partialMatch); //$NON-NLS-1$
+ Util.verbose(" SEEKING TYPES"); //$NON-NLS-1$
+ Util.verbose(" -> name: " + name); //$NON-NLS-1$
+ Util.verbose(" -> pkg: " + ((JavaElement) pkg).toStringWithAncestors()); //$NON-NLS-1$
+ Util.verbose(" -> partial match:" + partialMatch); //$NON-NLS-1$
}
*/
String matchName= partialMatch ? name.toLowerCase() : name;
@@ -762,15 +927,29 @@
}
IPackageFragmentRoot root= (IPackageFragmentRoot) pkg.getParent();
try {
+
+ // look in working copies first
+ int firstDot = -1;
+ String topLevelTypeName = null;
int packageFlavor= root.getKind();
+ if (this.typesInWorkingCopies != null || packageFlavor == IPackageFragmentRoot.K_SOURCE) {
+ firstDot = matchName.indexOf('.');
+ if (!partialMatch)
+ topLevelTypeName = firstDot == -1 ? matchName : matchName.substring(0, firstDot);
+ }
+ if (this.typesInWorkingCopies != null) {
+ if (seekTypesInWorkingCopies(matchName, pkg, firstDot, partialMatch, topLevelTypeName, acceptFlags, requestor))
+ return;
+ }
+
+ // look in model
switch (packageFlavor) {
case IPackageFragmentRoot.K_BINARY :
matchName= matchName.replace('.', '$');
seekTypesInBinaryPackage(matchName, pkg, partialMatch, acceptFlags, requestor);
break;
case IPackageFragmentRoot.K_SOURCE :
- matchName= matchName.replace('$', '.');
- seekTypesInSourcePackage(matchName, pkg, partialMatch, acceptFlags, requestor);
+ seekTypesInSourcePackage(matchName, pkg, firstDot, partialMatch, topLevelTypeName, acceptFlags, requestor);
break;
default :
return;
@@ -788,44 +967,46 @@
if (VERBOSE)
start = System.currentTimeMillis();
try {
- IClassFile[] classFiles= null;
- try {
- classFiles= pkg.getClassFiles();
- } catch (JavaModelException npe) {
- return; // the package is not present
- }
- int length= classFiles.length;
-
- String unqualifiedName= name;
- int index= name.lastIndexOf('$');
- if (index != -1) {
- //the type name of the inner type
- unqualifiedName= Util.localTypeName(name, index, name.length());
- // unqualifiedName is empty if the name ends with a '$' sign.
- // See http://dev.eclipse.org/bugs/show_bug.cgi?id=14642
- }
- String matchName= partialMatch ? name.toLowerCase() : name;
- for (int i= 0; i < length; i++) {
- if (requestor.isCanceled())
- return;
- IClassFile classFile= classFiles[i];
- String elementName = classFile.getElementName();
- if (partialMatch) elementName = elementName.toLowerCase();
-
- /**
- * Must use startWith because matchName will never have the
- * extension ".class" and the elementName always will.
- */
- if (elementName.startsWith(matchName)) {
- IType type= null;
- try {
- type= classFile.getType();
- } catch (JavaModelException npe) {
- continue; // the classFile is not present
+ if (!partialMatch) {
+ // exact match
+ if (requestor.isCanceled()) return;
+ ClassFile classFile = new ClassFile((PackageFragment) pkg, name);
+ if (classFile.existsUsingJarTypeCache()) {
+ IType type = classFile.getType();
+ if (acceptType(type, acceptFlags, false/*not a source type*/)) {
+ requestor.acceptType(type);
}
- if (!partialMatch || (type.getElementName().length() > 0 && !Character.isDigit(type.getElementName().charAt(0)))) { //not an anonymous type
- if (nameMatches(unqualifiedName, type, partialMatch) && acceptType(type, acceptFlags, false/*not a source type*/))
- requestor.acceptType(type);
+ }
+ } else {
+ IJavaElement[] classFiles= null;
+ try {
+ classFiles= pkg.getChildren();
+ } catch (JavaModelException npe) {
+ return; // the package is not present
+ }
+ int length= classFiles.length;
+ String unqualifiedName = name;
+ int index = name.lastIndexOf('$');
+ if (index != -1) {
+ //the type name of the inner type
+ unqualifiedName = Util.localTypeName(name, index, name.length());
+ // unqualifiedName is empty if the name ends with a '$' sign.
+ // See http://dev.eclipse.org/bugs/show_bug.cgi?id=14642
+ }
+ int matchLength = name.length();
+ for (int i = 0; i < length; i++) {
+ if (requestor.isCanceled())
+ return;
+ IJavaElement classFile= classFiles[i];
+ // MatchName will never have the extension ".class" and the elementName always will.
+ String elementName = classFile.getElementName();
+ if (elementName.regionMatches(true /*ignore case*/, 0, name, 0, matchLength)) {
+ IType type = ((ClassFile) classFile).getType();
+ String typeName = type.getElementName();
+ if (typeName.length() > 0 && !Character.isDigit(typeName.charAt(0))) { //not an anonymous type
+ if (nameMatches(unqualifiedName, type, true/*partial match*/) && acceptType(type, acceptFlags, false/*not a source type*/))
+ requestor.acceptType(type);
+ }
}
}
}
@@ -838,52 +1019,31 @@
/**
* Performs type search in a source package.
*/
- protected void seekTypesInSourcePackage(String name, IPackageFragment pkg, boolean partialMatch, int acceptFlags, IJavaElementRequestor requestor) {
+ protected void seekTypesInSourcePackage(
+ String name,
+ IPackageFragment pkg,
+ int firstDot,
+ boolean partialMatch,
+ String topLevelTypeName,
+ int acceptFlags,
+ IJavaElementRequestor requestor) {
long start = -1;
if (VERBOSE)
start = System.currentTimeMillis();
try {
if (!partialMatch) {
- int firstDot = name.indexOf('.');
- String topLevelTypeName = firstDot == -1 ? name : name.substring(0, firstDot);
-
- // look in unitsToLookInside first
- HashMap typeMap = (HashMap) (this.unitsToLookInside == null ? null : this.unitsToLookInside.get(pkg));
- if (typeMap != null) {
- Object object = typeMap.get(topLevelTypeName);
- if (object instanceof IType) {
- IType type = getMemberType((IType) object, name, firstDot);
- if (acceptType(type, acceptFlags, true/*a source type*/)) {
- requestor.acceptType(type);
- return; // don't continue with compilation unit
- }
- } else if (object instanceof IType[]) {
- IType[] topLevelTypes = (IType[]) object;
- for (int i = 0, length = topLevelTypes.length; i < length; i++) {
- if (requestor.isCanceled())
- return;
- IType type = getMemberType(topLevelTypes[i], name, firstDot);
- if (acceptType(type, acceptFlags, true/*a source type*/)) {
- requestor.acceptType(type);
- return; // return the first one
- }
- }
- }
- }
-
- // look in compilation units
try {
- ICompilationUnit[] compilationUnits = pkg.getCompilationUnits();
+ IJavaElement[] compilationUnits = pkg.getChildren();
for (int i = 0, length = compilationUnits.length; i < length; i++) {
if (requestor.isCanceled())
return;
- ICompilationUnit cu = compilationUnits[i];
+ IJavaElement cu = compilationUnits[i];
String cuName = cu.getElementName();
int lastDot = cuName.lastIndexOf('.');
- if (!topLevelTypeName.equals(cuName.substring(0, lastDot)))
+ if (lastDot != topLevelTypeName.length() || !topLevelTypeName.regionMatches(0, cuName, 0, lastDot))
continue;
- IType type = cu.getType(topLevelTypeName);
+ IType type = ((ICompilationUnit) cu).getType(topLevelTypeName);
type = getMemberType(type, name, firstDot);
if (acceptType(type, acceptFlags, true/*a source type*/)) { // accept type checks for existence
requestor.acceptType(type);
@@ -894,41 +1054,19 @@
// package doesn't exist -> ignore
}
} else {
- String prefix = name.toLowerCase();
- int firstDot = prefix.indexOf('.');
-
- // look in unitsToLookInside first
- HashMap typeMap = (HashMap) (this.unitsToLookInside == null ? null : this.unitsToLookInside.get(pkg));
- if (typeMap != null) {
- Iterator iterator = typeMap.values().iterator();
- while (iterator.hasNext()) {
- if (requestor.isCanceled())
- return;
- Object object = iterator.next();
- if (object instanceof IType) {
- seekTypesInTopLevelType(prefix, firstDot, (IType) object, requestor, acceptFlags);
- } else if (object instanceof IType[]) {
- IType[] topLevelTypes = (IType[]) object;
- for (int i = 0, length = topLevelTypes.length; i < length; i++)
- seekTypesInTopLevelType(prefix, firstDot, topLevelTypes[i], requestor, acceptFlags);
- }
- }
- }
-
- // look in compilation units
try {
- String cuPrefix = firstDot == -1 ? prefix : prefix.substring(0, firstDot);
- ICompilationUnit[] compilationUnits = pkg.getCompilationUnits();
+ String cuPrefix = firstDot == -1 ? name : name.substring(0, firstDot);
+ IJavaElement[] compilationUnits = pkg.getChildren();
for (int i = 0, length = compilationUnits.length; i < length; i++) {
if (requestor.isCanceled())
return;
- ICompilationUnit cu = compilationUnits[i];
+ IJavaElement cu = compilationUnits[i];
if (!cu.getElementName().toLowerCase().startsWith(cuPrefix))
continue;
try {
- IType[] types = cu.getTypes();
+ IType[] types = ((ICompilationUnit) cu).getTypes();
for (int j = 0, typeLength = types.length; j < typeLength; j++)
- seekTypesInTopLevelType(prefix, firstDot, types[j], requestor, acceptFlags);
+ seekTypesInTopLevelType(name, firstDot, types[j], requestor, acceptFlags);
} catch (JavaModelException e) {
// cu doesn't exist -> ignore
}
@@ -942,22 +1080,22 @@
this.timeSpentInSeekTypesInSourcePackage += System.currentTimeMillis()-start;
}
}
-
+
/**
* Notifies the given requestor of all types (classes and interfaces) in the
* given type with the given (possibly qualified) name. Checks
* the requestor at regular intervals to see if the requestor
* has canceled.
*/
- protected void seekTypesInType(String prefix, int firstDot, IType type, IJavaElementRequestor requestor, int acceptFlags) {
+ protected boolean seekTypesInType(String prefix, int firstDot, IType type, IJavaElementRequestor requestor, int acceptFlags) {
IType[] types= null;
try {
types= type.getTypes();
} catch (JavaModelException npe) {
- return; // the enclosing type is not present
+ return false; // the enclosing type is not present
}
int length= types.length;
- if (length == 0) return;
+ if (length == 0) return false;
String memberPrefix = prefix;
boolean isMemberTypePrefix = false;
@@ -967,27 +1105,92 @@
}
for (int i= 0; i < length; i++) {
if (requestor.isCanceled())
- return;
+ return false;
IType memberType= types[i];
if (memberType.getElementName().toLowerCase().startsWith(memberPrefix))
if (isMemberTypePrefix) {
String subPrefix = prefix.substring(firstDot + 1, prefix.length());
- seekTypesInType(subPrefix, subPrefix.indexOf('.'), memberType, requestor, acceptFlags);
+ return seekTypesInType(subPrefix, subPrefix.indexOf('.'), memberType, requestor, acceptFlags);
} else {
- if (acceptType(memberType, acceptFlags, true/*a source type*/))
+ if (acceptType(memberType, acceptFlags, true/*a source type*/)) {
requestor.acceptMemberType(memberType);
+ return true;
+ }
}
}
+ return false;
}
- protected void seekTypesInTopLevelType(String prefix, int firstDot, IType topLevelType, IJavaElementRequestor requestor, int acceptFlags) {
+ protected boolean seekTypesInTopLevelType(String prefix, int firstDot, IType topLevelType, IJavaElementRequestor requestor, int acceptFlags) {
if (!topLevelType.getElementName().toLowerCase().startsWith(prefix))
- return;
+ return false;
if (firstDot == -1) {
- if (acceptType(topLevelType, acceptFlags, true/*a source type*/))
+ if (acceptType(topLevelType, acceptFlags, true/*a source type*/)) {
requestor.acceptType(topLevelType);
+ return true;
+ }
} else {
- seekTypesInType(prefix, firstDot, topLevelType, requestor, acceptFlags);
+ return seekTypesInType(prefix, firstDot, topLevelType, requestor, acceptFlags);
}
+ return false;
}
+
+ /*
+ * Seeks the type with the given name in the map of types with precedence (coming from working copies)
+ * Return whether a type has been found.
+ */
+ protected boolean seekTypesInWorkingCopies(
+ String name,
+ IPackageFragment pkg,
+ int firstDot,
+ boolean partialMatch,
+ String topLevelTypeName,
+ int acceptFlags,
+ IJavaElementRequestor requestor) {
+
+ if (!partialMatch) {
+ HashMap typeMap = (HashMap) (this.typesInWorkingCopies == null ? null : this.typesInWorkingCopies.get(pkg));
+ if (typeMap != null) {
+ Object object = typeMap.get(topLevelTypeName);
+ if (object instanceof IType) {
+ IType type = getMemberType((IType) object, name, firstDot);
+ if (acceptType(type, acceptFlags, true/*a source type*/)) {
+ requestor.acceptType(type);
+ return true; // don't continue with compilation unit
+ }
+ } else if (object instanceof IType[]) {
+ if (object == NO_TYPES) return true; // all types where deleted -> type is hidden
+ IType[] topLevelTypes = (IType[]) object;
+ for (int i = 0, length = topLevelTypes.length; i < length; i++) {
+ if (requestor.isCanceled())
+ return false;
+ IType type = getMemberType(topLevelTypes[i], name, firstDot);
+ if (acceptType(type, acceptFlags, true/*a source type*/)) {
+ requestor.acceptType(type);
+ return true; // return the first one
+ }
+ }
+ }
+ }
+ } else {
+ HashMap typeMap = (HashMap) (this.typesInWorkingCopies == null ? null : this.typesInWorkingCopies.get(pkg));
+ if (typeMap != null) {
+ Iterator iterator = typeMap.values().iterator();
+ while (iterator.hasNext()) {
+ if (requestor.isCanceled())
+ return false;
+ Object object = iterator.next();
+ if (object instanceof IType) {
+ seekTypesInTopLevelType(name, firstDot, (IType) object, requestor, acceptFlags);
+ } else if (object instanceof IType[]) {
+ IType[] topLevelTypes = (IType[]) object;
+ for (int i = 0, length = topLevelTypes.length; i < length; i++)
+ seekTypesInTopLevelType(name, firstDot, topLevelTypes[i], requestor, acceptFlags);
+ }
+ }
+ }
+ }
+ return false;
+ }
+
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NamedMember.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NamedMember.java
index 1de6701..c305503 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NamedMember.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NamedMember.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -21,6 +21,7 @@
import org.eclipse.jdt.core.ITypeParameter;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
+import org.eclipse.jdt.core.compiler.CharOperation;
public abstract class NamedMember extends Member {
@@ -89,6 +90,28 @@
String selector = method.getElementName();
key.append(selector);
+ // type parameters
+ if (forceOpen) {
+ ITypeParameter[] typeParameters = method.getTypeParameters();
+ int length = typeParameters.length;
+ if (length > 0) {
+ key.append('<');
+ for (int i = 0; i < length; i++) {
+ ITypeParameter typeParameter = typeParameters[i];
+ String[] bounds = typeParameter.getBounds();
+ int boundsLength = bounds.length;
+ char[][] boundSignatures = new char[boundsLength][];
+ for (int j = 0; j < boundsLength; j++) {
+ boundSignatures[j] = Signature.createCharArrayTypeSignature(bounds[j].toCharArray(), method.isBinary());
+ CharOperation.replace(boundSignatures[j], '.', '/');
+ }
+ char[] sig = Signature.createTypeParameterSignature(typeParameter.getElementName().toCharArray(), boundSignatures);
+ key.append(sig);
+ }
+ key.append('>');
+ }
+ }
+
// parameters
key.append('(');
String[] parameters = method.getParameterTypes();
@@ -98,7 +121,7 @@
// return type
if (forceOpen)
- key.append(method.getReturnType());
+ key.append(method.getReturnType().replace('.', '/'));
else
key.append('V');
@@ -140,7 +163,6 @@
buffer.append('<');
for (int i = 0; i < length; i++) {
String typeArgument = typeArguments[i];
- typeArgument.replace('/', '.');
buffer.append(Signature.toString(typeArgument));
if (i < length-1)
buffer.append(',');
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NullBuffer.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NullBuffer.java
new file mode 100755
index 0000000..a6cd755
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NullBuffer.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jdt.core.IOpenable;
+
+/**
+ * This class represents a null buffer. This buffer is used to represent a buffer for a class file
+ * that has no source attached.
+ */
+public class NullBuffer extends Buffer {
+ /**
+ * Creates a new null buffer on an underlying resource.
+ */
+ public NullBuffer(IFile file, IOpenable owner, boolean readOnly) {
+ super(file, owner, readOnly);
+ }
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Openable.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Openable.java
index 15cbcd5..e221294 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Openable.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Openable.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,21 +10,18 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core;
-import java.util.*;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.resources.*;
-import org.eclipse.core.resources.IContainer;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.PerformanceStats;
import org.eclipse.jdt.core.*;
import org.eclipse.jdt.internal.codeassist.CompletionEngine;
import org.eclipse.jdt.internal.codeassist.SelectionEngine;
+import org.eclipse.jdt.internal.core.util.Util;
/**
@@ -51,7 +48,7 @@
JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().remove(this);
getBufferManager().removeBuffer(event.getBuffer());
} else {
- JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().put(this, this);
+ JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().add(this);
}
}
/**
@@ -102,13 +99,11 @@
if (requestor == null) {
throw new IllegalArgumentException("Completion requestor cannot be null"); //$NON-NLS-1$
}
- PerformanceStats stats = null;
- if(CompletionEngine.PERF) {
- stats = PerformanceStats.getStats(JavaModelManager.COMPLETION_PERF, this);
- stats.startRun(
- new String(cu.getFileName()) +
- " at " + //$NON-NLS-1$
- position);
+ PerformanceStats performanceStats = CompletionEngine.PERF
+ ? PerformanceStats.getStats(JavaModelManager.COMPLETION_PERF, this)
+ : null;
+ if(performanceStats != null) {
+ performanceStats.startRun(new String(cu.getFileName()) + " at " + position); //$NON-NLS-1$
}
IBuffer buffer = getBuffer();
if (buffer == null) {
@@ -126,8 +121,8 @@
// code complete
CompletionEngine engine = new CompletionEngine(environment, requestor, project.getOptions(true), project);
engine.complete(cu, position, 0);
- if(CompletionEngine.PERF) {
- stats.endRun();
+ if(performanceStats != null) {
+ performanceStats.endRun();
}
if (NameLookup.VERBOSE) {
System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInSourcePackage: " + environment.nameLookup.timeSpentInSeekTypesInSourcePackage + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
@@ -135,16 +130,11 @@
}
}
protected IJavaElement[] codeSelect(org.eclipse.jdt.internal.compiler.env.ICompilationUnit cu, int offset, int length, WorkingCopyOwner owner) throws JavaModelException {
- PerformanceStats stats = null;
- if(SelectionEngine.PERF) {
- stats = PerformanceStats.getStats(JavaModelManager.SELECTION_PERF, this);
- stats.startRun(
- new String(cu.getFileName()) +
- " at [" + //$NON-NLS-1$
- offset +
- "," + //$NON-NLS-1$
- length +
- "]"); //$NON-NLS-1$
+ PerformanceStats performanceStats = SelectionEngine.PERF
+ ? PerformanceStats.getStats(JavaModelManager.SELECTION_PERF, this)
+ : null;
+ if(performanceStats != null) {
+ performanceStats.startRun(new String(cu.getFileName()) + " at [" + offset + "," + length + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
JavaProject project = (JavaProject)getJavaProject();
@@ -163,8 +153,9 @@
// fix for 1FVXGDK
SelectionEngine engine = new SelectionEngine(environment, requestor, project.getOptions(true));
engine.select(cu, offset, offset + length - 1);
- if(SelectionEngine.PERF) {
- stats.endRun();
+
+ if(performanceStats != null) {
+ performanceStats.endRun();
}
if (NameLookup.VERBOSE) {
System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInSourcePackage: " + environment.nameLookup.timeSpentInSeekTypesInSourcePackage + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
@@ -192,9 +183,14 @@
}
return super.exists();
}
+public String findRecommendedLineSeparator() throws JavaModelException {
+ IBuffer buffer = getBuffer();
+ String source = buffer == null ? null : buffer.getContents();
+ return Util.getLineSeparator(source, getJavaProject());
+}
protected void generateInfos(Object info, HashMap newElements, IProgressMonitor monitor) throws JavaModelException {
- if (JavaModelManager.VERBOSE){
+ if (JavaModelCache.VERBOSE){
String element;
switch (getElementType()) {
case JAVA_PROJECT:
@@ -240,8 +236,8 @@
// remove out of sync buffer for this element
JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().remove(this);
- if (JavaModelManager.VERBOSE) {
- System.out.println(JavaModelManager.getJavaModelManager().cache.toStringFillingRation("-> ")); //$NON-NLS-1$
+ if (JavaModelCache.VERBOSE) {
+ System.out.println(JavaModelManager.getJavaModelManager().cacheToString("-> ")); //$NON-NLS-1$
}
}
/**
@@ -262,6 +258,9 @@
// try to (re)open a buffer
buffer = openBuffer(null, info);
}
+ if (buffer instanceof NullBuffer) {
+ return null;
+ }
return buffer;
} else {
return null;
@@ -394,34 +393,8 @@
* @see IOpenable
*/
public void makeConsistent(IProgressMonitor monitor) throws JavaModelException {
- if (isConsistent()) return;
-
- // create a new info and make it the current info
- // (this will remove the info and its children just before storing the new infos)
- JavaModelManager manager = JavaModelManager.getJavaModelManager();
- boolean hadTemporaryCache = manager.hasTemporaryCache();
- try {
- HashMap newElements = manager.getTemporaryCache();
- openWhenClosed(newElements, monitor);
- if (newElements.get(this) == null) {
- // close any buffer that was opened for the new elements
- Iterator iterator = newElements.keySet().iterator();
- while (iterator.hasNext()) {
- IJavaElement element = (IJavaElement)iterator.next();
- if (element instanceof Openable) {
- ((Openable)element).closeBuffer();
- }
- }
- throw newNotPresentException();
- }
- if (!hadTemporaryCache) {
- manager.putInfos(this, newElements);
- }
- } finally {
- if (!hadTemporaryCache) {
- manager.resetTemporaryCache();
- }
- }
+ // only compilation units can be inconsistent
+ // other openables cannot be inconsistent so default is to do nothing
}
/**
* @see IOpenable
@@ -493,12 +466,7 @@
* Find enclosing package fragment root if any
*/
public PackageFragmentRoot getPackageFragmentRoot() {
- IJavaElement current = this;
- do {
- if (current instanceof PackageFragmentRoot) return (PackageFragmentRoot)current;
- current = current.getParent();
- } while(current != null);
- return null;
+ return (PackageFragmentRoot) getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/OpenableElementInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/OpenableElementInfo.java
index ded5721..0b35f5c 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/OpenableElementInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/OpenableElementInfo.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/OverflowingLRUCache.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/OverflowingLRUCache.java
index 4e91f55..80c20f8 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/OverflowingLRUCache.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/OverflowingLRUCache.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,7 +10,6 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core;
-import java.text.NumberFormat;
import java.util.Enumeration;
import java.util.Iterator;
@@ -162,15 +161,13 @@
protected boolean makeSpace(int space) {
int limit = fSpaceLimit;
- if (fOverflow == 0) {
+ if (fOverflow == 0 && fCurrentSpace + space <= limit) {
/* if space is already available */
- if (fCurrentSpace + space <= limit) {
- return true;
- }
+ return true;
}
/* Free up space by removing oldest entries */
- int spaceNeeded = (int)((1 - fLoadFactor) * fSpaceLimit);
+ int spaceNeeded = (int)((1 - fLoadFactor) * limit);
spaceNeeded = (spaceNeeded > space) ? spaceNeeded : space;
LRUCacheEntry entry = fEntryQueueTail;
@@ -201,20 +198,6 @@
* Returns a new instance of the reciever.
*/
protected abstract LRUCache newInstance(int size, int overflow);
- /**
- * Answers the value in the cache at the given key.
- * If the value is not in the cache, returns null
- *
- * This function does not modify timestamps.
- */
- public Object peek(Object key) {
-
- LRUCacheEntry entry = (LRUCacheEntry) fEntryTable.get(key);
- if (entry == null) {
- return null;
- }
- return entry._fValue;
- }
/**
* For testing purposes only
*/
@@ -259,8 +242,8 @@
}
}
- for (Iterator iter = h.keySet().iterator(); iter.hasNext();){
- System.out.println(h.get(iter.next()));
+ for (Iterator iter = h.values().iterator(); iter.hasNext();){
+ System.out.println(iter.next());
}
}
/**
@@ -290,7 +273,6 @@
if (external) {
fEntryTable.remove(entry._fKey);
fCurrentSpace -= entry._fSpace;
- privateNotifyDeletionFromCache(entry);
} else {
if (!close(entry)) return;
// buffer close will recursively call #privateRemoveEntry with external==true
@@ -301,7 +283,6 @@
// basic removal
fEntryTable.remove(entry._fKey);
fCurrentSpace -= entry._fSpace;
- privateNotifyDeletionFromCache(entry);
}
}
}
@@ -415,8 +396,8 @@
*/
public String toString() {
return
- "OverflowingLRUCache " + NumberFormat.getInstance().format(this.fillingRatio()) + "% full\n" + //$NON-NLS-1$ //$NON-NLS-2$
- this.toStringContents();
+ toStringFillingRation("OverflowingLRUCache ") + //$NON-NLS-1$
+ toStringContents();
}
/**
* Updates the timestamp for the given entry, ensuring that the queue is
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragment.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragment.java
index f2065fa..f374c43 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragment.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragment.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,8 +10,9 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core;
-import java.util.*;
+import java.net.URL;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.Map;
import org.eclipse.core.resources.IContainer;
@@ -20,15 +21,22 @@
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Path;
-import org.eclipse.jdt.core.*;
import org.eclipse.jdt.core.IClassFile;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaModelStatusConstants;
+import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.IParent;
+import org.eclipse.jdt.core.ISourceManipulation;
+import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.WorkingCopyOwner;
import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
+import org.eclipse.jdt.internal.core.JavaModelManager.PerProjectInfo;
import org.eclipse.jdt.internal.core.util.MementoTokenizer;
import org.eclipse.jdt.internal.core.util.Messages;
import org.eclipse.jdt.internal.core.util.Util;
@@ -59,8 +67,12 @@
// check whether this pkg can be opened
if (!underlyingResource.isAccessible()) throw newNotPresentException();
-
+
+ // check that it is not excluded (https://bugs.eclipse.org/bugs/show_bug.cgi?id=138577)
int kind = getKind();
+ if (kind == IPackageFragmentRoot.K_SOURCE && Util.isExcluded(this))
+ throw newNotPresentException();
+
// add compilation units/class files from resources
HashSet vChildren = new HashSet();
@@ -69,17 +81,23 @@
char[][] inclusionPatterns = root.fullInclusionPatternChars();
char[][] exclusionPatterns = root.fullExclusionPatternChars();
IResource[] members = ((IContainer) underlyingResource).members();
- for (int i = 0, max = members.length; i < max; i++) {
- IResource child = members[i];
- if (child.getType() != IResource.FOLDER
- && !Util.isExcluded(child, inclusionPatterns, exclusionPatterns)) {
- IJavaElement childElement;
- if (kind == IPackageFragmentRoot.K_SOURCE && Util.isValidCompilationUnitName(child.getName())) {
- childElement = new CompilationUnit(this, child.getName(), DefaultWorkingCopyOwner.PRIMARY);
- vChildren.add(childElement);
- } else if (kind == IPackageFragmentRoot.K_BINARY && Util.isValidClassFileName(child.getName())) {
- childElement = getClassFile(child.getName());
- vChildren.add(childElement);
+ int length = members.length;
+ if (length > 0) {
+ IJavaProject project = getJavaProject();
+ String sourceLevel = project.getOption(JavaCore.COMPILER_SOURCE, true);
+ String complianceLevel = project.getOption(JavaCore.COMPILER_COMPLIANCE, true);
+ for (int i = 0; i < length; i++) {
+ IResource child = members[i];
+ if (child.getType() != IResource.FOLDER
+ && !Util.isExcluded(child, inclusionPatterns, exclusionPatterns)) {
+ IJavaElement childElement;
+ if (kind == IPackageFragmentRoot.K_SOURCE && Util.isValidCompilationUnitName(child.getName(), sourceLevel, complianceLevel)) {
+ childElement = new CompilationUnit(this, child.getName(), DefaultWorkingCopyOwner.PRIMARY);
+ vChildren.add(childElement);
+ } else if (kind == IPackageFragmentRoot.K_BINARY && Util.isValidClassFileName(child.getName(), sourceLevel, complianceLevel)) {
+ childElement = getClassFile(child.getName());
+ vChildren.add(childElement);
+ }
}
}
}
@@ -156,6 +174,11 @@
return Util.equalArraysOrNull(this.names, other.names) &&
this.parent.equals(other.parent);
}
+public boolean exists() {
+ // super.exist() only checks for the parent and the resource existence
+ // so also ensure that the package is not exceluded (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=138577)
+ return super.exists() && !Util.isExcluded(this);
+}
/**
* @see IPackageFragment#getClassFile(String)
* @exception IllegalArgumentException if the name does not end with ".class"
@@ -164,7 +187,12 @@
if (!org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(classFileName)) {
throw new IllegalArgumentException(Messages.element_invalidClassFileName);
}
- return new ClassFile(this, classFileName);
+ // don't hold on the .class file extension to save memory
+ // also make sure to not use substring as the resulting String may hold on the underlying char[] which might be much bigger than necessary
+ int length = classFileName.length() - 6;
+ char[] nameWithoutExtension = new char[length];
+ classFileName.getChars(0, length, nameWithoutExtension, 0);
+ return new ClassFile(this, new String(nameWithoutExtension));
}
/**
* Returns a the collection of class files in this - a folder package fragment which has a root
@@ -430,4 +458,37 @@
}
}
}
+/*
+ * @see IJavaElement#getAttachedJavadoc(IProgressMonitor)
+ */
+public String getAttachedJavadoc(IProgressMonitor monitor) throws JavaModelException {
+ PerProjectInfo projectInfo = JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(this.getJavaProject().getProject());
+ String cachedJavadoc = null;
+ synchronized (projectInfo.javadocCache) {
+ cachedJavadoc = (String) projectInfo.javadocCache.get(this);
+ }
+ if (cachedJavadoc != null) {
+ return cachedJavadoc;
+ }
+ URL baseLocation= getJavadocBaseLocation();
+ if (baseLocation == null) {
+ return null;
+ }
+ StringBuffer pathBuffer = new StringBuffer(baseLocation.toExternalForm());
+
+ if (!(pathBuffer.charAt(pathBuffer.length() - 1) == '/')) {
+ pathBuffer.append('/');
+ }
+ String packPath= this.getElementName().replace('.', '/');
+ pathBuffer.append(packPath).append('/').append(JavadocConstants.PACKAGE_FILE_NAME);
+
+ if (monitor != null && monitor.isCanceled()) throw new OperationCanceledException();
+ final String contents = getURLContents(String.valueOf(pathBuffer));
+ if (monitor != null && monitor.isCanceled()) throw new OperationCanceledException();
+ if (contents == null) throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.CANNOT_RETRIEVE_ATTACHED_JAVADOC, this));
+ synchronized (projectInfo.javadocCache) {
+ projectInfo.javadocCache.put(this, contents);
+ }
+ return contents;
+}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentInfo.java
index 14704a4..f256bff 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentInfo.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java
index 0896050..ab2825c 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -15,13 +15,7 @@
import java.util.Map;
import org.eclipse.core.resources.*;
-import org.eclipse.core.resources.IContainer;
-import org.eclipse.core.resources.IFolder;
-import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.*;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.*;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.core.util.MementoTokenizer;
@@ -41,11 +35,7 @@
/*
* No source attachment property
*/
- protected final static String NO_SOURCE_ATTACHMENT = ""; //$NON-NLS-1$
- /*
- * No source mapper singleton
- */
- protected final static SourceMapper NO_SOURCE_MAPPER = new SourceMapper();
+ public final static String NO_SOURCE_ATTACHMENT = ""; //$NON-NLS-1$
/**
* The resource associated with this root.
@@ -113,9 +103,6 @@
// check if source path is valid
Object target = JavaModel.getTarget(workspace.getRoot(), sourcePath, false);
if (target == null) {
- if (monitor != null) {
- monitor.done();
- }
throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INVALID_PATH, sourcePath));
}
SourceMapper mapper = createSourceMapper(sourcePath, rootPath);
@@ -126,10 +113,11 @@
setSourceMapper(mapper);
}
if (sourcePath == null) {
- setSourceAttachmentProperty(null); //remove the property
+ Util.setSourceAttachmentProperty(getPath(), null); //remove the property
} else {
//set the property to the path of the mapped source
- setSourceAttachmentProperty(
+ Util.setSourceAttachmentProperty(
+ getPath(),
sourcePath.toString()
+ (rootPath == null ? "" : (ATTACHMENT_PROPERTY_DELIMITER + rootPath.toString()))); //$NON-NLS-1$
}
@@ -151,7 +139,7 @@
}
}
} catch (JavaModelException e) {
- setSourceAttachmentProperty(null); // loose info - will be recomputed
+ Util.setSourceAttachmentProperty(getPath(), null); // loose info - will be recomputed
throw e;
} finally {
if (monitor != null) {
@@ -211,7 +199,7 @@
IContainer rootFolder = (IContainer) underlyingResource;
char[][] inclusionPatterns = fullInclusionPatternChars();
char[][] exclusionPatterns = fullExclusionPatternChars();
- computeFolderChildren(rootFolder, !Util.isExcluded(rootFolder, inclusionPatterns, exclusionPatterns), CharOperation.NO_STRINGS, vChildren, inclusionPatterns, exclusionPatterns); //$NON-NLS-1$
+ computeFolderChildren(rootFolder, !Util.isExcluded(rootFolder, inclusionPatterns, exclusionPatterns), CharOperation.NO_STRINGS, vChildren, inclusionPatterns, exclusionPatterns);
IJavaElement[] children = new IJavaElement[vChildren.size()];
vChildren.toArray(children);
info.setChildren(children);
@@ -241,35 +229,39 @@
JavaModelManager manager = JavaModelManager.getJavaModelManager();
IResource[] members = folder.members();
boolean hasIncluded = isIncluded;
- for (int i = 0, max = members.length; i < max; i++) {
- IResource member = members[i];
- String memberName = member.getName();
+ int length = members.length;
+ if (length >0) {
+ String sourceLevel = javaProject.getOption(JavaCore.COMPILER_SOURCE, true);
+ String complianceLevel = javaProject.getOption(JavaCore.COMPILER_COMPLIANCE, true);
+ for (int i = 0; i < length; i++) {
+ IResource member = members[i];
+ String memberName = member.getName();
- switch(member.getType()) {
+ switch(member.getType()) {
- case IResource.FOLDER:
- if (Util.isValidFolderNameForPackage(memberName)) {
- boolean isMemberIncluded = !Util.isExcluded(member, inclusionPatterns, exclusionPatterns);
- // keep looking inside as long as included already, or may have child included due to inclusion patterns
- if (isMemberIncluded || inclusionPatterns != null) {
- // eliminate binary output only if nested inside direct subfolders
- if (javaProject.contains(member)) {
- String[] newNames = Util.arrayConcat(pkgName, manager.intern(memberName));
- computeFolderChildren((IFolder) member, isMemberIncluded, newNames, vChildren, inclusionPatterns, exclusionPatterns);
- }
- }
- }
- break;
- case IResource.FILE:
- // inclusion filter may only include files, in which case we still want to include the immediate parent package (lazily)
- if (!hasIncluded
- && Util.isValidCompilationUnitName(memberName)
+ case IResource.FOLDER:
+ // recurse into sub folders even even parent not included as a sub folder could be included
+ // (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=65637)
+ if (Util.isValidFolderNameForPackage(memberName, sourceLevel, complianceLevel)) {
+ // eliminate binary output only if nested inside direct subfolders
+ if (javaProject.contains(member)) {
+ String[] newNames = Util.arrayConcat(pkgName, manager.intern(memberName));
+ boolean isMemberIncluded = !Util.isExcluded(member, inclusionPatterns, exclusionPatterns);
+ computeFolderChildren((IFolder) member, isMemberIncluded, newNames, vChildren, inclusionPatterns, exclusionPatterns);
+ }
+ }
+ break;
+ case IResource.FILE:
+ // inclusion filter may only include files, in which case we still want to include the immediate parent package (lazily)
+ if (!hasIncluded
+ && Util.isValidCompilationUnitName(memberName, sourceLevel, complianceLevel)
&& !Util.isExcluded(member, inclusionPatterns, exclusionPatterns)) {
- hasIncluded = true;
- IPackageFragment pkg = getPackageFragment(pkgName);
- vChildren.add(pkg);
- }
- break;
+ hasIncluded = true;
+ IPackageFragment pkg = getPackageFragment(pkgName);
+ vChildren.add(pkg);
+ }
+ break;
+ }
}
}
} catch(IllegalArgumentException e){
@@ -319,12 +311,9 @@
* not exist.
*/
protected int determineKind(IResource underlyingResource) throws JavaModelException {
- IClasspathEntry[] entries= ((JavaProject)getJavaProject()).getResolvedClasspath(true);
- for (int i= 0; i < entries.length; i++) {
- IClasspathEntry entry= entries[i];
- if (entry.getPath().equals(underlyingResource.getFullPath())) {
- return entry.getContentKind();
- }
+ IClasspathEntry entry = ((JavaProject)getJavaProject()).getClasspathEntryFor(underlyingResource.getFullPath());
+ if (entry != null) {
+ return entry.getContentKind();
}
return IPackageFragmentRoot.K_SOURCE;
}
@@ -341,7 +330,7 @@
if (!(o instanceof PackageFragmentRoot))
return false;
PackageFragmentRoot other = (PackageFragmentRoot) o;
- return this.resource.equals(other.resource) &&
+ return getResource().equals(other.getResource()) &&
this.parent.equals(other.parent);
}
@@ -352,7 +341,7 @@
return super.exists() && validateOnClasspath().isOK();
}
-public IClasspathEntry findSourceAttachmentRecommendation() {
+private IClasspathEntry findSourceAttachmentRecommendation() {
try {
IPath rootPath = this.getPath();
IClasspathEntry entry;
@@ -465,8 +454,9 @@
}
}
public String getElementName() {
- if (this.resource instanceof IFolder)
- return ((IFolder) this.resource).getName();
+ IResource res = getResource();
+ if (res instanceof IFolder)
+ return ((IFolder) res).getName();
return ""; //$NON-NLS-1$
}
/**
@@ -589,10 +579,13 @@
IClasspathEntry rawEntry = null;
JavaProject project = (JavaProject)this.getJavaProject();
- project.getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/); // force the reverse rawEntry cache to be populated
- JavaModelManager.PerProjectInfo perProjectInfo = project.getPerProjectInfo();
- if (perProjectInfo != null && perProjectInfo.resolvedPathToRawEntries != null) {
- rawEntry = (IClasspathEntry) perProjectInfo.resolvedPathToRawEntries.get(this.getPath());
+ project.getResolvedClasspath(); // force the reverse rawEntry cache to be populated
+ Map rootPathToRawEntries = project.getPerProjectInfo().rootPathToRawEntries;
+ if (rootPathToRawEntries != null) {
+ rawEntry = (IClasspathEntry) rootPathToRawEntries.get(this.getPath());
+ }
+ if (rawEntry == null) {
+ throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_NOT_ON_CLASSPATH, this));
}
return rawEntry;
}
@@ -610,69 +603,33 @@
public IPath getSourceAttachmentPath() throws JavaModelException {
if (getKind() != K_BINARY) return null;
- String serverPathString= getSourceAttachmentProperty();
- if (serverPathString == null) {
- return null;
- }
- int index= serverPathString.lastIndexOf(ATTACHMENT_PROPERTY_DELIMITER);
- if (index < 0) {
- // no root path specified
- return new Path(serverPathString);
- } else {
- String serverSourcePathString= serverPathString.substring(0, index);
- return new Path(serverSourcePathString);
- }
-}
-
-/**
- * Returns the server property for this package fragment root's
- * source attachement.
- */
-protected String getSourceAttachmentProperty() throws JavaModelException {
- String propertyString = null;
- QualifiedName qName= getSourceAttachmentPropertyName();
- try {
- propertyString = ResourcesPlugin.getWorkspace().getRoot().getPersistentProperty(qName);
-
- // if no existing source attachment information, then lookup a recommendation from classpath entries
- if (propertyString == null) {
- IClasspathEntry recommendation = findSourceAttachmentRecommendation();
- if (recommendation != null) {
- IPath rootPath = recommendation.getSourceAttachmentRootPath();
- propertyString =
- recommendation.getSourceAttachmentPath().toString()
- + ((rootPath == null)
- ? "" : //$NON-NLS-1$
- (ATTACHMENT_PROPERTY_DELIMITER + rootPath.toString()));
- setSourceAttachmentProperty(propertyString);
- } else {
- // mark as being already looked up
- setSourceAttachmentProperty(NO_SOURCE_ATTACHMENT);
- }
- } else if (NO_SOURCE_ATTACHMENT.equals(propertyString)) {
- // already looked up and no source attachment found
- return null;
+ // 1) look source attachment property (set iff attachSource(...) was called
+ IPath path = getPath();
+ String serverPathString= Util.getSourceAttachmentProperty(path);
+ if (serverPathString != null) {
+ int index= serverPathString.lastIndexOf(ATTACHMENT_PROPERTY_DELIMITER);
+ if (index < 0) {
+ // no root path specified
+ return new Path(serverPathString);
+ } else {
+ String serverSourcePathString= serverPathString.substring(0, index);
+ return new Path(serverSourcePathString);
}
- return propertyString;
- } catch (CoreException ce) {
- throw new JavaModelException(ce);
}
-}
-
-/**
- * Returns the qualified name for the source attachment property
- * of this root.
- */
-protected QualifiedName getSourceAttachmentPropertyName() {
- return new QualifiedName(JavaCore.PLUGIN_ID, "sourceattachment: " + this.getPath().toOSString()); //$NON-NLS-1$
-}
-public void setSourceAttachmentProperty(String property) {
- try {
- ResourcesPlugin.getWorkspace().getRoot().setPersistentProperty(this.getSourceAttachmentPropertyName(), property);
- } catch (CoreException ce) {
- // ignore
+ // 2) look at classpath entry
+ IClasspathEntry entry = ((JavaProject) getParent()).getClasspathEntryFor(path);
+ IPath sourceAttachmentPath;
+ if (entry != null && (sourceAttachmentPath = entry.getSourceAttachmentPath()) != null)
+ return sourceAttachmentPath;
+
+ // 3) look for a recommendation
+ entry = findSourceAttachmentRecommendation();
+ if (entry != null && (sourceAttachmentPath = entry.getSourceAttachmentPath()) != null) {
+ return sourceAttachmentPath;
}
+
+ return null;
}
/**
@@ -691,17 +648,31 @@
public IPath getSourceAttachmentRootPath() throws JavaModelException {
if (getKind() != K_BINARY) return null;
- String serverPathString= getSourceAttachmentProperty();
- if (serverPathString == null) {
- return null;
+ // 1) look source attachment property (set iff attachSource(...) was called
+ IPath path = getPath();
+ String serverPathString= Util.getSourceAttachmentProperty(path);
+ if (serverPathString != null) {
+ int index = serverPathString.lastIndexOf(ATTACHMENT_PROPERTY_DELIMITER);
+ if (index == -1) return null;
+ String serverRootPathString= IPackageFragmentRoot.DEFAULT_PACKAGEROOT_PATH;
+ if (index != serverPathString.length() - 1) {
+ serverRootPathString= serverPathString.substring(index + 1);
+ }
+ return new Path(serverRootPathString);
}
- int index = serverPathString.lastIndexOf(ATTACHMENT_PROPERTY_DELIMITER);
- if (index == -1) return null;
- String serverRootPathString= IPackageFragmentRoot.DEFAULT_PACKAGEROOT_PATH;
- if (index != serverPathString.length() - 1) {
- serverRootPathString= serverPathString.substring(index + 1);
- }
- return new Path(serverRootPathString);
+
+ // 2) look at classpath entry
+ IClasspathEntry entry = ((JavaProject) getParent()).getClasspathEntryFor(path);
+ IPath sourceAttachmentRootPath;
+ if (entry != null && (sourceAttachmentRootPath = entry.getSourceAttachmentRootPath()) != null)
+ return sourceAttachmentRootPath;
+
+ // 3) look for a recomendation
+ entry = findSourceAttachmentRecommendation();
+ if (entry != null && (sourceAttachmentRootPath = entry.getSourceAttachmentRootPath()) != null)
+ return sourceAttachmentRootPath;
+
+ return null;
}
/**
@@ -715,28 +686,12 @@
if (mapper == null) {
// first call to this method
IPath sourcePath= getSourceAttachmentPath();
- if (sourcePath != null) {
- IPath rootPath= getSourceAttachmentRootPath();
- mapper = this.createSourceMapper(sourcePath, rootPath);
- if (rootPath == null && mapper.rootPath != null) {
- // as a side effect of calling the SourceMapper constructor, the root path was computed
- rootPath = new Path(mapper.rootPath);
-
- //set the property to the path of the mapped source
- this.setSourceAttachmentProperty(
- sourcePath.toString()
- + ATTACHMENT_PROPERTY_DELIMITER
- + rootPath.toString());
- }
- rootInfo.setSourceMapper(mapper);
- } else {
- // remember that no source is attached
- rootInfo.setSourceMapper(NO_SOURCE_MAPPER);
- mapper = null;
- }
- } else if (mapper == NO_SOURCE_MAPPER) {
- // a previous call to this method found out that no source was attached
- mapper = null;
+ IPath rootPath= getSourceAttachmentRootPath();
+ if (sourcePath == null)
+ mapper = createSourceMapper(getPath(), rootPath); // attach root to itself
+ else
+ mapper = createSourceMapper(sourcePath, rootPath);
+ rootInfo.setSourceMapper(mapper);
}
} catch (JavaModelException e) {
// no source can be attached
@@ -762,7 +717,7 @@
}
public int hashCode() {
- return this.resource.hashCode();
+ return getResource().hashCode();
}
/**
@@ -788,12 +743,9 @@
try {
// check package fragment root on classpath of its project
JavaProject project = (JavaProject) getJavaProject();
- IClasspathEntry[] classpath = project.getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/);
- for (int i = 0, length = classpath.length; i < length; i++) {
- IClasspathEntry entry = classpath[i];
- if (entry.getPath().equals(path)) {
- return Status.OK_STATUS;
- }
+ IClasspathEntry entry = project.getClasspathEntryFor(path);
+ if (entry != null) {
+ return Status.OK_STATUS;
}
} catch(JavaModelException e){
// could not read classpath, then assume it is outside
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRootInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRootInfo.java
index caa9645..22cf527 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRootInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRootInfo.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -16,9 +16,6 @@
import org.eclipse.core.runtime.IPath;
import org.eclipse.jdt.core.*;
-import org.eclipse.jdt.core.IPackageFragmentRoot;
-import org.eclipse.jdt.core.IJavaProject;
-import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.core.util.Util;
/**
@@ -60,39 +57,43 @@
Object[] nonJavaResources = new IResource[5];
int nonJavaResourcesCounter = 0;
try {
- IClasspathEntry[] classpath = project.getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/);
+ IClasspathEntry[] classpath = project.getResolvedClasspath();
IResource[] members = folder.members();
- nextResource: for (int i = 0, max = members.length; i < max; i++) {
- IResource member = members[i];
- switch (member.getType()) {
- case IResource.FILE :
- String fileName = member.getName();
+ int length = members.length;
+ if (length > 0) {
+ String sourceLevel = project.getOption(JavaCore.COMPILER_SOURCE, true);
+ String complianceLevel = project.getOption(JavaCore.COMPILER_COMPLIANCE, true);
+ nextResource: for (int i = 0; i < length; i++) {
+ IResource member = members[i];
+ switch (member.getType()) {
+ case IResource.FILE :
+ String fileName = member.getName();
- // ignore .java files that are not excluded
- if (Util.isValidCompilationUnitName(fileName) && !Util.isExcluded(member, inclusionPatterns, exclusionPatterns))
- continue nextResource;
- // ignore .class files
- if (Util.isValidClassFileName(fileName))
- continue nextResource;
- // ignore .zip or .jar file on classpath
- if (org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(fileName) && isClasspathEntry(member.getFullPath(), classpath))
- continue nextResource;
- break;
+ // ignore .java files that are not excluded
+ if (Util.isValidCompilationUnitName(fileName, sourceLevel, complianceLevel) && !Util.isExcluded(member, inclusionPatterns, exclusionPatterns))
+ continue nextResource;
+ // ignore .class files
+ if (Util.isValidClassFileName(fileName, sourceLevel, complianceLevel))
+ continue nextResource;
+ // ignore .zip or .jar file on classpath
+ if (org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(fileName) && isClasspathEntry(member.getFullPath(), classpath))
+ continue nextResource;
+ break;
- case IResource.FOLDER :
- // ignore valid packages or excluded folders that correspond to a nested pkg fragment root
- if (Util.isValidFolderNameForPackage(member.getName())
- && (!Util.isExcluded(member, inclusionPatterns, exclusionPatterns)
- || isClasspathEntry(member.getFullPath(), classpath)))
- continue nextResource;
- break;
- }
- if (nonJavaResources.length == nonJavaResourcesCounter) {
- // resize
- System.arraycopy(nonJavaResources, 0, (nonJavaResources = new IResource[nonJavaResourcesCounter * 2]), 0, nonJavaResourcesCounter);
- }
- nonJavaResources[nonJavaResourcesCounter++] = member;
-
+ case IResource.FOLDER :
+ // ignore valid packages or excluded folders that correspond to a nested pkg fragment root
+ if (Util.isValidFolderNameForPackage(member.getName(), sourceLevel, complianceLevel)
+ && (!Util.isExcluded(member, inclusionPatterns, exclusionPatterns)
+ || isClasspathEntry(member.getFullPath(), classpath)))
+ continue nextResource;
+ break;
+ }
+ if (nonJavaResources.length == nonJavaResourcesCounter) {
+ // resize
+ System.arraycopy(nonJavaResources, 0, (nonJavaResources = new IResource[nonJavaResourcesCounter * 2]), 0, nonJavaResourcesCounter);
+ }
+ nonJavaResources[nonJavaResourcesCounter++] = member;
+ }
}
if (nonJavaResources.length != nonJavaResourcesCounter) {
System.arraycopy(nonJavaResources, 0, (nonJavaResources = new IResource[nonJavaResourcesCounter]), 0, nonJavaResourcesCounter);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ProjectReferenceChange.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ProjectReferenceChange.java
new file mode 100755
index 0000000..e0ff9c4
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ProjectReferenceChange.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core;
+
+import java.util.HashSet;
+import java.util.Iterator;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.core.util.Util;
+
+public class ProjectReferenceChange {
+
+ private JavaProject project;
+ private IClasspathEntry[] oldResolvedClasspath;
+
+ public ProjectReferenceChange(JavaProject project, IClasspathEntry[] oldResolvedClasspath) {
+ this.project = project;
+ this.oldResolvedClasspath = oldResolvedClasspath;
+ }
+
+ /*
+ * Update projects references so that the build order is consistent with the classpath
+ */
+ public void updateProjectReferencesIfNecessary() throws JavaModelException {
+
+ String[] oldRequired = this.oldResolvedClasspath == null ? CharOperation.NO_STRINGS : this.project.projectPrerequisites(this.oldResolvedClasspath);
+ IClasspathEntry[] newResolvedClasspath = this.project.getResolvedClasspath();
+ String[] newRequired = this.project.projectPrerequisites(newResolvedClasspath);
+ try {
+ IProject projectResource = this.project.getProject();
+ IProjectDescription description = projectResource.getDescription();
+
+ IProject[] projectReferences = description.getDynamicReferences();
+
+ HashSet oldReferences = new HashSet(projectReferences.length);
+ for (int i = 0; i < projectReferences.length; i++){
+ String projectName = projectReferences[i].getName();
+ oldReferences.add(projectName);
+ }
+ HashSet newReferences = (HashSet)oldReferences.clone();
+
+ for (int i = 0; i < oldRequired.length; i++){
+ String projectName = oldRequired[i];
+ newReferences.remove(projectName);
+ }
+ for (int i = 0; i < newRequired.length; i++){
+ String projectName = newRequired[i];
+ newReferences.add(projectName);
+ }
+
+ Iterator iter;
+ int newSize = newReferences.size();
+
+ checkIdentity: {
+ if (oldReferences.size() == newSize){
+ iter = newReferences.iterator();
+ while (iter.hasNext()){
+ if (!oldReferences.contains(iter.next())){
+ break checkIdentity;
+ }
+ }
+ return;
+ }
+ }
+ String[] requiredProjectNames = new String[newSize];
+ int index = 0;
+ iter = newReferences.iterator();
+ while (iter.hasNext()){
+ requiredProjectNames[index++] = (String)iter.next();
+ }
+ Util.sort(requiredProjectNames); // ensure that if changed, the order is consistent
+
+ IProject[] requiredProjectArray = new IProject[newSize];
+ IWorkspaceRoot wksRoot = projectResource.getWorkspace().getRoot();
+ for (int i = 0; i < newSize; i++){
+ requiredProjectArray[i] = wksRoot.getProject(requiredProjectNames[i]);
+ }
+ description.setDynamicReferences(requiredProjectArray);
+ projectResource.setDescription(description, null);
+
+ } catch(CoreException e){
+ if (!ExternalJavaProject.EXTERNAL_PROJECT_NAME.equals(this.project.getElementName()))
+ throw new JavaModelException(e);
+ }
+ }
+ public String toString() {
+ return "ProjectRefenceChange: " + this.project.getElementName(); //$NON-NLS-1$
+ }
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ReconcileWorkingCopyOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ReconcileWorkingCopyOperation.java
index 3cec2ff..82756ac 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ReconcileWorkingCopyOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ReconcileWorkingCopyOperation.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,104 +10,255 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core;
+import java.util.HashMap;
+import java.util.Iterator;
import java.util.Map;
+import org.eclipse.core.runtime.ISafeRunnable;
import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.jdt.core.*;
-import org.eclipse.jdt.core.IJavaElement;
-import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.compiler.CategorizedProblem;
+import org.eclipse.jdt.core.compiler.CompilationParticipant;
+import org.eclipse.jdt.core.compiler.ReconcileContext;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.core.util.Messages;
+import org.eclipse.jdt.internal.core.util.Util;
/**
* Reconcile a working copy and signal the changes through a delta.
+ * <p>
+ * High level summmary of what a reconcile does:
+ * <ul>
+ * <li>populates the model with the new working copy contents</li>
+ * <li>fires a fine grained delta (flag F_FINE_GRAINED) describing the difference between the previous content
+ * and the new content (which method was added/removed, which field was changed, etc.)</li>
+ * <li>computes problems and reports them to the IProblemRequestor (begingReporting(), n x acceptProblem(...), endReporting()) iff
+ * (working copy is not consistent with its buffer || forceProblemDetection is set)
+ * && problem requestor is active
+ * </li>
+ * <li>produces a DOM AST (either JLS_2, JLS_3 or NO_AST) that is resolved if flag is set</li>
+ * <li>notifies compilation participants of the reconcile allowing them to participate in this operation and report problems</li>
+ * </ul>
*/
public class ReconcileWorkingCopyOperation extends JavaModelOperation {
public static boolean PERF = false;
-
- boolean createAST;
- int astLevel;
- boolean forceProblemDetection;
+
+ public int astLevel;
+ public boolean resolveBindings;
+ public HashMap problems;
+ public int reconcileFlags;
WorkingCopyOwner workingCopyOwner;
- org.eclipse.jdt.core.dom.CompilationUnit ast;
-
- public ReconcileWorkingCopyOperation(IJavaElement workingCopy, boolean creatAST, int astLevel, boolean forceProblemDetection, WorkingCopyOwner workingCopyOwner) {
+ public org.eclipse.jdt.core.dom.CompilationUnit ast;
+ public JavaElementDeltaBuilder deltaBuilder;
+ public boolean requestorIsActive;
+
+ public ReconcileWorkingCopyOperation(IJavaElement workingCopy, int astLevel, int reconcileFlags, WorkingCopyOwner workingCopyOwner) {
super(new IJavaElement[] {workingCopy});
- this.createAST = creatAST;
this.astLevel = astLevel;
- this.forceProblemDetection = forceProblemDetection;
+ this.reconcileFlags = reconcileFlags;
this.workingCopyOwner = workingCopyOwner;
}
+
/**
* @exception JavaModelException if setting the source
* of the original compilation unit fails
*/
protected void executeOperation() throws JavaModelException {
- if (this.progressMonitor != null){
- if (this.progressMonitor.isCanceled())
- throw new OperationCanceledException();
- this.progressMonitor.beginTask(Messages.element_reconciling, 2);
- }
-
- CompilationUnit workingCopy = getWorkingCopy();
- boolean wasConsistent = workingCopy.isConsistent();
+ checkCanceled();
try {
- if (!wasConsistent) {
- // create the delta builder (this remembers the current content of the cu)
- JavaElementDeltaBuilder deltaBuilder = new JavaElementDeltaBuilder(workingCopy);
-
- // update the element infos with the content of the working copy
- this.ast = workingCopy.makeConsistent(this.createAST, this.astLevel, this.progressMonitor);
- deltaBuilder.buildDeltas();
+ beginTask(Messages.element_reconciling, 2);
- if (progressMonitor != null) progressMonitor.worked(2);
-
- // register the deltas
- if (deltaBuilder.delta != null) {
- addReconcileDelta(workingCopy, deltaBuilder.delta);
+ CompilationUnit workingCopy = getWorkingCopy();
+ boolean wasConsistent = workingCopy.isConsistent();
+
+ // check is problem requestor is active
+ IProblemRequestor problemRequestor = workingCopy.getPerWorkingCopyInfo();
+ if (problemRequestor != null)
+ problemRequestor = ((JavaModelManager.PerWorkingCopyInfo)problemRequestor).getProblemRequestor();
+ boolean defaultRequestorIsActive = problemRequestor != null && problemRequestor.isActive();
+ IProblemRequestor ownerProblemRequestor = this.workingCopyOwner.getProblemRequestor(workingCopy);
+ boolean ownerRequestorIsActive = ownerProblemRequestor != null && ownerProblemRequestor != problemRequestor && ownerProblemRequestor.isActive();
+ this.requestorIsActive = defaultRequestorIsActive || ownerRequestorIsActive;
+
+ // create the delta builder (this remembers the current content of the cu)
+ this.deltaBuilder = new JavaElementDeltaBuilder(workingCopy);
+
+ // make working copy consistent if needed and compute AST if needed
+ makeConsistent(workingCopy);
+
+ // notify reconcile participants only if working copy was not consistent or if forcing problem detection
+ // (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=177319)
+ if (!wasConsistent || ((this.reconcileFlags & ICompilationUnit.FORCE_PROBLEM_DETECTION) != 0)) {
+ notifyParticipants(workingCopy);
+
+ // recreate ast if one participant reset it
+ if (this.ast == null)
+ makeConsistent(workingCopy);
+ }
+
+ // report problems
+ if (this.problems != null && (((this.reconcileFlags & ICompilationUnit.FORCE_PROBLEM_DETECTION) != 0) || !wasConsistent)) {
+ if (defaultRequestorIsActive) {
+ reportProblems(workingCopy, problemRequestor);
}
- } else {
- // force problem detection? - if structure was consistent
- if (forceProblemDetection) {
- IProblemRequestor problemRequestor = workingCopy.getPerWorkingCopyInfo();
- if (problemRequestor != null && problemRequestor.isActive()) {
- CompilationUnitDeclaration unit = null;
- try {
- problemRequestor.beginReporting();
- char[] contents = workingCopy.getContents();
- unit = CompilationUnitProblemFinder.process(workingCopy, contents, this.workingCopyOwner, problemRequestor, !this.createAST/*reset env if not creating AST*/, this.progressMonitor);
- problemRequestor.endReporting();
- if (progressMonitor != null) progressMonitor.worked(1);
- if (this.createAST && unit != null) {
- Map options = workingCopy.getJavaProject().getOptions(true);
- this.ast = AST.convertCompilationUnit(this.astLevel, unit, contents, options, true/*isResolved*/, workingCopy, this.progressMonitor);
- if (progressMonitor != null) progressMonitor.worked(1);
- }
- } finally {
- if (unit != null) {
- unit.cleanUp();
- }
- }
+ if (ownerRequestorIsActive) {
+ reportProblems(workingCopy, ownerProblemRequestor);
+ }
+ }
+
+ // report delta
+ JavaElementDelta delta = this.deltaBuilder.delta;
+ if (delta != null) {
+ addReconcileDelta(workingCopy, delta);
+ }
+ } finally {
+ done();
+ }
+ }
+
+ /**
+ * Report working copy problems to a given requestor.
+ *
+ * @param workingCopy
+ * @param problemRequestor
+ */
+ private void reportProblems(CompilationUnit workingCopy, IProblemRequestor problemRequestor) {
+ try {
+ problemRequestor.beginReporting();
+ for (Iterator iteraror = this.problems.values().iterator(); iteraror.hasNext();) {
+ CategorizedProblem[] categorizedProblems = (CategorizedProblem[]) iteraror.next();
+ if (categorizedProblems == null) continue;
+ for (int i = 0, length = categorizedProblems.length; i < length; i++) {
+ CategorizedProblem problem = categorizedProblems[i];
+ if (JavaModelManager.VERBOSE){
+ System.out.println("PROBLEM FOUND while reconciling : " + problem.getMessage());//$NON-NLS-1$
}
+ if (this.progressMonitor != null && this.progressMonitor.isCanceled()) break;
+ problemRequestor.acceptProblem(problem);
}
}
} finally {
- if (progressMonitor != null) progressMonitor.done();
+ problemRequestor.endReporting();
}
}
+
/**
* Returns the working copy this operation is working on.
*/
protected CompilationUnit getWorkingCopy() {
return (CompilationUnit)getElementToProcess();
}
- /**
- * @see JavaModelOperation#isReadOnly
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.core.JavaModelOperation#isReadOnly()
*/
public boolean isReadOnly() {
return true;
}
+
+ /*
+ * Makes the given working copy consistent, computes the delta and computes an AST if needed.
+ * Returns the AST.
+ */
+ public org.eclipse.jdt.core.dom.CompilationUnit makeConsistent(CompilationUnit workingCopy) throws JavaModelException {
+ if (!workingCopy.isConsistent()) {
+ // make working copy consistent
+ if (this.problems == null) this.problems = new HashMap();
+ this.resolveBindings = this.requestorIsActive;
+ this.ast = workingCopy.makeConsistent(this.astLevel, this.resolveBindings, reconcileFlags, this.problems, this.progressMonitor);
+ this.deltaBuilder.buildDeltas();
+ if (this.ast != null && this.deltaBuilder.delta != null)
+ this.deltaBuilder.delta.changedAST(this.ast);
+ return this.ast;
+ }
+ if (this.ast != null)
+ return this.ast; // no need to recompute AST if known already
+
+ CompilationUnitDeclaration unit = null;
+ char[] contents = null;
+ try {
+ // find problems if needed
+ if (JavaProject.hasJavaNature(workingCopy.getJavaProject().getProject())
+ && (this.reconcileFlags & ICompilationUnit.FORCE_PROBLEM_DETECTION) != 0) {
+ this.resolveBindings = this.requestorIsActive;
+ if (this.problems == null)
+ this.problems = new HashMap();
+ contents = workingCopy.getContents();
+ unit =
+ CompilationUnitProblemFinder.process(
+ workingCopy,
+ contents,
+ this.workingCopyOwner,
+ this.problems,
+ this.astLevel != ICompilationUnit.NO_AST/*creating AST if level is not NO_AST */,
+ reconcileFlags,
+ this.progressMonitor);
+ if (this.progressMonitor != null) this.progressMonitor.worked(1);
+ }
+
+ // create AST if needed
+ if (this.astLevel != ICompilationUnit.NO_AST
+ && unit !=null/*unit is null if working copy is consistent && (problem detection not forced || non-Java project) -> don't create AST as per API*/) {
+ Map options = workingCopy.getJavaProject().getOptions(true);
+ // convert AST
+ this.ast =
+ AST.convertCompilationUnit(
+ this.astLevel,
+ unit,
+ contents,
+ options,
+ this.resolveBindings,
+ workingCopy,
+ reconcileFlags,
+ this.progressMonitor);
+ if (this.ast != null) {
+ this.deltaBuilder.delta = new JavaElementDelta(workingCopy);
+ this.deltaBuilder.delta.changedAST(this.ast);
+ }
+ if (this.progressMonitor != null) this.progressMonitor.worked(1);
+ }
+ } catch (JavaModelException e) {
+ if (JavaProject.hasJavaNature(workingCopy.getJavaProject().getProject()))
+ throw e;
+ // else JavaProject has lost its nature (or most likely was closed/deleted) while reconciling -> ignore
+ // (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=100919)
+ } finally {
+ if (unit != null) {
+ unit.cleanUp();
+ }
+ }
+ return this.ast;
+ }
+
+ private void notifyParticipants(final CompilationUnit workingCopy) {
+ IJavaProject javaProject = getWorkingCopy().getJavaProject();
+ CompilationParticipant[] participants = JavaModelManager.getJavaModelManager().compilationParticipants.getCompilationParticipants(javaProject);
+ if (participants == null) return;
+
+ final ReconcileContext context = new ReconcileContext(this, workingCopy);
+ for (int i = 0, length = participants.length; i < length; i++) {
+ final CompilationParticipant participant = participants[i];
+ SafeRunner.run(new ISafeRunnable() {
+ public void handleException(Throwable exception) {
+ if (exception instanceof Error) {
+ throw (Error) exception; // errors are not supposed to be caught
+ } else if (exception instanceof OperationCanceledException)
+ throw (OperationCanceledException) exception;
+ else if (exception instanceof UnsupportedOperationException) {
+ // might want to disable participant as it tried to modify the buffer of the working copy being reconciled
+ Util.log(exception, "Reconcile participant attempted to modify the buffer of the working copy being reconciled"); //$NON-NLS-1$
+ } else
+ Util.log(exception, "Exception occurred in reconcile participant"); //$NON-NLS-1$
+ }
+ public void run() throws Exception {
+ participant.reconcile(context);
+ }
+ });
+ }
+ }
+
protected IJavaModelStatus verify() {
IJavaModelStatus status = super.verify();
if (!status.isOK()) {
@@ -120,5 +271,4 @@
return status;
}
-
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Region.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Region.java
index 4bb5ece..b35d79b 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Region.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Region.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -16,7 +16,6 @@
import org.eclipse.jdt.core.IParent;
import org.eclipse.jdt.core.IRegion;
-
/**
* @see IRegion
*/
@@ -110,7 +109,7 @@
*
* <p>Children are all children, not just direct children.
*/
-private void removeAllChildren(IJavaElement element) {
+protected void removeAllChildren(IJavaElement element) {
if (element instanceof IParent) {
ArrayList newRootElements = new ArrayList();
for (int i = 0, size = fRootElements.size(); i < size; i++) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/RenameElementsOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/RenameElementsOperation.java
index 352fe23..5bf4076 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/RenameElementsOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/RenameElementsOperation.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -65,8 +65,6 @@
* @see MultiOperation
*/
protected void verify(IJavaElement element) throws JavaModelException {
- int elementType = element.getElementType();
-
if (element == null || !element.exists())
error(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, element);
@@ -76,6 +74,7 @@
if (!(element instanceof ISourceReference))
error(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, element);
+ int elementType = element.getElementType();
if (elementType < IJavaElement.TYPE || elementType == IJavaElement.INITIALIZER)
error(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, element);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/RenameResourceElementsOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/RenameResourceElementsOperation.java
index 1879091..d48ff1a 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/RenameResourceElementsOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/RenameResourceElementsOperation.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ResolvedBinaryField.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ResolvedBinaryField.java
index 3e24250..81c0793 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ResolvedBinaryField.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ResolvedBinaryField.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -51,4 +51,10 @@
buffer.append("}"); //$NON-NLS-1$
}
}
+
+ public JavaElement unresolved() {
+ SourceRefElement handle = new BinaryField(this.parent, this.name);
+ handle.occurrenceCount = this.occurrenceCount;
+ return handle;
+ }
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ResolvedBinaryMethod.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ResolvedBinaryMethod.java
index 5c68ee4..aff1171 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ResolvedBinaryMethod.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ResolvedBinaryMethod.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -37,6 +37,7 @@
public boolean isResolved() {
return true;
}
+
/**
* @private Debugging purposes
*/
@@ -48,4 +49,10 @@
buffer.append("}"); //$NON-NLS-1$
}
}
+
+ public JavaElement unresolved() {
+ SourceRefElement handle = new BinaryMethod(this.parent, this.name, this.parameterTypes);
+ handle.occurrenceCount = this.occurrenceCount;
+ return handle;
+ }
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ResolvedBinaryType.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ResolvedBinaryType.java
index 90b3553..b1cc4ad 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ResolvedBinaryType.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ResolvedBinaryType.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -57,4 +57,10 @@
buffer.append("}"); //$NON-NLS-1$
}
}
+
+ public JavaElement unresolved() {
+ SourceRefElement handle = new BinaryType(this.parent, this.name);
+ handle.occurrenceCount = this.occurrenceCount;
+ return handle;
+ }
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ResolvedSourceField.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ResolvedSourceField.java
index ec7e24d..d710f04 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ResolvedSourceField.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ResolvedSourceField.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -51,4 +51,10 @@
buffer.append("}"); //$NON-NLS-1$
}
}
+
+ public JavaElement unresolved() {
+ SourceRefElement handle = new SourceField(this.parent, this.name);
+ handle.occurrenceCount = this.occurrenceCount;
+ return handle;
+ }
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ResolvedSourceMethod.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ResolvedSourceMethod.java
index 3ba8dba..1b67651 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ResolvedSourceMethod.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ResolvedSourceMethod.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -38,6 +38,7 @@
public boolean isResolved() {
return true;
}
+
/**
* @private Debugging purposes
*/
@@ -49,4 +50,10 @@
buffer.append("}"); //$NON-NLS-1$
}
}
+
+ public JavaElement unresolved() {
+ SourceRefElement handle = new SourceMethod(this.parent, this.name, this.parameterTypes);
+ handle.occurrenceCount = this.occurrenceCount;
+ return handle;
+ }
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ResolvedSourceType.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ResolvedSourceType.java
index b61905c..59c4e6d 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ResolvedSourceType.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ResolvedSourceType.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004, 2005 IBM Corporation and others.
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -57,4 +57,10 @@
buffer.append("}"); //$NON-NLS-1$
}
}
+
+ public JavaElement unresolved() {
+ SourceRefElement handle = new SourceType(this.parent, this.name);
+ handle.occurrenceCount = this.occurrenceCount;
+ return handle;
+ }
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironment.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironment.java
index 4da06fa..45acefc 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironment.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironment.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -13,17 +13,10 @@
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.jdt.core.*;
-import org.eclipse.jdt.core.IJavaElement;
-import org.eclipse.jdt.core.IPackageFragment;
-import org.eclipse.jdt.core.IType;
-import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.search.*;
-import org.eclipse.jdt.core.search.IJavaSearchConstants;
-import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.internal.codeassist.ISearchRequestor;
import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
-import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
import org.eclipse.jdt.internal.compiler.env.IBinaryType;
import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
@@ -74,6 +67,24 @@
this(project, owner == null ? null : JavaModelManager.getJavaModelManager().getWorkingCopies(owner, true/*add primary WCs*/));
}
+ private static int convertSearchFilterToModelFilter(int searchFilter) {
+ switch (searchFilter) {
+ case IJavaSearchConstants.CLASS:
+ return NameLookup.ACCEPT_CLASSES;
+ case IJavaSearchConstants.INTERFACE:
+ return NameLookup.ACCEPT_INTERFACES;
+ case IJavaSearchConstants.ENUM:
+ return NameLookup.ACCEPT_ENUMS;
+ case IJavaSearchConstants.ANNOTATION_TYPE:
+ return NameLookup.ACCEPT_ANNOTATIONS;
+ case IJavaSearchConstants.CLASS_AND_ENUM:
+ return NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_ENUMS;
+ case IJavaSearchConstants.CLASS_AND_INTERFACE:
+ return NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES;
+ default:
+ return NameLookup.ACCEPT_ALL;
+ }
+ }
/**
* Returns the given type in the the given package if it exists,
* otherwise <code>null</code>.
@@ -81,43 +92,25 @@
protected NameEnvironmentAnswer find(String typeName, String packageName) {
if (packageName == null)
packageName = IPackageFragment.DEFAULT_PACKAGE_NAME;
- IType type =
+ NameLookup.Answer answer =
this.nameLookup.findType(
typeName,
packageName,
- false,
- NameLookup.ACCEPT_ALL);
- if (type != null) {
- boolean isBinary = type instanceof BinaryType;
-
- // determine associated access restriction
- AccessRestriction accessRestriction = null;
-
- if (this.checkAccessRestrictions && (isBinary || !type.getJavaProject().equals(this.project))) {
- PackageFragmentRoot root = (PackageFragmentRoot)type.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
- ClasspathEntry entry = (ClasspathEntry) this.nameLookup.rootToResolvedEntries.get(root);
- if (entry != null) { // reverse map always contains resolved CP entry
- AccessRuleSet accessRuleSet = entry.getAccessRuleSet();
- if (accessRuleSet != null) {
- // TODO (philippe) improve char[] <-> String conversions to avoid performing them on the fly
- char[][] packageChars = CharOperation.splitOn('.', packageName.toCharArray());
- char[] classFileChars = type.getElementName().toCharArray();
- accessRestriction = accessRuleSet.getViolatedRestriction(CharOperation.concatWith(packageChars, classFileChars, '/'));
- }
- }
- }
-
+ false/*exact match*/,
+ NameLookup.ACCEPT_ALL,
+ this.checkAccessRestrictions);
+ if (answer != null) {
// construct name env answer
- if (isBinary) { // BinaryType
+ if (answer.type instanceof BinaryType) { // BinaryType
try {
- return new NameEnvironmentAnswer((IBinaryType) ((BinaryType) type).getElementInfo(), accessRestriction);
+ return new NameEnvironmentAnswer((IBinaryType) ((BinaryType) answer.type).getElementInfo(), answer.restriction);
} catch (JavaModelException npe) {
return null;
}
} else { //SourceType
try {
// retrieve the requested type
- SourceTypeElementInfo sourceType = (SourceTypeElementInfo)((SourceType)type).getElementInfo();
+ SourceTypeElementInfo sourceType = (SourceTypeElementInfo)((SourceType) answer.type).getElementInfo();
ISourceType topLevelType = sourceType;
while (topLevelType.getEnclosingType() != null) {
topLevelType = topLevelType.getEnclosingType();
@@ -135,7 +128,7 @@
if (!otherType.equals(topLevelType) && index < length) // check that the index is in bounds (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=62861)
sourceTypes[index++] = otherType;
}
- return new NameEnvironmentAnswer(sourceTypes, accessRestriction);
+ return new NameEnvironmentAnswer(sourceTypes, answer.restriction);
} catch (JavaModelException npe) {
return null;
}
@@ -159,6 +152,107 @@
}
/**
+ * Find the top-level types that are defined
+ * in the current environment and whose simple name matches the given name.
+ *
+ * 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.
+ */
+ public void findExactTypes(char[] name, final boolean findMembers, int searchFor, final ISearchRequestor storage) {
+
+ try {
+ final String excludePath;
+ if (this.unitToSkip != null) {
+ if (!(this.unitToSkip instanceof IJavaElement)) {
+ // revert to model investigation
+ findExactTypes(
+ new String(name),
+ storage,
+ convertSearchFilterToModelFilter(searchFor));
+ return;
+ }
+ excludePath = ((IJavaElement) this.unitToSkip).getPath().toString();
+ } else {
+ excludePath = null;
+ }
+
+ IProgressMonitor progressMonitor = new IProgressMonitor() {
+ boolean isCanceled = false;
+ public void beginTask(String n, int totalWork) {
+ // implements interface method
+ }
+ public void done() {
+ // implements interface method
+ }
+ public void internalWorked(double work) {
+ // implements interface method
+ }
+ public boolean isCanceled() {
+ return isCanceled;
+ }
+ public void setCanceled(boolean value) {
+ isCanceled = value;
+ }
+ public void setTaskName(String n) {
+ // implements interface method
+ }
+ public void subTask(String n) {
+ // implements interface method
+ }
+ public void worked(int work) {
+ // implements interface method
+ }
+ };
+ IRestrictedAccessTypeRequestor typeRequestor = new IRestrictedAccessTypeRequestor() {
+ public void acceptType(int modifiers, char[] packageName, char[] simpleTypeName, char[][] enclosingTypeNames, String path, AccessRestriction access) {
+ if (excludePath != null && excludePath.equals(path))
+ return;
+ if (!findMembers && enclosingTypeNames != null && enclosingTypeNames.length > 0)
+ return; // accept only top level types
+ storage.acceptType(packageName, simpleTypeName, enclosingTypeNames, modifiers, access);
+ }
+ };
+ try {
+ new BasicSearchEngine(this.workingCopies).searchAllTypeNames(
+ null,
+ SearchPattern.R_EXACT_MATCH,
+ name,
+ SearchPattern.R_EXACT_MATCH,
+ searchFor,
+ this.searchScope,
+ typeRequestor,
+ CANCEL_IF_NOT_READY_TO_SEARCH,
+ progressMonitor);
+ } catch (OperationCanceledException e) {
+ findExactTypes(
+ new String(name),
+ storage,
+ convertSearchFilterToModelFilter(searchFor));
+ }
+ } catch (JavaModelException e) {
+ findExactTypes(
+ new String(name),
+ storage,
+ convertSearchFilterToModelFilter(searchFor));
+ }
+ }
+
+ /**
+ * Returns all types whose simple name matches with the given <code>name</code>.
+ */
+ private void findExactTypes(String name, ISearchRequestor storage, int type) {
+ SearchableEnvironmentRequestor requestor =
+ new SearchableEnvironmentRequestor(storage, this.unitToSkip, this.project, this.nameLookup);
+ this.nameLookup.seekTypes(name, null, false, type, requestor);
+ }
+
+ /**
* @see org.eclipse.jdt.internal.compiler.env.INameEnvironment#findType(char[][])
*/
public NameEnvironmentAnswer findType(char[][] compoundTypeName) {
@@ -191,7 +285,7 @@
}
/**
- * Find the top-level types (classes and interfaces) that are defined
+ * Find the top-level types 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).
@@ -205,7 +299,7 @@
* This method can not be used to find member types... member
* types are found relative to their enclosing type.
*/
- public void findTypes(char[] prefix, final boolean findMembers, final ISearchRequestor storage) {
+ public void findTypes(char[] prefix, final boolean findMembers, boolean camelCaseMatch, int searchFor, final ISearchRequestor storage) {
/*
if (true){
@@ -221,7 +315,7 @@
findTypes(
new String(prefix),
storage,
- NameLookup.ACCEPT_ALL);
+ convertSearchFilterToModelFilter(searchFor));
return;
}
excludePath = ((IJavaElement) this.unitToSkip).getPath().toString();
@@ -232,12 +326,20 @@
char[] qualification, simpleName;
if (lastDotIndex < 0) {
qualification = null;
- simpleName = CharOperation.toLowerCase(prefix);
+ if (camelCaseMatch) {
+ simpleName = prefix;
+ } else {
+ simpleName = CharOperation.toLowerCase(prefix);
+ }
} else {
qualification = CharOperation.subarray(prefix, 0, lastDotIndex);
- simpleName =
- CharOperation.toLowerCase(
- CharOperation.subarray(prefix, lastDotIndex + 1, prefix.length));
+ if (camelCaseMatch) {
+ simpleName = CharOperation.subarray(prefix, lastDotIndex + 1, prefix.length);
+ } else {
+ simpleName =
+ CharOperation.toLowerCase(
+ CharOperation.subarray(prefix, lastDotIndex + 1, prefix.length));
+ }
}
IProgressMonitor progressMonitor = new IProgressMonitor() {
@@ -277,11 +379,14 @@
}
};
try {
+ int matchRule = SearchPattern.R_PREFIX_MATCH;
+ if (camelCaseMatch) matchRule |= SearchPattern.R_CAMELCASE_MATCH;
new BasicSearchEngine(this.workingCopies).searchAllTypeNames(
qualification,
+ SearchPattern.R_EXACT_MATCH,
simpleName,
- SearchPattern.R_PREFIX_MATCH, // not case sensitive
- IJavaSearchConstants.TYPE,
+ matchRule, // not case sensitive
+ searchFor,
this.searchScope,
typeRequestor,
CANCEL_IF_NOT_READY_TO_SEARCH,
@@ -290,13 +395,13 @@
findTypes(
new String(prefix),
storage,
- NameLookup.ACCEPT_ALL);
+ convertSearchFilterToModelFilter(searchFor));
}
} catch (JavaModelException e) {
findTypes(
new String(prefix),
storage,
- NameLookup.ACCEPT_ALL);
+ convertSearchFilterToModelFilter(searchFor));
}
}
@@ -307,6 +412,7 @@
* the <code>prefix</code> are returned.
*/
private void findTypes(String prefix, ISearchRequestor storage, int type) {
+ //TODO (david) should add camel case support
SearchableEnvironmentRequestor requestor =
new SearchableEnvironmentRequestor(storage, this.unitToSkip, this.project, this.nameLookup);
int index = prefix.lastIndexOf('.');
@@ -330,22 +436,17 @@
* @see org.eclipse.jdt.internal.compiler.env.INameEnvironment#isPackage(char[][], char[])
*/
public boolean isPackage(char[][] parentPackageName, char[] subPackageName) {
- if (subPackageName == null || CharOperation.contains('.', subPackageName))
- return false;
- if (parentPackageName == null || parentPackageName.length == 0)
- return isTopLevelPackage(subPackageName);
- for (int i = 0, length = parentPackageName.length; i < length; i++)
- if (parentPackageName[i] == null || CharOperation.contains('.', parentPackageName[i]))
- return false;
-
- String packageName = new String(CharOperation.concatWith(parentPackageName, subPackageName, '.'));
- return this.nameLookup.findPackageFragments(packageName, false) != null;
- }
-
- public boolean isTopLevelPackage(char[] packageName) {
- return packageName != null &&
- !CharOperation.contains('.', packageName) &&
- this.nameLookup.findPackageFragments(new String(packageName), false) != null;
+ String[] pkgName;
+ if (parentPackageName == null)
+ pkgName = new String[] {new String(subPackageName)};
+ else {
+ int length = parentPackageName.length;
+ pkgName = new String[length+1];
+ for (int i = 0; i < length; i++)
+ pkgName[i] = new String(parentPackageName[i]);
+ pkgName[length] = new String(subPackageName);
+ }
+ return this.nameLookup.isPackage(pkgName);
}
/**
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SelectionRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SelectionRequestor.java
index bc53cd2..d7b741c 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SelectionRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SelectionRequestor.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -24,11 +24,10 @@
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.compiler.*;
-import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.internal.codeassist.ISelectionRequestor;
import org.eclipse.jdt.internal.codeassist.SelectionEngine;
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
-import org.eclipse.jdt.internal.compiler.env.IConstants;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
import org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
@@ -36,6 +35,8 @@
import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
+import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
import org.eclipse.jdt.internal.core.util.HandleFactory;
import org.eclipse.jdt.internal.core.util.Util;
@@ -59,7 +60,7 @@
*/
protected IJavaElement[] elements = JavaElement.NO_ELEMENTS;
protected int elementIndex = -1;
-
+
protected HandleFactory handleFactory = new HandleFactory();
/**
@@ -73,26 +74,91 @@
this.nameLookup = nameLookup;
this.openable = openable;
}
+private void acceptBinaryMethod(
+ IType type,
+ IMethod method,
+ char[] uniqueKey,
+ boolean isConstructor) {
+ try {
+ if(!isConstructor || ((JavaElement)method).getSourceMapper() == null) {
+ if (uniqueKey != null) {
+ ResolvedBinaryMethod resolvedMethod = new ResolvedBinaryMethod(
+ (JavaElement)method.getParent(),
+ method.getElementName(),
+ method.getParameterTypes(),
+ new String(uniqueKey));
+ resolvedMethod.occurrenceCount = method.getOccurrenceCount();
+ method = resolvedMethod;
+ }
+
+ addElement(method);
+ if(SelectionEngine.DEBUG){
+ System.out.print("SELECTION - accept method("); //$NON-NLS-1$
+ System.out.print(method.toString());
+ System.out.println(")"); //$NON-NLS-1$
+ }
+ } else {
+ ISourceRange range = method.getSourceRange();
+ if (range.getOffset() != -1 && range.getLength() != 0 ) {
+ if (uniqueKey != null) {
+ ResolvedBinaryMethod resolvedMethod = new ResolvedBinaryMethod(
+ (JavaElement)method.getParent(),
+ method.getElementName(),
+ method.getParameterTypes(),
+ new String(uniqueKey));
+ resolvedMethod.occurrenceCount = method.getOccurrenceCount();
+ method = resolvedMethod;
+ }
+ addElement(method);
+ if(SelectionEngine.DEBUG){
+ System.out.print("SELECTION - accept method("); //$NON-NLS-1$
+ System.out.print(method.toString());
+ System.out.println(")"); //$NON-NLS-1$
+ }
+ } else {
+ // no range was actually found, but a method was originally given -> default constructor
+ addElement(type);
+ if(SelectionEngine.DEBUG){
+ System.out.print("SELECTION - accept type("); //$NON-NLS-1$
+ System.out.print(type.toString());
+ System.out.println(")"); //$NON-NLS-1$
+ }
+ }
+ }
+ } catch (JavaModelException e) {
+ // an exception occurs, return nothing
+ }
+}
/**
* Resolve the binary method
*
* fix for 1FWFT6Q
*/
-protected void acceptBinaryMethod(IType type, char[] selector, char[][] parameterPackageNames, char[][] parameterTypeNames, String[] parameterSignatures, char[] uniqueKey) {
+protected void acceptBinaryMethod(
+ IType type,
+ char[] selector,
+ char[][] parameterPackageNames,
+ char[][] parameterTypeNames,
+ String[] parameterSignatures,
+ char[][] typeParameterNames,
+ char[][][] typeParameterBoundNames,
+ char[] uniqueKey,
+ boolean isConstructor) {
IMethod method= type.getMethod(new String(selector), parameterSignatures);
+
if (method.exists()) {
- if (uniqueKey != null)
- method = new ResolvedBinaryMethod(
- (JavaElement)method.getParent(),
- method.getElementName(),
- method.getParameterTypes(),
- new String(uniqueKey));
- addElement(method);
- if(SelectionEngine.DEBUG){
- System.out.print("SELECTION - accept method("); //$NON-NLS-1$
- System.out.print(method.toString());
- System.out.println(")"); //$NON-NLS-1$
+ if (typeParameterNames != null && typeParameterNames.length != 0) {
+ IMethod[] methods = type.findMethods(method);
+ if (methods.length > 1) {
+ for (int i = 0; i < methods.length; i++) {
+ if (areTypeParametersCompatible(methods[i], typeParameterNames, typeParameterBoundNames)) {
+ acceptBinaryMethod(type, method, uniqueKey, isConstructor);
+ }
+ }
+ return;
+ }
}
+ acceptBinaryMethod(type, method, uniqueKey, isConstructor);
}
}
/**
@@ -100,16 +166,16 @@
*/
public void acceptType(char[] packageName, char[] typeName, int modifiers, boolean isDeclaration, char[] uniqueKey, int start, int end) {
int acceptFlags = 0;
- int kind = modifiers & (IConstants.AccInterface+IConstants.AccEnum+IConstants.AccAnnotation);
+ int kind = modifiers & (ClassFileConstants.AccInterface|ClassFileConstants.AccEnum|ClassFileConstants.AccAnnotation);
switch (kind) {
- case IConstants.AccAnnotation:
- case IConstants.AccAnnotation+IConstants.AccInterface:
+ case ClassFileConstants.AccAnnotation:
+ case ClassFileConstants.AccAnnotation|ClassFileConstants.AccInterface:
acceptFlags = NameLookup.ACCEPT_ANNOTATIONS;
break;
- case IConstants.AccEnum:
+ case ClassFileConstants.AccEnum:
acceptFlags = NameLookup.ACCEPT_ENUMS;
break;
- case IConstants.AccInterface:
+ case ClassFileConstants.AccInterface:
acceptFlags = NameLookup.ACCEPT_INTERFACES;
break;
default:
@@ -124,13 +190,17 @@
if(type != null ) {
String key = uniqueKey == null ? type.getKey() : new String(uniqueKey);
if(type.isBinary()) {
- type = new ResolvedBinaryType((JavaElement)type.getParent(), type.getElementName(), key);
+ ResolvedBinaryType resolvedType = new ResolvedBinaryType((JavaElement)type.getParent(), type.getElementName(), key);
+ resolvedType.occurrenceCount = type.getOccurrenceCount();
+ type = resolvedType;
} else {
- type = new ResolvedSourceType((JavaElement)type.getParent(), type.getElementName(), key);
+ ResolvedSourceType resolvedType = new ResolvedSourceType((JavaElement)type.getParent(), type.getElementName(), key);
+ resolvedType.occurrenceCount = type.getOccurrenceCount();
+ type = resolvedType;
}
}
}
-
+
if (type != null) {
addElement(type);
if(SelectionEngine.DEBUG){
@@ -138,12 +208,12 @@
System.out.print(type.toString());
System.out.println(")"); //$NON-NLS-1$
}
- }
+ }
}
/**
* @see ISelectionRequestor#acceptError
*/
-public void acceptError(IProblem error) {
+public void acceptError(CategorizedProblem error) {
// do nothing
}
/**
@@ -173,7 +243,7 @@
}
}
} catch (JavaModelException e) {
- return;
+ return;
}
}
} else {
@@ -183,15 +253,19 @@
if (field.exists()) {
if (uniqueKey != null) {
if(field.isBinary()) {
- field = new ResolvedBinaryField(
+ ResolvedBinaryField resolvedField = new ResolvedBinaryField(
(JavaElement)field.getParent(),
field.getElementName(),
new String(uniqueKey));
+ resolvedField.occurrenceCount = field.getOccurrenceCount();
+ field = resolvedField;
} else {
- field = new ResolvedSourceField(
+ ResolvedSourceField resolvedField = new ResolvedSourceField(
(JavaElement)field.getParent(),
field.getElementName(),
new String(uniqueKey));
+ resolvedField.occurrenceCount = field.getOccurrenceCount();
+ field = resolvedField;
}
}
addElement(field);
@@ -207,7 +281,7 @@
public void acceptLocalField(FieldBinding fieldBinding) {
IJavaElement res;
if(fieldBinding.declaringClass instanceof ParameterizedTypeBinding) {
- LocalTypeBinding localTypeBinding = (LocalTypeBinding)((ParameterizedTypeBinding)fieldBinding.declaringClass).type;
+ LocalTypeBinding localTypeBinding = (LocalTypeBinding)((ParameterizedTypeBinding)fieldBinding.declaringClass).genericType();
res = findLocalElement(localTypeBinding.sourceStart());
} else {
SourceTypeBinding typeBinding = (SourceTypeBinding)fieldBinding.declaringClass;
@@ -219,15 +293,19 @@
if (field.exists()) {
char[] uniqueKey = fieldBinding.computeUniqueKey();
if(field.isBinary()) {
- field = new ResolvedBinaryField(
+ ResolvedBinaryField resolvedField = new ResolvedBinaryField(
(JavaElement)field.getParent(),
field.getElementName(),
new String(uniqueKey));
+ resolvedField.occurrenceCount = field.getOccurrenceCount();
+ field = resolvedField;
} else {
- field = new ResolvedSourceField(
+ ResolvedSourceField resolvedField = new ResolvedSourceField(
(JavaElement)field.getParent(),
field.getElementName(),
new String(uniqueKey));
+ resolvedField.occurrenceCount = field.getOccurrenceCount();
+ field = resolvedField;
}
addElement(field);
if(SelectionEngine.DEBUG){
@@ -240,41 +318,56 @@
}
public void acceptLocalMethod(MethodBinding methodBinding) {
IJavaElement res = findLocalElement(methodBinding.sourceStart());
- if(res != null && res.getElementType() == IJavaElement.METHOD) {
- IMethod method = (IMethod) res;
-
- char[] uniqueKey = methodBinding.computeUniqueKey();
- if(method.isBinary()) {
- res = new ResolvedBinaryMethod(
- (JavaElement)res.getParent(),
- method.getElementName(),
- method.getParameterTypes(),
- new String(uniqueKey));
- } else {
- res = new ResolvedSourceMethod(
- (JavaElement)res.getParent(),
- method.getElementName(),
- method.getParameterTypes(),
- new String(uniqueKey));
- }
- addElement(res);
- if(SelectionEngine.DEBUG){
- System.out.print("SELECTION - accept method("); //$NON-NLS-1$
- System.out.print(res.toString());
- System.out.println(")"); //$NON-NLS-1$
+ if(res != null) {
+ if(res.getElementType() == IJavaElement.METHOD) {
+ IMethod method = (IMethod) res;
+
+ char[] uniqueKey = methodBinding.computeUniqueKey();
+ if(method.isBinary()) {
+ ResolvedBinaryMethod resolvedRes = new ResolvedBinaryMethod(
+ (JavaElement)res.getParent(),
+ method.getElementName(),
+ method.getParameterTypes(),
+ new String(uniqueKey));
+ resolvedRes.occurrenceCount = method.getOccurrenceCount();
+ res = resolvedRes;
+ } else {
+ ResolvedSourceMethod resolvedRes = new ResolvedSourceMethod(
+ (JavaElement)res.getParent(),
+ method.getElementName(),
+ method.getParameterTypes(),
+ new String(uniqueKey));
+ resolvedRes.occurrenceCount = method.getOccurrenceCount();
+ res = resolvedRes;
+ }
+ addElement(res);
+ if(SelectionEngine.DEBUG){
+ System.out.print("SELECTION - accept method("); //$NON-NLS-1$
+ System.out.print(res.toString());
+ System.out.println(")"); //$NON-NLS-1$
+ }
+ } else if(methodBinding.selector == TypeConstants.INIT && res.getElementType() == IJavaElement.TYPE) {
+ // it's a default constructor
+ res = ((JavaElement)res).resolved(methodBinding.declaringClass);
+ addElement(res);
+ if(SelectionEngine.DEBUG){
+ System.out.print("SELECTION - accept type("); //$NON-NLS-1$
+ System.out.print(res.toString());
+ System.out.println(")"); //$NON-NLS-1$
+ }
}
}
}
public void acceptLocalType(TypeBinding typeBinding) {
IJavaElement res = null;
if(typeBinding instanceof ParameterizedTypeBinding) {
- LocalTypeBinding localTypeBinding = (LocalTypeBinding)((ParameterizedTypeBinding)typeBinding).type;
+ LocalTypeBinding localTypeBinding = (LocalTypeBinding)((ParameterizedTypeBinding)typeBinding).genericType();
res = findLocalElement(localTypeBinding.sourceStart());
} else if(typeBinding instanceof SourceTypeBinding) {
res = findLocalElement(((SourceTypeBinding)typeBinding).sourceStart());
}
if(res != null && res.getElementType() == IJavaElement.TYPE) {
- res = new ResolvedSourceType((JavaElement)res.getParent(), res.getElementName(), new String(typeBinding.computeUniqueKey()));
+ res = ((JavaElement)res).resolved(typeBinding);
addElement(res);
if(SelectionEngine.DEBUG){
System.out.print("SELECTION - accept type("); //$NON-NLS-1$
@@ -283,14 +376,53 @@
}
}
}
+public void acceptLocalTypeParameter(TypeVariableBinding typeVariableBinding) {
+ IJavaElement res;
+ if(typeVariableBinding.declaringElement instanceof ParameterizedTypeBinding) {
+ LocalTypeBinding localTypeBinding = (LocalTypeBinding)((ParameterizedTypeBinding)typeVariableBinding.declaringElement).genericType();
+ res = findLocalElement(localTypeBinding.sourceStart());
+ } else {
+ SourceTypeBinding typeBinding = (SourceTypeBinding)typeVariableBinding.declaringElement;
+ res = findLocalElement(typeBinding.sourceStart());
+ }
+ if (res != null && res.getElementType() == IJavaElement.TYPE) {
+ IType type = (IType) res;
+ ITypeParameter typeParameter = type.getTypeParameter(new String(typeVariableBinding.sourceName));
+ if (typeParameter.exists()) {
+ addElement(typeParameter);
+ if(SelectionEngine.DEBUG){
+ System.out.print("SELECTION - accept type parameter("); //$NON-NLS-1$
+ System.out.print(typeParameter.toString());
+ System.out.println(")"); //$NON-NLS-1$
+ }
+ }
+ }
+}
+public void acceptLocalMethodTypeParameter(TypeVariableBinding typeVariableBinding) {
+ MethodBinding methodBinding = (MethodBinding)typeVariableBinding.declaringElement;
+ IJavaElement res = findLocalElement(methodBinding.sourceStart());
+ if(res != null && res.getElementType() == IJavaElement.METHOD) {
+ IMethod method = (IMethod) res;
+
+ ITypeParameter typeParameter = method.getTypeParameter(new String(typeVariableBinding.sourceName));
+ if (typeParameter.exists()) {
+ addElement(typeParameter);
+ if(SelectionEngine.DEBUG){
+ System.out.print("SELECTION - accept type parameter("); //$NON-NLS-1$
+ System.out.print(typeParameter.toString());
+ System.out.println(")"); //$NON-NLS-1$
+ }
+ }
+ }
+}
public void acceptLocalVariable(LocalVariableBinding binding) {
LocalDeclaration local = binding.declaration;
IJavaElement parent = findLocalElement(local.sourceStart); // findLocalElement() cannot find local variable
IJavaElement localVar = null;
if(parent != null) {
localVar = new LocalVariable(
- (JavaElement)parent,
- new String(local.name),
+ (JavaElement)parent,
+ new String(local.name),
local.declarationSourceStart,
local.declarationSourceEnd,
local.sourceStart,
@@ -309,17 +441,31 @@
/**
* Resolve the method
*/
-public void acceptMethod(char[] declaringTypePackageName, char[] declaringTypeName, String enclosingDeclaringTypeSignature, char[] selector, char[][] parameterPackageNames, char[][] parameterTypeNames, String[] parameterSignatures, boolean isConstructor, boolean isDeclaration, char[] uniqueKey, int start, int end) {
+public void acceptMethod(
+ char[] declaringTypePackageName,
+ char[] declaringTypeName,
+ String enclosingDeclaringTypeSignature,
+ char[] selector,
+ char[][] parameterPackageNames,
+ char[][] parameterTypeNames,
+ String[] parameterSignatures,
+ char[][] typeParameterNames,
+ char[][][] typeParameterBoundNames,
+ boolean isConstructor,
+ boolean isDeclaration,
+ char[] uniqueKey,
+ int start,
+ int end) {
IJavaElement[] previousElement = this.elements;
int previousElementIndex = this.elementIndex;
this.elements = JavaElement.NO_ELEMENTS;
this.elementIndex = -1;
-
+
if(isDeclaration) {
IType type = resolveTypeByLocation(declaringTypePackageName, declaringTypeName,
NameLookup.ACCEPT_ALL,
start, end);
-
+
if(type != null) {
this.acceptMethodDeclaration(type, selector, start, end);
}
@@ -329,35 +475,35 @@
// fix for 1FWFT6Q
if (type != null) {
if (type.isBinary()) {
-
+
// need to add a paramater for constructor in binary type
IType declaringDeclaringType = type.getDeclaringType();
-
+
boolean isStatic = false;
try {
isStatic = Flags.isStatic(type.getFlags());
} catch (JavaModelException e) {
// isStatic == false
}
-
+
if(declaringDeclaringType != null && isConstructor && !isStatic) {
int length = parameterPackageNames.length;
System.arraycopy(parameterPackageNames, 0, parameterPackageNames = new char[length+1][], 1, length);
System.arraycopy(parameterTypeNames, 0, parameterTypeNames = new char[length+1][], 1, length);
System.arraycopy(parameterSignatures, 0, parameterSignatures = new String[length+1], 1, length);
-
+
parameterPackageNames[0] = declaringDeclaringType.getPackageFragment().getElementName().toCharArray();
parameterTypeNames[0] = declaringDeclaringType.getTypeQualifiedName().toCharArray();
- parameterSignatures[0] = enclosingDeclaringTypeSignature;
+ parameterSignatures[0] = Signature.getTypeErasure(enclosingDeclaringTypeSignature);
}
-
- acceptBinaryMethod(type, selector, parameterPackageNames, parameterTypeNames, parameterSignatures, uniqueKey);
+
+ acceptBinaryMethod(type, selector, parameterPackageNames, parameterTypeNames, parameterSignatures, typeParameterNames, typeParameterBoundNames, uniqueKey, isConstructor);
} else {
- acceptSourceMethod(type, selector, parameterPackageNames, parameterTypeNames, uniqueKey);
+ acceptSourceMethod(type, selector, parameterPackageNames, parameterTypeNames, parameterSignatures, typeParameterNames, typeParameterBoundNames, uniqueKey);
}
}
}
-
+
if(previousElementIndex > -1) {
int elementsLength = this.elementIndex + previousElementIndex + 2;
if(elementsLength > this.elements.length) {
@@ -388,7 +534,16 @@
*
* fix for 1FWFT6Q
*/
-protected void acceptSourceMethod(IType type, char[] selector, char[][] parameterPackageNames, char[][] parameterTypeNames, char[] uniqueKey) {
+protected void acceptSourceMethod(
+ IType type,
+ char[] selector,
+ char[][] parameterPackageNames,
+ char[][] parameterTypeNames,
+ String[] parameterSignatures,
+ char[][] typeParameterNames,
+ char[][][] typeParameterBoundNames,
+ char[] uniqueKey) {
+
String name = new String(selector);
IMethod[] methods = null;
try {
@@ -397,17 +552,20 @@
if (methods[i].getElementName().equals(name)
&& methods[i].getParameterTypes().length == parameterTypeNames.length) {
IMethod method = methods[i];
- if (uniqueKey != null)
- method = new ResolvedSourceMethod(
+ if (uniqueKey != null) {
+ ResolvedSourceMethod resolvedMethod = new ResolvedSourceMethod(
(JavaElement)method.getParent(),
method.getElementName(),
method.getParameterTypes(),
new String(uniqueKey));
+ resolvedMethod.occurrenceCount = method.getOccurrenceCount();
+ method = resolvedMethod;
+ }
addElement(method);
}
}
} catch (JavaModelException e) {
- return;
+ return;
}
// if no matches, nothing to report
@@ -449,6 +607,11 @@
break;
}
}
+
+ if (match && !areTypeParametersCompatible(method, typeParameterNames, typeParameterBoundNames)) {
+ match = false;
+ }
+
if (match) {
addElement(method);
if(SelectionEngine.DEBUG){
@@ -458,7 +621,7 @@
}
}
}
-
+
}
protected void acceptMethodDeclaration(IType type, char[] selector, int start, int end) {
String name = new String(selector);
@@ -480,7 +643,7 @@
}
}
} catch (JavaModelException e) {
- return;
+ return;
}
// no match was actually found
@@ -502,7 +665,7 @@
type = resolveType(declaringTypePackageName, declaringTypeName,
NameLookup.ACCEPT_ALL);
}
-
+
if(type != null) {
ITypeParameter typeParameter = type.getTypeParameter(new String(typeParameterName));
if(typeParameter == null) {
@@ -526,13 +689,13 @@
IType type = resolveTypeByLocation(declaringTypePackageName, declaringTypeName,
NameLookup.ACCEPT_ALL,
selectorStart, selectorEnd);
-
+
if(type != null) {
IMethod method = null;
-
+
String name = new String(selector);
IMethod[] methods = null;
-
+
try {
methods = type.getMethods();
done : for (int i = 0; i < methods.length; i++) {
@@ -585,7 +748,45 @@
}
this.elements[++this.elementIndex] = element;
}
+private boolean areTypeParametersCompatible(IMethod method, char[][] typeParameterNames, char[][][] typeParameterBoundNames) {
+ try {
+ ITypeParameter[] typeParameters = method.getTypeParameters();
+ int length1 = typeParameters == null ? 0 : typeParameters.length;
+ int length2 = typeParameterNames == null ? 0 : typeParameterNames.length;
+ if (length1 != length2) {
+ return false;
+ } else {
+ for (int j = 0; j < length1; j++) {
+ ITypeParameter typeParameter = typeParameters[j];
+ String typeParameterName = typeParameter.getElementName();
+ if (!typeParameterName.equals(new String(typeParameterNames[j]))) {
+ return false;
+ }
+ String[] bounds = typeParameter.getBounds();
+ int boundCount = typeParameterBoundNames[j] == null ? 0 : typeParameterBoundNames[j].length;
+
+ if (bounds.length != boundCount) {
+ return false;
+ } else {
+ for (int k = 0; k < boundCount; k++) {
+ String simpleName = Signature.getSimpleName(bounds[k]);
+ int index = simpleName.indexOf('<');
+ if (index != -1) {
+ simpleName = simpleName.substring(0, index);
+ }
+ if (!simpleName.equals(new String(typeParameterBoundNames[j][k]))) {
+ return false;
+ }
+ }
+ }
+ }
+ }
+ } catch (JavaModelException e) {
+ return false;
+ }
+ return true;
+}
/*
* findLocalElement() cannot find local variable
*/
@@ -624,13 +825,13 @@
protected IType resolveType(char[] packageName, char[] typeName, int acceptFlags) {
IType type= null;
-
+
if (this.openable instanceof CompilationUnit && ((CompilationUnit)this.openable).isWorkingCopy()) {
CompilationUnit wc = (CompilationUnit) this.openable;
try {
if(((packageName == null || packageName.length == 0) && wc.getPackageDeclarations().length == 0) ||
(!(packageName == null || packageName.length == 0) && wc.getPackageDeclaration(new String(packageName)).exists())) {
-
+
char[][] compoundName = CharOperation.splitOn('.', typeName);
if(compoundName.length > 0) {
type = wc.getType(new String(compoundName[0]));
@@ -638,24 +839,24 @@
type = type.getType(new String(compoundName[i]));
}
}
-
+
if(type != null && !type.exists()) {
type = null;
}
}
}catch (JavaModelException e) {
- type = null;
+ // type is null
}
}
if(type == null) {
IPackageFragment[] pkgs = this.nameLookup.findPackageFragments(
- (packageName == null || packageName.length == 0) ? IPackageFragment.DEFAULT_PACKAGE_NAME : new String(packageName),
+ (packageName == null || packageName.length == 0) ? IPackageFragment.DEFAULT_PACKAGE_NAME : new String(packageName),
false);
// iterate type lookup in each package fragment
for (int i = 0, length = pkgs == null ? 0 : pkgs.length; i < length; i++) {
- type= this.nameLookup.findType(new String(typeName), pkgs[i], false, acceptFlags);
- if (type != null) break;
+ type= this.nameLookup.findType(new String(typeName), pkgs[i], false, acceptFlags, true/*consider secondary types*/);
+ if (type != null) break;
}
if (type == null) {
String pName= IPackageFragment.DEFAULT_PACKAGE_NAME;
@@ -687,17 +888,17 @@
protected IType resolveTypeByLocation(char[] packageName, char[] typeName, int acceptFlags, int start, int end) {
IType type= null;
-
+
// TODO (david) post 3.0 should remove isOpen check, and investigate reusing ICompilationUnit#getElementAt. may need to optimize #getElementAt to remove recursions
if (this.openable instanceof CompilationUnit && ((CompilationUnit)this.openable).isOpen()) {
CompilationUnit wc = (CompilationUnit) this.openable;
try {
if(((packageName == null || packageName.length == 0) && wc.getPackageDeclarations().length == 0) ||
(!(packageName == null || packageName.length == 0) && wc.getPackageDeclaration(new String(packageName)).exists())) {
-
+
char[][] compoundName = CharOperation.splitOn('.', typeName);
if(compoundName.length > 0) {
-
+
IType[] tTypes = wc.getTypes();
int i = 0;
int depth = 0;
@@ -718,24 +919,24 @@
i++;
}
}
-
+
if(type != null && !type.exists()) {
type = null;
}
}
}catch (JavaModelException e) {
- type = null;
+ // type is null
}
}
if(type == null) {
IPackageFragment[] pkgs = this.nameLookup.findPackageFragments(
- (packageName == null || packageName.length == 0) ? IPackageFragment.DEFAULT_PACKAGE_NAME : new String(packageName),
+ (packageName == null || packageName.length == 0) ? IPackageFragment.DEFAULT_PACKAGE_NAME : new String(packageName),
false);
// iterate type lookup in each package fragment
for (int i = 0, length = pkgs == null ? 0 : pkgs.length; i < length; i++) {
- type= this.nameLookup.findType(new String(typeName), pkgs[i], false, acceptFlags);
- if (type != null) break;
+ type= this.nameLookup.findType(new String(typeName), pkgs[i], false, acceptFlags, true/*consider secondary types*/);
+ if (type != null) break;
}
if (type == null) {
String pName= IPackageFragment.DEFAULT_PACKAGE_NAME;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SetClasspathOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SetClasspathOperation.java
index 704a8f1..d21117a 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SetClasspathOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SetClasspathOperation.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,830 +10,79 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core;
-import java.util.*;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Iterator;
-
-import org.eclipse.core.resources.IFolder;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.resources.IWorkspace;
-import org.eclipse.core.resources.ResourcesPlugin;
-import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaElement;
-import org.eclipse.jdt.core.IJavaElementDelta;
-import org.eclipse.jdt.core.IJavaModel;
import org.eclipse.jdt.core.IJavaModelStatus;
import org.eclipse.jdt.core.IJavaProject;
-import org.eclipse.jdt.core.IPackageFragment;
-import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaModelException;
-import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
-import org.eclipse.jdt.internal.compiler.util.ObjectVector;
-import org.eclipse.jdt.internal.core.search.indexing.IndexManager;
-import org.eclipse.jdt.internal.core.util.Messages;
-import org.eclipse.jdt.internal.core.util.Util;
-
/**
* This operation sets an <code>IJavaProject</code>'s classpath.
*
* @see IJavaProject
*/
-public class SetClasspathOperation extends JavaModelOperation {
+public class SetClasspathOperation extends ChangeClasspathOperation {
- IClasspathEntry[] oldResolvedPath, newResolvedPath;
- IClasspathEntry[] newRawPath;
- boolean canChangeResources;
- boolean classpathWasSaved;
- boolean needCycleCheck;
- boolean needValidation;
- boolean needSave;
+ IClasspathEntry[] newRawClasspath;
IPath newOutputLocation;
JavaProject project;
- boolean identicalRoots;
-
- /*
- * Used to indicate that the classpath entries remain the same.
- */
- public static final IClasspathEntry[] DO_NOT_SET_ENTRIES = new IClasspathEntry[0];
-
- public static final IClasspathEntry[] DO_NOT_UPDATE_PROJECT_REFS = new IClasspathEntry[0];
-
- /*
- * Used to indicate that the output location remains the same.
- */
- public static final IPath DO_NOT_SET_OUTPUT = new Path("Reuse Existing Output Location"); //$NON-NLS-1$
-
+
/**
- * When executed, this operation sets the classpath of the given project.
+ * When executed, this operation sets the raw classpath and output location of the given project.
*/
public SetClasspathOperation(
JavaProject project,
- IClasspathEntry[] oldResolvedPath,
- IClasspathEntry[] newRawPath,
+ IClasspathEntry[] newRawClasspath,
IPath newOutputLocation,
- boolean canChangeResource,
- boolean needValidation,
- boolean needSave) {
+ boolean canChangeResource) {
- super(new IJavaElement[] { project });
- this.oldResolvedPath = oldResolvedPath;
- this.newRawPath = newRawPath;
- this.newOutputLocation = newOutputLocation;
- this.canChangeResources = canChangeResource;
- this.needValidation = needValidation;
- this.needSave = needSave;
+ super(new IJavaElement[] { project }, canChangeResource);
this.project = project;
- }
-
- /**
- * Adds deltas for the given roots, with the specified change flag,
- * and closes the root. Helper method for #setClasspath
- */
- protected void addClasspathDeltas(
- IPackageFragmentRoot[] roots,
- int flag,
- JavaElementDelta delta) {
-
- for (int i = 0; i < roots.length; i++) {
- IPackageFragmentRoot root = roots[i];
- delta.changed(root, flag);
- if ((flag & IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) != 0
- || (flag & IJavaElementDelta.F_SOURCEATTACHED) != 0
- || (flag & IJavaElementDelta.F_SOURCEDETACHED) != 0){
- try {
- root.close();
- } catch (JavaModelException e) {
- // ignore
- }
- // force detach source on jar package fragment roots (source will be lazily computed when needed)
- ((PackageFragmentRoot) root).setSourceAttachmentProperty(null);// loose info - will be recomputed
- }
- }
- }
-
- protected boolean canModifyRoots() {
- // setting classpath can modify roots
- return true;
- }
-
- /**
- * Returns the index of the item in the list if the given list contains the specified entry. If the list does
- * not contain the entry, -1 is returned.
- * A helper method for #setClasspath
- */
- protected int classpathContains(
- IClasspathEntry[] list,
- IClasspathEntry entry) {
-
- IPath[] exclusionPatterns = entry.getExclusionPatterns();
- IPath[] inclusionPatterns = entry.getInclusionPatterns();
- nextEntry: for (int i = 0; i < list.length; i++) {
- IClasspathEntry other = list[i];
- if (other.getContentKind() == entry.getContentKind()
- && other.getEntryKind() == entry.getEntryKind()
- && other.isExported() == entry.isExported()
- && other.getPath().equals(entry.getPath())) {
- // check custom outputs
- IPath entryOutput = entry.getOutputLocation();
- IPath otherOutput = other.getOutputLocation();
- if (entryOutput == null) {
- if (otherOutput != null)
- continue;
- } else {
- if (!entryOutput.equals(otherOutput))
- continue;
- }
-
- // check inclusion patterns
- IPath[] otherIncludes = other.getInclusionPatterns();
- if (inclusionPatterns != otherIncludes) {
- if (inclusionPatterns == null) continue;
- int includeLength = inclusionPatterns.length;
- if (otherIncludes == null || otherIncludes.length != includeLength)
- continue;
- for (int j = 0; j < includeLength; j++) {
- // compare toStrings instead of IPaths
- // since IPath.equals is specified to ignore trailing separators
- if (!inclusionPatterns[j].toString().equals(otherIncludes[j].toString()))
- continue nextEntry;
- }
- }
- // check exclusion patterns
- IPath[] otherExcludes = other.getExclusionPatterns();
- if (exclusionPatterns != otherExcludes) {
- if (exclusionPatterns == null) continue;
- int excludeLength = exclusionPatterns.length;
- if (otherExcludes == null || otherExcludes.length != excludeLength)
- continue;
- for (int j = 0; j < excludeLength; j++) {
- // compare toStrings instead of IPaths
- // since IPath.equals is specified to ignore trailing separators
- if (!exclusionPatterns[j].toString().equals(otherExcludes[j].toString()))
- continue nextEntry;
- }
- }
- return i;
- }
- }
- return -1;
- }
-
- /**
- * Recursively adds all subfolders of <code>folder</code> to the given collection.
- */
- protected void collectAllSubfolders(IFolder folder, ArrayList collection) throws JavaModelException {
- try {
- IResource[] members= folder.members();
- for (int i = 0, max = members.length; i < max; i++) {
- IResource r= members[i];
- if (r.getType() == IResource.FOLDER) {
- collection.add(r);
- collectAllSubfolders((IFolder)r, collection);
- }
- }
- } catch (CoreException e) {
- throw new JavaModelException(e);
- }
- }
-
- /**
- * Returns a collection of package fragments that have been added/removed
- * as the result of changing the output location to/from the given
- * location. The collection is empty if no package fragments are
- * affected.
- */
- protected ArrayList determineAffectedPackageFragments(IPath location) throws JavaModelException {
- ArrayList fragments = new ArrayList();
-
- // see if this will cause any package fragments to be affected
- IWorkspace workspace = ResourcesPlugin.getWorkspace();
- IResource resource = null;
- if (location != null) {
- resource = workspace.getRoot().findMember(location);
- }
- if (resource != null && resource.getType() == IResource.FOLDER) {
- IFolder folder = (IFolder) resource;
- // only changes if it actually existed
- IClasspathEntry[] classpath = project.getExpandedClasspath(true);
- for (int i = 0; i < classpath.length; i++) {
- IClasspathEntry entry = classpath[i];
- IPath path = classpath[i].getPath();
- if (entry.getEntryKind() != IClasspathEntry.CPE_PROJECT && path.isPrefixOf(location) && !path.equals(location)) {
- IPackageFragmentRoot[] roots = project.computePackageFragmentRoots(classpath[i]);
- PackageFragmentRoot root = (PackageFragmentRoot) roots[0];
- // now the output location becomes a package fragment - along with any subfolders
- ArrayList folders = new ArrayList();
- folders.add(folder);
- collectAllSubfolders(folder, folders);
- Iterator elements = folders.iterator();
- int segments = path.segmentCount();
- while (elements.hasNext()) {
- IFolder f = (IFolder) elements.next();
- IPath relativePath = f.getFullPath().removeFirstSegments(segments);
- String[] pkgName = relativePath.segments();
- IPackageFragment pkg = root.getPackageFragment(pkgName);
- fragments.add(pkg);
- }
- }
- }
- }
- return fragments;
+ this.newRawClasspath = newRawClasspath;
+ this.newOutputLocation = newOutputLocation;
}
/**
* Sets the classpath of the pre-specified project.
*/
protected void executeOperation() throws JavaModelException {
- // project reference updated - may throw an exception if unable to write .project file
- updateProjectReferencesIfNecessary();
-
- // classpath file updated - may throw an exception if unable to write .classpath file
- saveClasspathIfNecessary();
-
- // perform classpath and output location updates, if exception occurs in classpath update,
- // make sure the output location is updated before surfacing the exception (in case the output
- // location update also throws an exception, give priority to the classpath update one).
- JavaModelException originalException = null;
-
+ checkCanceled();
try {
- if (this.newRawPath == DO_NOT_UPDATE_PROJECT_REFS) this.newRawPath = project.getRawClasspath();
- if (this.newRawPath != DO_NOT_SET_ENTRIES){
- updateClasspath();
- project.updatePackageFragmentRoots();
- JavaModelManager.getJavaModelManager().getDeltaProcessor().addForRefresh(project);
- }
-
- } catch(JavaModelException e){
- originalException = e;
- throw e;
-
- } finally { // if traversed by an exception we still need to update the output location when necessary
-
- try {
- if (this.newOutputLocation != DO_NOT_SET_OUTPUT) updateOutputLocation();
-
- } catch(JavaModelException e){
- if (originalException != null) throw originalException;
- throw e;
- } finally {
- // ensures the project is getting rebuilt if only variable is modified
- if (!this.identicalRoots && this.canChangeResources) {
- try {
- this.project.getProject().touch(this.progressMonitor);
- } catch (CoreException e) {
- if (JavaModelManager.CP_RESOLVE_VERBOSE){
- Util.verbose("CPContainer INIT - FAILED to touch project: "+ this.project.getElementName(), System.err); //$NON-NLS-1$
- e.printStackTrace();
- }
- }
- }
- }
- }
- done();
- }
-
- /**
- * Generates the delta of removed/added/reordered roots.
- * Use three deltas in case the same root is removed/added/reordered (for
- * instance, if it is changed from K_SOURCE to K_BINARY or vice versa)
- */
- protected void generateClasspathChangeDeltas() {
-
- JavaModelManager manager = JavaModelManager.getJavaModelManager();
- boolean needToUpdateDependents = false;
- JavaElementDelta delta = new JavaElementDelta(getJavaModel());
- boolean hasDelta = false;
- if (this.classpathWasSaved) {
- delta.changed(this.project, IJavaElementDelta.F_CLASSPATH_CHANGED);
- hasDelta = true;
- }
- int oldLength = oldResolvedPath.length;
- int newLength = newResolvedPath.length;
+ // set raw classpath and null out resolved info
+ this.project.getPerProjectInfo().setClasspath(this.newRawClasspath, this.newOutputLocation, JavaModelStatus.VERIFIED_OK/*format is ok*/, null, null, null, null);
- final IndexManager indexManager = manager.getIndexManager();
- Map oldRoots = null;
- IPackageFragmentRoot[] roots = null;
- if (project.isOpen()) {
- try {
- roots = project.getPackageFragmentRoots();
- } catch (JavaModelException e) {
- // ignore
- }
- } else {
- Map allRemovedRoots ;
- if ((allRemovedRoots = manager.getDeltaProcessor().removedRoots) != null) {
- roots = (IPackageFragmentRoot[]) allRemovedRoots.get(project);
- }
- }
- if (roots != null) {
- oldRoots = new HashMap();
- for (int i = 0; i < roots.length; i++) {
- IPackageFragmentRoot root = roots[i];
- oldRoots.put(root.getPath(), root);
- }
- }
- for (int i = 0; i < oldLength; i++) {
+ // if needed, generate delta, update project ref, create markers, ...
+ classpathChanged(this.project);
- int index = classpathContains(newResolvedPath, oldResolvedPath[i]);
- if (index == -1) {
- // do not notify remote project changes
- if (oldResolvedPath[i].getEntryKind() == IClasspathEntry.CPE_PROJECT){
- needToUpdateDependents = true;
- this.needCycleCheck = true;
- continue;
- }
-
- IPackageFragmentRoot[] pkgFragmentRoots = null;
- if (oldRoots != null) {
- IPackageFragmentRoot oldRoot = (IPackageFragmentRoot) oldRoots.get(oldResolvedPath[i].getPath());
- if (oldRoot != null) { // use old root if any (could be none if entry wasn't bound)
- pkgFragmentRoots = new IPackageFragmentRoot[] { oldRoot };
- }
- }
- if (pkgFragmentRoots == null) {
- try {
- ObjectVector accumulatedRoots = new ObjectVector();
- HashSet rootIDs = new HashSet(5);
- rootIDs.add(project.rootID());
- project.computePackageFragmentRoots(
- oldResolvedPath[i],
- accumulatedRoots,
- rootIDs,
- null, // inside original project
- false, // don't check existency
- false, // don't retrieve exported roots
- null); /*no reverse map*/
- pkgFragmentRoots = new IPackageFragmentRoot[accumulatedRoots.size()];
- accumulatedRoots.copyInto(pkgFragmentRoots);
- } catch (JavaModelException e) {
- pkgFragmentRoots = new IPackageFragmentRoot[] {};
- }
- }
- addClasspathDeltas(pkgFragmentRoots, IJavaElementDelta.F_REMOVED_FROM_CLASSPATH, delta);
-
- int changeKind = oldResolvedPath[i].getEntryKind();
- needToUpdateDependents |= (changeKind == IClasspathEntry.CPE_SOURCE) || oldResolvedPath[i].isExported();
-
- // Remove the .java files from the index for a source folder
- // For a lib folder or a .jar file, remove the corresponding index if not shared.
- if (indexManager != null) {
- IClasspathEntry oldEntry = oldResolvedPath[i];
- final IPath path = oldEntry.getPath();
- switch (changeKind) {
- case IClasspathEntry.CPE_SOURCE:
- final char[][] inclusionPatterns = ((ClasspathEntry)oldEntry).fullInclusionPatternChars();
- final char[][] exclusionPatterns = ((ClasspathEntry)oldEntry).fullExclusionPatternChars();
- postAction(new IPostAction() {
- public String getID() {
- return path.toString();
- }
- public void run() /* throws JavaModelException */ {
- indexManager.removeSourceFolderFromIndex(project, path, inclusionPatterns, exclusionPatterns);
- }
- },
- REMOVEALL_APPEND);
- break;
- case IClasspathEntry.CPE_LIBRARY:
- final DeltaProcessingState deltaState = manager.deltaState;
- postAction(new IPostAction() {
- public String getID() {
- return path.toString();
- }
- public void run() /* throws JavaModelException */ {
- if (deltaState.otherRoots.get(path) == null) { // if root was not shared
- indexManager.discardJobs(path.toString());
- indexManager.removeIndex(path);
- // TODO (kent) we could just remove the in-memory index and have the indexing check for timestamps
- }
- }
- },
- REMOVEALL_APPEND);
- break;
- }
- }
- hasDelta = true;
-
- } else {
- // do not notify remote project changes
- if (oldResolvedPath[i].getEntryKind() == IClasspathEntry.CPE_PROJECT){
- // Need to updated dependents in case old and/or new entries are exported and have an access restriction
- ClasspathEntry oldEntry = (ClasspathEntry) oldResolvedPath[i];
- ClasspathEntry newEntry = (ClasspathEntry) newResolvedPath[index];
- if (oldEntry.isExported || newEntry.isExported) { // then we need to verify if there's access restriction
- AccessRuleSet oldRuleSet = oldEntry.getAccessRuleSet();
- AccessRuleSet newRuleSet = newEntry.getAccessRuleSet();
- if (index != i) { // entry has been moved
- needToUpdateDependents |= (oldRuleSet != null || newRuleSet != null); // there's an access restriction, this may change combination
- } else if (oldRuleSet == null) {
- needToUpdateDependents |= newRuleSet != null; // access restriction was added
- } else {
- needToUpdateDependents |= !oldRuleSet.equals(newRuleSet); // access restriction has changed or has been removed
- }
- }
- this.needCycleCheck |= (oldEntry.isExported() != newEntry.isExported());
- continue;
- }
- needToUpdateDependents |= (oldResolvedPath[i].isExported() != newResolvedPath[index].isExported());
- if (index != i) { //reordering of the classpath
- addClasspathDeltas(
- project.computePackageFragmentRoots(oldResolvedPath[i]),
- IJavaElementDelta.F_REORDER,
- delta);
- int changeKind = oldResolvedPath[i].getEntryKind();
- needToUpdateDependents |= (changeKind == IClasspathEntry.CPE_SOURCE);
-
- hasDelta = true;
- }
-
- // check source attachment
- IPath newSourcePath = newResolvedPath[index].getSourceAttachmentPath();
- int sourceAttachmentFlags =
- this.getSourceAttachmentDeltaFlag(
- oldResolvedPath[i].getSourceAttachmentPath(),
- newSourcePath);
- IPath oldRootPath = oldResolvedPath[i].getSourceAttachmentRootPath();
- IPath newRootPath = newResolvedPath[index].getSourceAttachmentRootPath();
- int sourceAttachmentRootFlags = getSourceAttachmentDeltaFlag(oldRootPath, newRootPath);
- int flags = sourceAttachmentFlags | sourceAttachmentRootFlags;
- if (flags != 0) {
- addClasspathDeltas(project.computePackageFragmentRoots(oldResolvedPath[i]), flags, delta);
- hasDelta = true;
- } else {
- if (oldRootPath == null && newRootPath == null) {
- // if source path is specified and no root path, it needs to be recomputed dynamically
- // force detach source on jar package fragment roots (source will be lazily computed when needed)
- IPackageFragmentRoot[] computedRoots = project.computePackageFragmentRoots(oldResolvedPath[i]);
- for (int j = 0; j < computedRoots.length; j++) {
- IPackageFragmentRoot root = computedRoots[j];
- // force detach source on jar package fragment roots (source will be lazily computed when needed)
- try {
- root.close();
- } catch (JavaModelException e) {
- // ignore
- }
- ((PackageFragmentRoot) root).setSourceAttachmentProperty(null);// loose info - will be recomputed
- }
- }
- }
- }
- }
-
- for (int i = 0; i < newLength; i++) {
-
- int index = classpathContains(oldResolvedPath, newResolvedPath[i]);
- if (index == -1) {
- // do not notify remote project changes
- if (newResolvedPath[i].getEntryKind() == IClasspathEntry.CPE_PROJECT){
- needToUpdateDependents = true;
- this.needCycleCheck = true;
- continue;
- }
- addClasspathDeltas(
- project.computePackageFragmentRoots(newResolvedPath[i]),
- IJavaElementDelta.F_ADDED_TO_CLASSPATH,
- delta);
- int changeKind = newResolvedPath[i].getEntryKind();
-
- // Request indexing
- if (indexManager != null) {
- switch (changeKind) {
- case IClasspathEntry.CPE_LIBRARY:
- boolean pathHasChanged = true;
- final IPath newPath = newResolvedPath[i].getPath();
- for (int j = 0; j < oldLength; j++) {
- IClasspathEntry oldEntry = oldResolvedPath[j];
- if (oldEntry.getPath().equals(newPath)) {
- pathHasChanged = false;
- break;
- }
- }
- if (pathHasChanged) {
- postAction(new IPostAction() {
- public String getID() {
- return newPath.toString();
- }
- public void run() /* throws JavaModelException */ {
- indexManager.indexLibrary(newPath, project.getProject());
- }
- },
- REMOVEALL_APPEND);
- }
- break;
- case IClasspathEntry.CPE_SOURCE:
- IClasspathEntry entry = newResolvedPath[i];
- final IPath path = entry.getPath();
- final char[][] inclusionPatterns = ((ClasspathEntry)entry).fullInclusionPatternChars();
- final char[][] exclusionPatterns = ((ClasspathEntry)entry).fullExclusionPatternChars();
- postAction(new IPostAction() {
- public String getID() {
- return path.toString();
- }
- public void run() /* throws JavaModelException */ {
- indexManager.indexSourceFolder(project, path, inclusionPatterns, exclusionPatterns);
- }
- },
- APPEND); // append so that a removeSourceFolder action is not removed
- break;
- }
- }
-
- needToUpdateDependents |= (changeKind == IClasspathEntry.CPE_SOURCE) || newResolvedPath[i].isExported();
- hasDelta = true;
-
- } // classpath reordering has already been generated in previous loop
- }
-
- if (hasDelta) {
- this.addDelta(delta);
- } else {
- this.identicalRoots = true;
- }
- if (needToUpdateDependents){
- updateAffectedProjects(project.getProject().getFullPath());
- }
- }
- /*
- * Returns the source attachment flag for the delta between the 2 give source paths.
- * Returns either F_SOURCEATTACHED, F_SOURCEDETACHED, F_SOURCEATTACHED | F_SOURCEDETACHED
- * or 0 if there is no difference.
- */
- private int getSourceAttachmentDeltaFlag(IPath oldPath, IPath newPath) {
- if (oldPath == null) {
- if (newPath != null) {
- return IJavaElementDelta.F_SOURCEATTACHED;
- } else {
- return 0;
- }
- } else if (newPath == null) {
- return IJavaElementDelta.F_SOURCEDETACHED;
- } else if (!oldPath.equals(newPath)) {
- return IJavaElementDelta.F_SOURCEATTACHED | IJavaElementDelta.F_SOURCEDETACHED;
- } else {
- return 0;
+ // write .classpath file
+ if (this.canChangeResources && this.project.saveClasspath(this.newRawClasspath, this.newOutputLocation))
+ setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
+ } finally {
+ done();
}
}
- /**
- * Returns <code>true</code> if this operation performs no resource modifications,
- * otherwise <code>false</code>. Subclasses must override.
- */
- public boolean isReadOnly() {
- return !this.canChangeResources;
- }
-
- protected void saveClasspathIfNecessary() throws JavaModelException {
-
- if (!this.canChangeResources || !this.needSave) return;
-
- IClasspathEntry[] classpathForSave;
- if (this.newRawPath == DO_NOT_SET_ENTRIES || this.newRawPath == DO_NOT_UPDATE_PROJECT_REFS){
- classpathForSave = project.getRawClasspath();
- } else {
- classpathForSave = this.newRawPath;
- }
- IPath outputLocationForSave;
- if (this.newOutputLocation == DO_NOT_SET_OUTPUT){
- outputLocationForSave = project.getOutputLocation();
- } else {
- outputLocationForSave = this.newOutputLocation;
- }
- // if read-only .classpath, then the classpath setting will never been performed completely
- if (project.saveClasspath(classpathForSave, outputLocationForSave)) {
- this.classpathWasSaved = true;
- this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
- }
- }
-
public String toString(){
StringBuffer buffer = new StringBuffer(20);
buffer.append("SetClasspathOperation\n"); //$NON-NLS-1$
buffer.append(" - classpath : "); //$NON-NLS-1$
- if (this.newRawPath == DO_NOT_SET_ENTRIES){
- buffer.append("<Reuse Existing Classpath Entries>"); //$NON-NLS-1$
- } else {
- buffer.append("{"); //$NON-NLS-1$
- for (int i = 0; i < this.newRawPath.length; i++) {
- if (i > 0) buffer.append(","); //$NON-NLS-1$
- IClasspathEntry element = this.newRawPath[i];
- buffer.append(" ").append(element.toString()); //$NON-NLS-1$
- }
+ buffer.append("{"); //$NON-NLS-1$
+ for (int i = 0; i < this.newRawClasspath.length; i++) {
+ if (i > 0) buffer.append(","); //$NON-NLS-1$
+ IClasspathEntry element = this.newRawClasspath[i];
+ buffer.append(" ").append(element.toString()); //$NON-NLS-1$
}
buffer.append("\n - output location : "); //$NON-NLS-1$
- if (this.newOutputLocation == DO_NOT_SET_OUTPUT){
- buffer.append("<Reuse Existing Output Location>"); //$NON-NLS-1$
- } else {
- buffer.append(this.newOutputLocation.toString()); //$NON-NLS-1$
- }
+ buffer.append(this.newOutputLocation.toString());
return buffer.toString();
}
- private void updateClasspath() throws JavaModelException {
-
- beginTask(Messages.bind(Messages.classpath_settingProgress, project.getElementName()), 2);
-
- // SIDE-EFFECT: from thereon, the classpath got modified
- project.getPerProjectInfo().updateClasspathInformation(this.newRawPath);
-
- // resolve new path (asking for marker creation if problems)
- if (this.newResolvedPath == null) {
- this.newResolvedPath = project.getResolvedClasspath(true, this.canChangeResources, false/*don't returnResolutionInProgress*/);
- }
-
- if (this.oldResolvedPath != null) {
- generateClasspathChangeDeltas();
- } else {
- this.needCycleCheck = true;
- updateAffectedProjects(project.getProject().getFullPath());
- }
-
- updateCycleMarkersIfNecessary();
- }
-
- /**
- * Update projects which are affected by this classpath change:
- * those which refers to the current project as source (indirectly)
- */
- protected void updateAffectedProjects(IPath prerequisiteProjectPath) {
-
- // remove all update classpath post actions for this project
- final String updateClasspath = "UpdateClassPath:"; //$NON-NLS-1$
- removeAllPostAction(updateClasspath + prerequisiteProjectPath.toString());
-
- try {
- IJavaModel model = JavaModelManager.getJavaModelManager().getJavaModel();
- IJavaProject initialProject = this.project;
- IJavaProject[] projects = model.getJavaProjects();
- for (int i = 0, projectCount = projects.length; i < projectCount; i++) {
- try {
- final JavaProject affectedProject = (JavaProject) projects[i];
- if (affectedProject.equals(initialProject)) continue; // skip itself
- if (!affectedProject.isOpen()) continue; // skip project as its namelookup caches do not exist
-
- // consider ALL dependents (even indirect ones), since they may need to
- // flush their respective namelookup caches (all pkg fragment roots).
-
- IClasspathEntry[] classpath = affectedProject.getExpandedClasspath(true);
- for (int j = 0, entryCount = classpath.length; j < entryCount; j++) {
- IClasspathEntry entry = classpath[j];
- if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT
- && entry.getPath().equals(prerequisiteProjectPath)) {
-
- postAction(new IPostAction() {
- public String getID() {
- return updateClasspath + affectedProject.getPath().toString();
- }
- public void run() throws JavaModelException {
- affectedProject.setRawClasspath(
- DO_NOT_UPDATE_PROJECT_REFS,
- SetClasspathOperation.DO_NOT_SET_OUTPUT,
- SetClasspathOperation.this.progressMonitor,
- SetClasspathOperation.this.canChangeResources,
- affectedProject.getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/),
- false, // updating only - no validation
- false); // updating only - no need to save
- }
- },
- REMOVEALL_APPEND);
- break;
- }
- }
- } catch (JavaModelException e) {
- // ignore
- }
- }
- } catch (JavaModelException e) {
- // ignore
- }
-
- }
-
- /**
- * Update cycle markers
- */
- protected void updateCycleMarkersIfNecessary() {
-
- if (!this.needCycleCheck) return;
- if (!this.canChangeResources) return;
-
- if (!project.hasCycleMarker() && !project.hasClasspathCycle(newResolvedPath)){
- return;
- }
-
- postAction(
- new IPostAction() {
- public String getID() {
- return "updateCycleMarkers"; //$NON-NLS-1$
- }
- public void run() throws JavaModelException {
- JavaProject.updateAllCycleMarkers(null);
- }
- },
- REMOVEALL_APPEND);
- }
-
- /**
- * Sets the output location of the pre-specified project.
- *
- * <p>This can cause changes in package fragments, in case either the
- * old or new output location folder are considered as a package fragment.
- */
- protected void updateOutputLocation() throws JavaModelException {
-
- beginTask(Messages.bind(Messages.classpath_settingOutputLocationProgress, project.getElementName()), 2);
-
- IPath oldLocation= project.getOutputLocation();
-
- // see if this will cause any package fragments to be added
- boolean deltaToFire= false;
- JavaElementDelta delta = newJavaElementDelta();
- ArrayList added= determineAffectedPackageFragments(oldLocation);
- Iterator iter = added.iterator();
- while (iter.hasNext()){
- IPackageFragment frag= (IPackageFragment)iter.next();
- ((IPackageFragmentRoot)frag.getParent()).close();
- if (!Util.isExcluded(frag)) {
- delta.added(frag);
- deltaToFire = true;
- }
- }
-
- // see if this will cause any package fragments to be removed
- ArrayList removed= determineAffectedPackageFragments(this.newOutputLocation);
- iter = removed.iterator();
- while (iter.hasNext()){
- IPackageFragment frag= (IPackageFragment)iter.next();
- ((IPackageFragmentRoot)frag.getParent()).close();
- if (!Util.isExcluded(frag)) {
- delta.removed(frag);
- deltaToFire = true;
- }
- }
-
- JavaModelManager.PerProjectInfo perProjectInfo = project.getPerProjectInfo();
- synchronized (perProjectInfo) {
- perProjectInfo.outputLocation = this.newOutputLocation;
- }
-
- if (deltaToFire) {
- addDelta(delta);
- }
- worked(1);
- }
-
- /**
- * Update projects references so that the build order is consistent with the classpath
- */
- protected void updateProjectReferencesIfNecessary() throws JavaModelException {
-
- if (this.newRawPath == DO_NOT_SET_ENTRIES || this.newRawPath == DO_NOT_UPDATE_PROJECT_REFS) return;
- // will run now, or be deferred until next pre-auto-build notification if resource tree is locked
- JavaModelManager.getJavaModelManager().deltaState.performClasspathResourceChange(
- project,
- oldResolvedPath,
- newResolvedPath,
- newRawPath,
- canChangeResources);
- }
-
public IJavaModelStatus verify() {
-
IJavaModelStatus status = super.verify();
- if (!status.isOK()) {
+ if (!status.isOK())
return status;
- }
-
- if (needValidation) {
- // retrieve classpath
- IClasspathEntry[] entries = this.newRawPath;
- if (entries == DO_NOT_SET_ENTRIES){
- try {
- entries = project.getRawClasspath();
- } catch (JavaModelException e) {
- return e.getJavaModelStatus();
- }
- }
- // retrieve output location
- IPath outputLocation = this.newOutputLocation;
- if (outputLocation == DO_NOT_SET_OUTPUT){
- try {
- outputLocation = project.getOutputLocation();
- } catch (JavaModelException e) {
- return e.getJavaModelStatus();
- }
- }
-
- // perform validation
- return ClasspathEntry.validateClasspath(
- project,
- entries,
- outputLocation);
- }
-
- return JavaModelStatus.VERIFIED_OK;
+ return ClasspathEntry.validateClasspath( this.project, this.newRawClasspath, this.newOutputLocation);
}
+
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SetContainerOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SetContainerOperation.java
new file mode 100755
index 0000000..22a0347
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SetContainerOperation.java
@@ -0,0 +1,205 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core;
+
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jdt.core.IClasspathContainer;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.internal.core.util.Util;
+
+public class SetContainerOperation extends ChangeClasspathOperation {
+
+ IPath containerPath;
+ IJavaProject[] affectedProjects;
+ IClasspathContainer[] respectiveContainers;
+
+ /*
+ * Creates a new SetContainerOperation.
+ */
+ public SetContainerOperation(IPath containerPath, IJavaProject[] affectedProjects, IClasspathContainer[] respectiveContainers) {
+ super(new IJavaElement[] {JavaModelManager.getJavaModelManager().getJavaModel()}, !ResourcesPlugin.getWorkspace().isTreeLocked());
+ this.containerPath = containerPath;
+ this.affectedProjects = affectedProjects;
+ this.respectiveContainers = respectiveContainers;
+ }
+
+ protected void executeOperation() throws JavaModelException {
+ checkCanceled();
+ try {
+ beginTask("", 1); //$NON-NLS-1$
+ if (JavaModelManager.CP_RESOLVE_VERBOSE)
+ verbose_set_container();
+ if (JavaModelManager.CP_RESOLVE_VERBOSE_ADVANCED)
+ verbose_set_container_invocation_trace();
+
+ JavaModelManager manager = JavaModelManager.getJavaModelManager();
+ if (manager.containerPutIfInitializingWithSameEntries(this.containerPath, this.affectedProjects, this.respectiveContainers))
+ return;
+
+ final int projectLength = this.affectedProjects.length;
+ final IJavaProject[] modifiedProjects;
+ System.arraycopy(this.affectedProjects, 0, modifiedProjects = new IJavaProject[projectLength], 0, projectLength);
+ final IClasspathEntry[][] oldResolvedPaths = new IClasspathEntry[projectLength][];
+
+ // filter out unmodified project containers
+ int remaining = 0;
+ for (int i = 0; i < projectLength; i++){
+ if (isCanceled())
+ return;
+ JavaProject affectedProject = (JavaProject) this.affectedProjects[i];
+ IClasspathContainer newContainer = this.respectiveContainers[i];
+ if (newContainer == null) newContainer = JavaModelManager.CONTAINER_INITIALIZATION_IN_PROGRESS; // 30920 - prevent infinite loop
+ boolean found = false;
+ if (JavaProject.hasJavaNature(affectedProject.getProject())){
+ IClasspathEntry[] rawClasspath = affectedProject.getRawClasspath();
+ for (int j = 0, cpLength = rawClasspath.length; j <cpLength; j++) {
+ IClasspathEntry entry = rawClasspath[j];
+ if (entry.getEntryKind() == IClasspathEntry.CPE_CONTAINER && entry.getPath().equals(this.containerPath)){
+ found = true;
+ break;
+ }
+ }
+ }
+ if (!found) {
+ modifiedProjects[i] = null; // filter out this project - does not reference the container path, or isnt't yet Java project
+ manager.containerPut(affectedProject, this.containerPath, newContainer);
+ continue;
+ }
+ IClasspathContainer oldContainer = manager.containerGet(affectedProject, this.containerPath);
+ if (oldContainer == JavaModelManager.CONTAINER_INITIALIZATION_IN_PROGRESS) {
+ oldContainer = null;
+ }
+ if ((oldContainer != null && oldContainer.equals(this.respectiveContainers[i]))
+ || (oldContainer == this.respectiveContainers[i])/*handle case where old and new containers are null (see bug 149043*/) {
+ modifiedProjects[i] = null; // filter out this project - container did not change
+ continue;
+ }
+ remaining++;
+ oldResolvedPaths[i] = affectedProject.getResolvedClasspath();
+ manager.containerPut(affectedProject, this.containerPath, newContainer);
+ }
+
+ if (remaining == 0) return;
+
+ // trigger model refresh
+ try {
+ for(int i = 0; i < projectLength; i++){
+ if (isCanceled())
+ return;
+
+ JavaProject affectedProject = (JavaProject)modifiedProjects[i];
+ if (affectedProject == null) continue; // was filtered out
+ if (JavaModelManager.CP_RESOLVE_VERBOSE_ADVANCED)
+ verbose_update_project(affectedProject);
+
+ // force resolved classpath to be recomputed
+ affectedProject.getPerProjectInfo().resetResolvedClasspath();
+
+ // if needed, generate delta, update project ref, create markers, ...
+ classpathChanged(affectedProject);
+
+ if (this.canChangeResources) {
+ // touch project to force a build if needed
+ try {
+ affectedProject.getProject().touch(this.progressMonitor);
+ } catch (CoreException e) {
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=148970
+ if (!ExternalJavaProject.EXTERNAL_PROJECT_NAME.equals(affectedProject.getElementName()))
+ throw e;
+ }
+ }
+ }
+ } catch(CoreException e) {
+ if (JavaModelManager.CP_RESOLVE_VERBOSE)
+ verbose_failure(e);
+ if (e instanceof JavaModelException) {
+ throw (JavaModelException)e;
+ } else {
+ throw new JavaModelException(e);
+ }
+ } finally {
+ for (int i = 0; i < projectLength; i++) {
+ if (this.respectiveContainers[i] == null) {
+ manager.containerPut(this.affectedProjects[i], this.containerPath, null); // reset init in progress marker
+ }
+ }
+ }
+ } finally {
+ done();
+ }
+ }
+
+ private void verbose_failure(CoreException e) {
+ Util.verbose(
+ "CPContainer SET - FAILED DUE TO EXCEPTION\n" + //$NON-NLS-1$
+ " container path: " + this.containerPath, //$NON-NLS-1$
+ System.err);
+ e.printStackTrace();
+ }
+
+ private void verbose_update_project(JavaProject affectedProject) {
+ Util.verbose(
+ "CPContainer SET - updating affected project due to setting container\n" + //$NON-NLS-1$
+ " project: " + affectedProject.getElementName() + '\n' + //$NON-NLS-1$
+ " container path: " + this.containerPath); //$NON-NLS-1$
+ }
+
+ private void verbose_set_container() {
+ Util.verbose(
+ "CPContainer SET - setting container\n" + //$NON-NLS-1$
+ " container path: " + this.containerPath + '\n' + //$NON-NLS-1$
+ " projects: {" +//$NON-NLS-1$
+ org.eclipse.jdt.internal.compiler.util.Util.toString(
+ this.affectedProjects,
+ new org.eclipse.jdt.internal.compiler.util.Util.Displayable(){
+ public String displayString(Object o) { return ((IJavaProject) o).getElementName(); }
+ }) +
+ "}\n values: {\n" +//$NON-NLS-1$
+ org.eclipse.jdt.internal.compiler.util.Util.toString(
+ this.respectiveContainers,
+ new org.eclipse.jdt.internal.compiler.util.Util.Displayable(){
+ public String displayString(Object o) {
+ StringBuffer buffer = new StringBuffer(" "); //$NON-NLS-1$
+ if (o == null) {
+ buffer.append("<null>"); //$NON-NLS-1$
+ return buffer.toString();
+ }
+ IClasspathContainer container = (IClasspathContainer) o;
+ buffer.append(container.getDescription());
+ buffer.append(" {\n"); //$NON-NLS-1$
+ IClasspathEntry[] entries = container.getClasspathEntries();
+ if (entries != null){
+ for (int i = 0; i < entries.length; i++){
+ buffer.append(" "); //$NON-NLS-1$
+ buffer.append(entries[i]);
+ buffer.append('\n');
+ }
+ }
+ buffer.append(" }"); //$NON-NLS-1$
+ return buffer.toString();
+ }
+ }) +
+ "\n }");//$NON-NLS-1$
+ }
+
+ private void verbose_set_container_invocation_trace() {
+ Util.verbose(
+ "CPContainer SET - setting container\n" + //$NON-NLS-1$
+ " invocation stack trace:"); //$NON-NLS-1$
+ new Exception("<Fake exception>").printStackTrace(System.out); //$NON-NLS-1$
+ }
+
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SetVariablesOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SetVariablesOperation.java
new file mode 100755
index 0000000..def49a6
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SetVariablesOperation.java
@@ -0,0 +1,193 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core;
+
+import java.util.HashMap;
+import java.util.Iterator;
+
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaModel;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.internal.core.util.Util;
+
+public class SetVariablesOperation extends ChangeClasspathOperation {
+
+ String[] variableNames;
+ IPath[] variablePaths;
+ boolean updatePreferences;
+
+ /*
+ * Creates a new SetVariablesOperation for the given variable values (null path meaning removal), allowing to change multiple variable values at once.
+ */
+ public SetVariablesOperation(String[] variableNames, IPath[] variablePaths, boolean updatePreferences) {
+ super(new IJavaElement[] {JavaModelManager.getJavaModelManager().getJavaModel()}, !ResourcesPlugin.getWorkspace().isTreeLocked());
+ this.variableNames = variableNames;
+ this.variablePaths = variablePaths;
+ this.updatePreferences = updatePreferences;
+ }
+
+ protected void executeOperation() throws JavaModelException {
+ checkCanceled();
+ try {
+ beginTask("", 1); //$NON-NLS-1$
+ if (JavaModelManager.CP_RESOLVE_VERBOSE)
+ verbose_set_variables();
+
+ JavaModelManager manager = JavaModelManager.getJavaModelManager();
+ if (manager.variablePutIfInitializingWithSameValue(this.variableNames, this.variablePaths))
+ return;
+
+ int varLength = this.variableNames.length;
+
+ // gather classpath information for updating
+ final HashMap affectedProjectClasspaths = new HashMap(5);
+ IJavaModel model = getJavaModel();
+
+ // filter out unmodified variables
+ int discardCount = 0;
+ for (int i = 0; i < varLength; i++){
+ String variableName = this.variableNames[i];
+ IPath oldPath = manager.variableGet(variableName); // if reentering will provide previous session value
+ if (oldPath == JavaModelManager.VARIABLE_INITIALIZATION_IN_PROGRESS) {
+ oldPath = null; //33695 - cannot filter out restored variable, must update affected project to reset cached CP
+ }
+ if (oldPath != null && oldPath.equals(this.variablePaths[i])){
+ this.variableNames[i] = null;
+ discardCount++;
+ }
+ }
+ if (discardCount > 0){
+ if (discardCount == varLength) return;
+ int changedLength = varLength - discardCount;
+ String[] changedVariableNames = new String[changedLength];
+ IPath[] changedVariablePaths = new IPath[changedLength];
+ for (int i = 0, index = 0; i < varLength; i++){
+ if (this.variableNames[i] != null){
+ changedVariableNames[index] = this.variableNames[i];
+ changedVariablePaths[index] = this.variablePaths[i];
+ index++;
+ }
+ }
+ this.variableNames = changedVariableNames;
+ this.variablePaths = changedVariablePaths;
+ varLength = changedLength;
+ }
+
+ if (isCanceled())
+ return;
+
+ IJavaProject[] projects = model.getJavaProjects();
+ nextProject : for (int i = 0, projectLength = projects.length; i < projectLength; i++){
+ JavaProject project = (JavaProject) projects[i];
+
+ // check to see if any of the modified variables is present on the classpath
+ IClasspathEntry[] classpath = project.getRawClasspath();
+ for (int j = 0, cpLength = classpath.length; j < cpLength; j++){
+
+ IClasspathEntry entry = classpath[j];
+ for (int k = 0; k < varLength; k++){
+
+ String variableName = this.variableNames[k];
+ if (entry.getEntryKind() == IClasspathEntry.CPE_VARIABLE){
+
+ if (variableName.equals(entry.getPath().segment(0))){
+ affectedProjectClasspaths.put(project, project.getResolvedClasspath());
+ continue nextProject;
+ }
+ IPath sourcePath, sourceRootPath;
+ if (((sourcePath = entry.getSourceAttachmentPath()) != null && variableName.equals(sourcePath.segment(0)))
+ || ((sourceRootPath = entry.getSourceAttachmentRootPath()) != null && variableName.equals(sourceRootPath.segment(0)))) {
+
+ affectedProjectClasspaths.put(project, project.getResolvedClasspath());
+ continue nextProject;
+ }
+ }
+ }
+ }
+ }
+
+ // update variables
+ for (int i = 0; i < varLength; i++){
+ manager.variablePut(this.variableNames[i], this.variablePaths[i]);
+ if (this.updatePreferences)
+ manager.variablePreferencesPut(this.variableNames[i], this.variablePaths[i]);
+ }
+
+ // update affected project classpaths
+ if (!affectedProjectClasspaths.isEmpty()) {
+ String[] dbgVariableNames = this.variableNames;
+ try {
+ // propagate classpath change
+ Iterator projectsToUpdate = affectedProjectClasspaths.keySet().iterator();
+ while (projectsToUpdate.hasNext()) {
+
+ if (this.progressMonitor != null && this.progressMonitor.isCanceled()) return;
+
+ JavaProject affectedProject = (JavaProject) projectsToUpdate.next();
+
+ // force resolved classpath to be recomputed
+ if (JavaModelManager.CP_RESOLVE_VERBOSE_ADVANCED)
+ verbose_update_project(dbgVariableNames, affectedProject);
+ affectedProject.getPerProjectInfo().resetResolvedClasspath();
+
+ // if needed, generate delta, update project ref, create markers, ...
+ classpathChanged(affectedProject);
+
+ if (this.canChangeResources) {
+ // touch project to force a build if needed
+ affectedProject.getProject().touch(this.progressMonitor);
+ }
+ }
+ } catch (CoreException e) {
+ if (JavaModelManager.CP_RESOLVE_VERBOSE){
+ verbose_failure(dbgVariableNames);
+ e.printStackTrace();
+ }
+ if (e instanceof JavaModelException) {
+ throw (JavaModelException)e;
+ } else {
+ throw new JavaModelException(e);
+ }
+ }
+ }
+ } finally {
+ done();
+ }
+ }
+
+ private void verbose_failure(String[] dbgVariableNames) {
+ Util.verbose(
+ "CPVariable SET - FAILED DUE TO EXCEPTION\n" + //$NON-NLS-1$
+ " variables: " + org.eclipse.jdt.internal.compiler.util.Util.toString(dbgVariableNames), //$NON-NLS-1$
+ System.err);
+ }
+
+ private void verbose_update_project(String[] dbgVariableNames,
+ JavaProject affectedProject) {
+ Util.verbose(
+ "CPVariable SET - updating affected project due to setting variables\n" + //$NON-NLS-1$
+ " project: " + affectedProject.getElementName() + '\n' + //$NON-NLS-1$
+ " variables: " + org.eclipse.jdt.internal.compiler.util.Util.toString(dbgVariableNames)); //$NON-NLS-1$
+ }
+
+ private void verbose_set_variables() {
+ Util.verbose(
+ "CPVariable SET - setting variables\n" + //$NON-NLS-1$
+ " variables: " + org.eclipse.jdt.internal.compiler.util.Util.toString(this.variableNames) + '\n' +//$NON-NLS-1$
+ " values: " + org.eclipse.jdt.internal.compiler.util.Util.toString(this.variablePaths)); //$NON-NLS-1$
+ }
+
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SimpleDelta.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SimpleDelta.java
index 4491164..53650d7 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SimpleDelta.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SimpleDelta.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SingleTypeRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SingleTypeRequestor.java
index 37d0f11..1b2c828 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SingleTypeRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SingleTypeRequestor.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SortElementsOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SortElementsOperation.java
index 53e7c13..48b915a 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SortElementsOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SortElementsOperation.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Alex Blewitt - alex_blewitt@yahoo.com https://bugs.eclipse.org/bugs/show_bug.cgi?id=171066
*******************************************************************************/
package org.eclipse.jdt.internal.core;
@@ -23,7 +24,6 @@
import org.eclipse.jdt.core.IJavaModelStatusConstants;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.ASTVisitor;
@@ -43,6 +43,7 @@
import org.eclipse.jface.text.Document;
import org.eclipse.text.edits.RangeMarker;
import org.eclipse.text.edits.TextEdit;
+import org.eclipse.text.edits.TextEditGroup;
/**
* This operation is used to sort elements in a compilation unit according to
@@ -51,11 +52,12 @@
* @since 2.1
*/
public class SortElementsOperation extends JavaModelOperation {
-
+ public static final String CONTAINS_MALFORMED_NODES = "malformed"; //$NON-NLS-1$
+
Comparator comparator;
int[] positions;
int apiLevel;
-
+
/**
* Constructor for SortElementsOperation.
*
@@ -79,6 +81,16 @@
return this.elementsToProcess.length;
}
+ boolean checkMalformedNodes(ASTNode node) {
+ Object property = node.getProperty(CONTAINS_MALFORMED_NODES);
+ if (property == null) return false;
+ return ((Boolean) property).booleanValue();
+ }
+
+ protected boolean isMalformed(ASTNode node) {
+ return (node.getFlags() & ASTNode.MALFORMED) != 0;
+ }
+
/**
* @see org.eclipse.jdt.internal.core.JavaModelOperation#executeOperation()
*/
@@ -101,6 +113,35 @@
done();
}
}
+
+ /**
+ * Calculates the required text edits to sort the <code>unit</code>
+ * @param group
+ * @return the edit or null if no sorting is required
+ */
+ public TextEdit calculateEdit(org.eclipse.jdt.core.dom.CompilationUnit unit, TextEditGroup group) throws JavaModelException {
+ if (this.elementsToProcess.length != 1)
+ throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.NO_ELEMENTS_TO_PROCESS));
+
+ if (!(this.elementsToProcess[0] instanceof ICompilationUnit))
+ throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, this.elementsToProcess[0]));
+
+ try {
+ beginTask(Messages.operation_sortelements, getMainAmountOfWork());
+
+ ICompilationUnit cu= (ICompilationUnit)this.elementsToProcess[0];
+ String content= cu.getBuffer().getContents();
+ ASTRewrite rewrite= sortCompilationUnit(unit, group);
+ if (rewrite == null) {
+ return null;
+ }
+
+ Document document= new Document(content);
+ return rewrite.rewriteAST(document, null);
+ } finally {
+ done();
+ }
+ }
/**
* Method processElement.
@@ -108,172 +149,32 @@
* @param source
*/
private String processElement(ICompilationUnit unit, char[] source) {
+ Document document = new Document(new String(source));
CompilerOptions options = new CompilerOptions(unit.getJavaProject().getOptions(true));
ASTParser parser = ASTParser.newParser(this.apiLevel);
parser.setCompilerOptions(options.getMap());
parser.setSource(source);
parser.setKind(ASTParser.K_COMPILATION_UNIT);
parser.setResolveBindings(false);
- org.eclipse.jdt.core.dom.CompilationUnit domUnit = (org.eclipse.jdt.core.dom.CompilationUnit) parser.createAST(null);
- domUnit.accept(new ASTVisitor() {
- public boolean visit(org.eclipse.jdt.core.dom.CompilationUnit compilationUnit) {
- List types = compilationUnit.types();
- for (Iterator iter = types.iterator(); iter.hasNext();) {
- AbstractTypeDeclaration typeDeclaration = (AbstractTypeDeclaration) iter.next();
- typeDeclaration.setProperty(CompilationUnitSorter.RELATIVE_ORDER, new Integer(typeDeclaration.getStartPosition()));
- }
- return true;
- }
- public boolean visit(AnnotationTypeDeclaration annotationTypeDeclaration) {
- List bodyDeclarations = annotationTypeDeclaration.bodyDeclarations();
- for (Iterator iter = bodyDeclarations.iterator(); iter.hasNext();) {
- BodyDeclaration bodyDeclaration = (BodyDeclaration) iter.next();
- bodyDeclaration.setProperty(CompilationUnitSorter.RELATIVE_ORDER, new Integer(bodyDeclaration.getStartPosition()));
- }
- return true;
- }
-
- public boolean visit(AnonymousClassDeclaration anonymousClassDeclaration) {
- List bodyDeclarations = anonymousClassDeclaration.bodyDeclarations();
- for (Iterator iter = bodyDeclarations.iterator(); iter.hasNext();) {
- BodyDeclaration bodyDeclaration = (BodyDeclaration) iter.next();
- bodyDeclaration.setProperty(CompilationUnitSorter.RELATIVE_ORDER, new Integer(bodyDeclaration.getStartPosition()));
- }
- return true;
- }
-
- public boolean visit(TypeDeclaration typeDeclaration) {
- List bodyDeclarations = typeDeclaration.bodyDeclarations();
- for (Iterator iter = bodyDeclarations.iterator(); iter.hasNext();) {
- BodyDeclaration bodyDeclaration = (BodyDeclaration) iter.next();
- bodyDeclaration.setProperty(CompilationUnitSorter.RELATIVE_ORDER, new Integer(bodyDeclaration.getStartPosition()));
- }
- return true;
- }
-
- public boolean visit(EnumDeclaration enumDeclaration) {
- List bodyDeclarations = enumDeclaration.bodyDeclarations();
- for (Iterator iter = bodyDeclarations.iterator(); iter.hasNext();) {
- BodyDeclaration bodyDeclaration = (BodyDeclaration) iter.next();
- bodyDeclaration.setProperty(CompilationUnitSorter.RELATIVE_ORDER, new Integer(bodyDeclaration.getStartPosition()));
- }
- List enumConstants = enumDeclaration.enumConstants();
- for (Iterator iter = enumConstants.iterator(); iter.hasNext();) {
- EnumConstantDeclaration enumConstantDeclaration = (EnumConstantDeclaration) iter.next();
- enumConstantDeclaration.setProperty(CompilationUnitSorter.RELATIVE_ORDER, new Integer(enumConstantDeclaration.getStartPosition()));
- }
- return true;
- }
- });
- final AST localAst = domUnit.getAST();
- final ASTRewrite rewriter = ASTRewrite.create(localAst);
- RangeMarker[] markers = null;
+ org.eclipse.jdt.core.dom.CompilationUnit ast = (org.eclipse.jdt.core.dom.CompilationUnit) parser.createAST(null);
+
+ ASTRewrite rewriter= sortCompilationUnit(ast, null);
+ if (rewriter == null)
+ return document.get();
- final boolean needPositionsMapping = this.positions != null;
- if (needPositionsMapping) {
- markers = new RangeMarker[this.positions.length];
- for (int i= 0; i < this.positions.length; i++) {
- markers[i]= new RangeMarker(this.positions[i], 0);
- }
- }
- String generatedSource = new String(source);
- Document document = new Document(generatedSource);
- domUnit.accept(new ASTVisitor() {
- public boolean visit(org.eclipse.jdt.core.dom.CompilationUnit compilationUnit) {
- ListRewrite listRewrite = rewriter.getListRewrite(compilationUnit, org.eclipse.jdt.core.dom.CompilationUnit.TYPES_PROPERTY);
- List types = compilationUnit.types();
- final int length = types.size();
- if (length > 1) {
- final List myCopy = new ArrayList();
- myCopy.addAll(types);
- Collections.sort(myCopy, SortElementsOperation.this.comparator);
- for (int i = 0; i < length; i++) {
- listRewrite.replace((ASTNode) types.get(i), rewriter.createMoveTarget((ASTNode) myCopy.get(i)), null);
- }
- }
- return true;
- }
- public boolean visit(AnnotationTypeDeclaration annotationTypeDeclaration) {
- ListRewrite listRewrite = rewriter.getListRewrite(annotationTypeDeclaration, AnnotationTypeDeclaration.BODY_DECLARATIONS_PROPERTY);
- List bodyDeclarations = annotationTypeDeclaration.bodyDeclarations();
- final int length = bodyDeclarations.size();
- if (length > 1) {
- final List myCopy = new ArrayList();
- myCopy.addAll(bodyDeclarations);
- Collections.sort(myCopy, SortElementsOperation.this.comparator);
- for (int i = 0; i < length; i++) {
- listRewrite.replace((ASTNode) bodyDeclarations.get(i), rewriter.createMoveTarget((ASTNode) myCopy.get(i)), null);
- }
- }
- return true;
- }
-
- public boolean visit(AnonymousClassDeclaration anonymousClassDeclaration) {
- ListRewrite listRewrite = rewriter.getListRewrite(anonymousClassDeclaration, AnonymousClassDeclaration.BODY_DECLARATIONS_PROPERTY);
- List bodyDeclarations = anonymousClassDeclaration.bodyDeclarations();
- final int length = bodyDeclarations.size();
- if (length > 1) {
- final List myCopy = new ArrayList();
- myCopy.addAll(bodyDeclarations);
- Collections.sort(myCopy, SortElementsOperation.this.comparator);
- for (int i = 0; i < length; i++) {
- listRewrite.replace((ASTNode) bodyDeclarations.get(i), rewriter.createMoveTarget((ASTNode) myCopy.get(i)), null);
- }
- }
- return true;
- }
-
- public boolean visit(TypeDeclaration typeDeclaration) {
- ListRewrite listRewrite = rewriter.getListRewrite(typeDeclaration, TypeDeclaration.BODY_DECLARATIONS_PROPERTY);
- List bodyDeclarations = typeDeclaration.bodyDeclarations();
- final int length = bodyDeclarations.size();
- if (length > 1) {
- final List myCopy = new ArrayList();
- myCopy.addAll(bodyDeclarations);
- Collections.sort(myCopy, SortElementsOperation.this.comparator);
- for (int i = 0; i < length; i++) {
- listRewrite.replace((ASTNode) bodyDeclarations.get(i), rewriter.createMoveTarget((ASTNode) myCopy.get(i)), null);
- }
- }
- return true;
- }
-
- public boolean visit(EnumDeclaration enumDeclaration) {
- ListRewrite listRewrite = rewriter.getListRewrite(enumDeclaration, EnumDeclaration.BODY_DECLARATIONS_PROPERTY);
- List bodyDeclarations = enumDeclaration.bodyDeclarations();
- int length = bodyDeclarations.size();
- if (length > 1) {
- final List myCopy = new ArrayList();
- myCopy.addAll(bodyDeclarations);
- Collections.sort(myCopy, SortElementsOperation.this.comparator);
- for (int i = 0; i < length; i++) {
- listRewrite.replace((ASTNode) bodyDeclarations.get(i), rewriter.createMoveTarget((ASTNode) myCopy.get(i)), null);
- }
- }
- listRewrite = rewriter.getListRewrite(enumDeclaration, EnumDeclaration.ENUM_CONSTANTS_PROPERTY);
- List enumConstants = enumDeclaration.enumConstants();
- length = enumConstants.size();
- if (length > 1) {
- final List myCopy = new ArrayList();
- myCopy.addAll(enumConstants);
- Collections.sort(myCopy, SortElementsOperation.this.comparator);
- for (int i = 0; i < length; i++) {
- listRewrite.replace((ASTNode) enumConstants.get(i), rewriter.createMoveTarget((ASTNode) myCopy.get(i)), null);
- }
- }
- return true;
- }
- });
TextEdit edits = rewriter.rewriteAST(document, null);
- if (needPositionsMapping) {
- for (int i = 0, max = markers.length; i < max; i++) {
+
+ RangeMarker[] markers = null;
+ if (this.positions != null) {
+ markers = new RangeMarker[this.positions.length];
+ for (int i = 0, max = this.positions.length; i < max; i++) {
+ markers[i]= new RangeMarker(this.positions[i], 0);
insert(edits, markers[i]);
}
}
try {
edits.apply(document, TextEdit.UPDATE_REGIONS);
- generatedSource = document.get();
- if (needPositionsMapping) {
+ if (this.positions != null) {
for (int i= 0, max = markers.length; i < max; i++) {
this.positions[i]= markers[i].getOffset();
}
@@ -281,7 +182,142 @@
} catch (BadLocationException e) {
// ignore
}
- return generatedSource;
+ return document.get();
+ }
+
+
+ private ASTRewrite sortCompilationUnit(org.eclipse.jdt.core.dom.CompilationUnit ast, final TextEditGroup group) {
+ ast.accept(new ASTVisitor() {
+ public boolean visit(org.eclipse.jdt.core.dom.CompilationUnit compilationUnit) {
+ List types = compilationUnit.types();
+ for (Iterator iter = types.iterator(); iter.hasNext();) {
+ AbstractTypeDeclaration typeDeclaration = (AbstractTypeDeclaration) iter.next();
+ typeDeclaration.setProperty(CompilationUnitSorter.RELATIVE_ORDER, new Integer(typeDeclaration.getStartPosition()));
+ compilationUnit.setProperty(CONTAINS_MALFORMED_NODES, Boolean.valueOf(isMalformed(typeDeclaration)));
+ }
+ return true;
+ }
+ public boolean visit(AnnotationTypeDeclaration annotationTypeDeclaration) {
+ List bodyDeclarations = annotationTypeDeclaration.bodyDeclarations();
+ for (Iterator iter = bodyDeclarations.iterator(); iter.hasNext();) {
+ BodyDeclaration bodyDeclaration = (BodyDeclaration) iter.next();
+ bodyDeclaration.setProperty(CompilationUnitSorter.RELATIVE_ORDER, new Integer(bodyDeclaration.getStartPosition()));
+ annotationTypeDeclaration.setProperty(CONTAINS_MALFORMED_NODES, Boolean.valueOf(isMalformed(bodyDeclaration)));
+ }
+ return true;
+ }
+
+ public boolean visit(AnonymousClassDeclaration anonymousClassDeclaration) {
+ List bodyDeclarations = anonymousClassDeclaration.bodyDeclarations();
+ for (Iterator iter = bodyDeclarations.iterator(); iter.hasNext();) {
+ BodyDeclaration bodyDeclaration = (BodyDeclaration) iter.next();
+ bodyDeclaration.setProperty(CompilationUnitSorter.RELATIVE_ORDER, new Integer(bodyDeclaration.getStartPosition()));
+ anonymousClassDeclaration.setProperty(CONTAINS_MALFORMED_NODES, Boolean.valueOf(isMalformed(bodyDeclaration)));
+ }
+ return true;
+ }
+
+ public boolean visit(TypeDeclaration typeDeclaration) {
+ List bodyDeclarations = typeDeclaration.bodyDeclarations();
+ for (Iterator iter = bodyDeclarations.iterator(); iter.hasNext();) {
+ BodyDeclaration bodyDeclaration = (BodyDeclaration) iter.next();
+ bodyDeclaration.setProperty(CompilationUnitSorter.RELATIVE_ORDER, new Integer(bodyDeclaration.getStartPosition()));
+ typeDeclaration.setProperty(CONTAINS_MALFORMED_NODES, Boolean.valueOf(isMalformed(bodyDeclaration)));
+ }
+ return true;
+ }
+
+ public boolean visit(EnumDeclaration enumDeclaration) {
+ List bodyDeclarations = enumDeclaration.bodyDeclarations();
+ for (Iterator iter = bodyDeclarations.iterator(); iter.hasNext();) {
+ BodyDeclaration bodyDeclaration = (BodyDeclaration) iter.next();
+ bodyDeclaration.setProperty(CompilationUnitSorter.RELATIVE_ORDER, new Integer(bodyDeclaration.getStartPosition()));
+ enumDeclaration.setProperty(CONTAINS_MALFORMED_NODES, Boolean.valueOf(isMalformed(bodyDeclaration)));
+ }
+ List enumConstants = enumDeclaration.enumConstants();
+ for (Iterator iter = enumConstants.iterator(); iter.hasNext();) {
+ EnumConstantDeclaration enumConstantDeclaration = (EnumConstantDeclaration) iter.next();
+ enumConstantDeclaration.setProperty(CompilationUnitSorter.RELATIVE_ORDER, new Integer(enumConstantDeclaration.getStartPosition()));
+ enumDeclaration.setProperty(CONTAINS_MALFORMED_NODES, Boolean.valueOf(isMalformed(enumConstantDeclaration)));
+ }
+ return true;
+ }
+ });
+
+ final ASTRewrite rewriter= ASTRewrite.create(ast.getAST());
+ final boolean[] hasChanges= new boolean[] {false};
+
+ ast.accept(new ASTVisitor() {
+
+ private void sortElements(List elements, ListRewrite listRewrite) {
+ if (elements.size() == 0)
+ return;
+
+ final List myCopy = new ArrayList();
+ myCopy.addAll(elements);
+ Collections.sort(myCopy, SortElementsOperation.this.comparator);
+
+ for (int i = 0; i < elements.size(); i++) {
+ ASTNode oldNode= (ASTNode) elements.get(i);
+ ASTNode newNode= (ASTNode) myCopy.get(i);
+ if (oldNode != newNode) {
+ listRewrite.replace(oldNode, rewriter.createMoveTarget(newNode), group);
+ hasChanges[0]= true;
+ }
+ }
+ }
+
+ public boolean visit(org.eclipse.jdt.core.dom.CompilationUnit compilationUnit) {
+ if (checkMalformedNodes(compilationUnit)) {
+ return true; // abort sorting of current element
+ }
+
+ sortElements(compilationUnit.types(), rewriter.getListRewrite(compilationUnit, org.eclipse.jdt.core.dom.CompilationUnit.TYPES_PROPERTY));
+ return true;
+ }
+
+ public boolean visit(AnnotationTypeDeclaration annotationTypeDeclaration) {
+ if (checkMalformedNodes(annotationTypeDeclaration)) {
+ return true; // abort sorting of current element
+ }
+
+ sortElements(annotationTypeDeclaration.bodyDeclarations(), rewriter.getListRewrite(annotationTypeDeclaration, AnnotationTypeDeclaration.BODY_DECLARATIONS_PROPERTY));
+ return true;
+ }
+
+ public boolean visit(AnonymousClassDeclaration anonymousClassDeclaration) {
+ if (checkMalformedNodes(anonymousClassDeclaration)) {
+ return true; // abort sorting of current element
+ }
+
+ sortElements(anonymousClassDeclaration.bodyDeclarations(), rewriter.getListRewrite(anonymousClassDeclaration, AnonymousClassDeclaration.BODY_DECLARATIONS_PROPERTY));
+ return true;
+ }
+
+ public boolean visit(TypeDeclaration typeDeclaration) {
+ if (checkMalformedNodes(typeDeclaration)) {
+ return true; // abort sorting of current element
+ }
+
+ sortElements(typeDeclaration.bodyDeclarations(), rewriter.getListRewrite(typeDeclaration, TypeDeclaration.BODY_DECLARATIONS_PROPERTY));
+ return true;
+ }
+
+ public boolean visit(EnumDeclaration enumDeclaration) {
+ if (checkMalformedNodes(enumDeclaration)) {
+ return true; // abort sorting of current element
+ }
+
+ sortElements(enumDeclaration.bodyDeclarations(), rewriter.getListRewrite(enumDeclaration, EnumDeclaration.BODY_DECLARATIONS_PROPERTY));
+ sortElements(enumDeclaration.enumConstants(), rewriter.getListRewrite(enumDeclaration, EnumDeclaration.ENUM_CONSTANTS_PROPERTY));
+ return true;
+ }
+ });
+
+ if (!hasChanges[0])
+ return null;
+
+ return rewriter;
}
/**
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceAnnotationMethodInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceAnnotationMethodInfo.java
index 46407d6..b868785 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceAnnotationMethodInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceAnnotationMethodInfo.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004 IBM Corporation and others.
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,8 +10,6 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core;
-import org.eclipse.jdt.core.compiler.CharOperation;
-
/*
* Element info for annotation method from source.
*/
@@ -22,16 +20,11 @@
* These are {-1, -1} if the method is an annotation method with no default value.
* Otherwise these are the start and end (inclusive) of the expression representing the default value.
*/
- protected int defaultValueStart;
- protected int defaultValueEnd;
+ public int defaultValueStart;
+ public int defaultValueEnd;
public boolean isAnnotationMethod() {
return true;
}
- public char[] getDefaultValueSource(char[] cuSource) {
- if (this.defaultValueStart == -1 && this.defaultValueEnd == -1)
- return null;
- return CharOperation.subarray(cuSource, this.defaultValueStart, this.defaultValueEnd+1);
- }
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceConstructorInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceConstructorInfo.java
index 1fe69f5..922a2d7 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceConstructorInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceConstructorInfo.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004 IBM Corporation and others.
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceField.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceField.java
index dc936e7..e025213 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceField.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceField.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -11,10 +11,6 @@
package org.eclipse.jdt.internal.core;
import org.eclipse.jdt.core.*;
-import org.eclipse.jdt.core.IField;
-import org.eclipse.jdt.core.IType;
-import org.eclipse.jdt.core.JavaModelException;
-import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
@@ -37,8 +33,12 @@
public ASTNode findNode(org.eclipse.jdt.core.dom.CompilationUnit ast) {
// For field declarations, a variable declaration fragment is returned
// Return the FieldDeclaration instead
+ // For enum constant declaration, we return the node directly
ASTNode node = super.findNode(ast);
if (node == null) return null;
+ if (node.getNodeType() == ASTNode.ENUM_CONSTANT_DECLARATION) {
+ return node;
+ }
return node.getParent();
}
/**
@@ -54,36 +54,41 @@
String constantSource = new String(constantSourceChars);
String signature = info.getTypeSignature();
- if (signature.equals(Signature.SIG_INT)) {
- constant = new Integer(constantSource);
- } else if (signature.equals(Signature.SIG_SHORT)) {
- constant = new Short(constantSource);
- } else if (signature.equals(Signature.SIG_BYTE)) {
- constant = new Byte(constantSource);
- } else if (signature.equals(Signature.SIG_BOOLEAN)) {
- constant = Boolean.valueOf(constantSource);
- } else if (signature.equals(Signature.SIG_CHAR)) {
- if (constantSourceChars.length != 3) {
- return null;
- }
- constant = new Character(constantSourceChars[1]);
- } else if (signature.equals(Signature.SIG_DOUBLE)) {
- constant = new Double(constantSource);
- } else if (signature.equals(Signature.SIG_FLOAT)) {
- constant = new Float(constantSource);
- } else if (signature.equals(Signature.SIG_LONG)) {
- if (constantSource.endsWith("L") || constantSource.endsWith("l")) { //$NON-NLS-1$ //$NON-NLS-2$
- int index = constantSource.lastIndexOf("L");//$NON-NLS-1$
- if (index != -1) {
- constant = new Long(constantSource.substring(0, index));
- } else {
- constant = new Long(constantSource.substring(0, constantSource.lastIndexOf("l")));//$NON-NLS-1$
+ try {
+ if (signature.equals(Signature.SIG_INT)) {
+ constant = new Integer(constantSource);
+ } else if (signature.equals(Signature.SIG_SHORT)) {
+ constant = new Short(constantSource);
+ } else if (signature.equals(Signature.SIG_BYTE)) {
+ constant = new Byte(constantSource);
+ } else if (signature.equals(Signature.SIG_BOOLEAN)) {
+ constant = Boolean.valueOf(constantSource);
+ } else if (signature.equals(Signature.SIG_CHAR)) {
+ if (constantSourceChars.length != 3) {
+ return null;
}
- } else {
- constant = new Long(constantSource);
+ constant = new Character(constantSourceChars[1]);
+ } else if (signature.equals(Signature.SIG_DOUBLE)) {
+ constant = new Double(constantSource);
+ } else if (signature.equals(Signature.SIG_FLOAT)) {
+ constant = new Float(constantSource);
+ } else if (signature.equals(Signature.SIG_LONG)) {
+ if (constantSource.endsWith("L") || constantSource.endsWith("l")) { //$NON-NLS-1$ //$NON-NLS-2$
+ int index = constantSource.lastIndexOf("L");//$NON-NLS-1$
+ if (index != -1) {
+ constant = new Long(constantSource.substring(0, index));
+ } else {
+ constant = new Long(constantSource.substring(0, constantSource.lastIndexOf("l")));//$NON-NLS-1$
+ }
+ } else {
+ constant = new Long(constantSource);
+ }
+ } else if (signature.equals("QString;")) {//$NON-NLS-1$
+ constant = constantSource;
}
- } else if (signature.equals("QString;")) {//$NON-NLS-1$
- constant = constantSource;
+ } catch (NumberFormatException e) {
+ // not a parsable constant
+ return null;
}
return constant;
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceFieldElementInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceFieldElementInfo.java
index d3d5f3d..9247f8c 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceFieldElementInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceFieldElementInfo.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMapper.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMapper.java
index 23fdcae..d6ca6f4 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMapper.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMapper.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -34,7 +34,11 @@
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
+import org.eclipse.jdt.core.Flags;
+import org.eclipse.jdt.core.IClassFile;
+import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IPackageFragmentRoot;
@@ -42,10 +46,11 @@
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeParameter;
import org.eclipse.jdt.core.JavaConventions;
+import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
+import org.eclipse.jdt.core.compiler.CategorizedProblem;
import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.internal.compiler.IProblemFactory;
import org.eclipse.jdt.internal.compiler.ISourceElementRequestor;
import org.eclipse.jdt.internal.compiler.SourceElementParser;
@@ -102,15 +107,10 @@
protected String rootPath = ""; //$NON-NLS-1$
/**
- * Used for efficiency
- */
- protected static String[] fgEmptyStringArray = new String[0];
-
- /**
* Table that maps a binary method to its parameter names.
* Keys are the method handles, entries are <code>char[][]</code>.
*/
- protected HashMap fParameterNames;
+ protected HashMap parameterNames;
/**
* Table that maps a binary element to its <code>SourceRange</code>s.
@@ -118,37 +118,42 @@
* is a two element array; the first being source range, the second
* being name range.
*/
- protected HashMap fSourceRanges;
+ protected HashMap sourceRanges;
+
+ /*
+ * A map from IJavaElement to String[]
+ */
+ protected HashMap categories;
/**
* The unknown source range {-1, 0}
*/
- public static SourceRange fgUnknownRange = new SourceRange(-1, 0);
+ public static final SourceRange UNKNOWN_RANGE = new SourceRange(-1, 0);
/**
* The position within the source of the start of the
* current member element, or -1 if we are outside a member.
*/
- protected int[] fMemberDeclarationStart;
+ protected int[] memberDeclarationStart;
/**
* The <code>SourceRange</code> of the name of the current member element.
*/
- protected SourceRange[] fMemberNameRange;
+ protected SourceRange[] memberNameRange;
/**
* The name of the current member element.
*/
- protected String[] fMemberName;
+ protected String[] memberName;
/**
* The parameter names for the current member method element.
*/
- protected char[][][] fMethodParameterNames;
+ protected char[][][] methodParameterNames;
/**
* The parameter types for the current member method element.
*/
- protected char[][][] fMethodParameterTypes;
+ protected char[][][] methodParameterTypes;
/**
@@ -168,6 +173,7 @@
IType[] types;
int[] typeDeclarationStarts;
SourceRange[] typeNameRanges;
+ int[] typeModifiers;
int typeDepth;
/**
@@ -208,8 +214,8 @@
this.rootPaths.add(rootPath);
}
this.sourcePath = sourcePath;
- this.fSourceRanges = new HashMap();
- this.fParameterNames = new HashMap();
+ this.sourceRanges = new HashMap();
+ this.parameterNames = new HashMap();
this.importsTable = new HashMap();
this.importsCounterTable = new HashMap();
}
@@ -220,7 +226,7 @@
public void acceptImport(
int declarationStart,
int declarationEnd,
- char[] name,
+ char[][] tokens,
boolean onDemand,
int modifiers) {
char[][] imports = (char[][]) this.importsTable.get(this.binaryType);
@@ -239,6 +245,7 @@
0,
importsCounter);
}
+ char[] name = CharOperation.concatWith(tokens, '.');
if (onDemand) {
int nameLength = name.length;
System.arraycopy(name, 0, (name = new char[nameLength + 2]), 0, nameLength);
@@ -270,17 +277,24 @@
/**
* @see ISourceElementRequestor
*/
- public void acceptProblem(IProblem problem) {
+ public void acceptProblem(CategorizedProblem problem) {
//do nothing
}
+ private void addCategories(IJavaElement element, char[][] elementCategories) {
+ if (elementCategories == null) return;
+ if (this.categories == null)
+ this.categories = new HashMap();
+ this.categories.put(element, CharOperation.toStrings(elementCategories));
+ }
+
/**
* Closes this <code>SourceMapper</code>'s zip file. Once this is done, this
* <code>SourceMapper</code> cannot be used again.
*/
public void close() {
- fSourceRanges = null;
- fParameterNames = null;
+ this.sourceRanges = null;
+ this.parameterNames = null;
}
/**
@@ -291,26 +305,57 @@
*/
private String[] convertTypeNamesToSigs(char[][] typeNames) {
if (typeNames == null)
- return fgEmptyStringArray;
+ return CharOperation.NO_STRINGS;
int n = typeNames.length;
if (n == 0)
- return fgEmptyStringArray;
+ return CharOperation.NO_STRINGS;
String[] typeSigs = new String[n];
for (int i = 0; i < n; ++i) {
- String typeSig = Signature.createTypeSignature(typeNames[i], false);
- int lastIndex = typeSig.lastIndexOf('.');
- if (lastIndex == -1) {
- typeSigs[i] = typeSig;
+ char[] typeSig = Signature.createCharArrayTypeSignature(typeNames[i], false);
+
+ // transforms signatures that contains a qualification into unqualified signatures
+ // e.g. "QX<+QMap.Entry;>;" becomes "QX<+QEntry;>;"
+ StringBuffer simpleTypeSig = null;
+ int start = 0;
+ int dot = -1;
+ int length = typeSig.length;
+ for (int j = 0; j < length; j++) {
+ switch (typeSig[j]) {
+ case Signature.C_UNRESOLVED:
+ if (simpleTypeSig != null)
+ simpleTypeSig.append(typeSig, start, j-start);
+ start = j;
+ break;
+ case Signature.C_DOT:
+ dot = j;
+ break;
+ case Signature.C_GENERIC_START:
+ case Signature.C_NAME_END:
+ if (dot > start) {
+ if (simpleTypeSig == null)
+ simpleTypeSig = new StringBuffer().append(typeSig, 0, start);
+ simpleTypeSig.append(Signature.C_UNRESOLVED);
+ simpleTypeSig.append(typeSig, dot+1, j-dot-1);
+ start = j;
+ }
+ break;
+ }
+ }
+ if (simpleTypeSig == null) {
+ typeSigs[i] = new String(typeSig);
} else {
- int arrayEnd = 0;
- while(typeSig.charAt(arrayEnd) == Signature.C_ARRAY) arrayEnd++;
- typeSigs[i] = typeSig.substring(0, arrayEnd) + Signature.C_UNRESOLVED + typeSig.substring(lastIndex + 1, typeSig.length());
+ simpleTypeSig.append(typeSig, start, length-start);
+ typeSigs[i] = simpleTypeSig.toString();
}
}
return typeSigs;
}
- private void computeAllRootPaths(IPackageFragmentRoot root) {
+ private synchronized void computeAllRootPaths(IType type) {
+ if (this.areRootPathsComputed) {
+ return;
+ }
+ IPackageFragmentRoot root = (IPackageFragmentRoot) type.getPackageFragment().getParent();
final HashSet tempRoots = new HashSet();
long time = 0;
if (VERBOSE) {
@@ -322,6 +367,9 @@
if (root.isArchive()) {
JarPackageFragmentRoot jarPackageFragmentRoot = (JarPackageFragmentRoot) root;
+ IJavaProject project = jarPackageFragmentRoot.getJavaProject();
+ String sourceLevel = null;
+ String complianceLevel = null;
JavaModelManager manager = JavaModelManager.getJavaModelManager();
ZipFile zip = null;
try {
@@ -334,7 +382,11 @@
if (index != -1 && Util.isClassFileName(entryName)) {
String firstLevelPackageName = entryName.substring(0, index);
if (!firstLevelPackageNames.contains(firstLevelPackageName)) {
- IStatus status = JavaConventions.validatePackageName(firstLevelPackageName);
+ if (sourceLevel == null) {
+ sourceLevel = project.getOption(JavaCore.COMPILER_SOURCE, true);
+ complianceLevel = project.getOption(JavaCore.COMPILER_COMPLIANCE, true);
+ }
+ IStatus status = JavaConventions.validatePackageName(firstLevelPackageName, sourceLevel, complianceLevel);
if (status.isOK() || status.getSeverity() == IStatus.WARNING) {
firstLevelPackageNames.add(firstLevelPackageName);
}
@@ -396,7 +448,7 @@
IPath path = new Path(entryName);
int segmentCount = path.segmentCount();
if (segmentCount > 1) {
- loop: for (int i = 0, max = path.segmentCount() - 1; i < max; i++) {
+ for (int i = 0, max = path.segmentCount() - 1; i < max; i++) {
if (firstLevelPackageNames.contains(path.segment(i))) {
tempRoots.add(path.uptoSegment(i));
// don't break here as this path could contain other first level package names (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=74014)
@@ -556,35 +608,41 @@
0,
this.typeDepth);
System.arraycopy(
- this.fMemberName,
+ this.memberName,
0,
- this.fMemberName = new String[this.typeDepth * 2],
+ this.memberName = new String[this.typeDepth * 2],
0,
this.typeDepth);
System.arraycopy(
- this.fMemberDeclarationStart,
+ this.memberDeclarationStart,
0,
- this.fMemberDeclarationStart = new int[this.typeDepth * 2],
+ this.memberDeclarationStart = new int[this.typeDepth * 2],
0,
this.typeDepth);
System.arraycopy(
- this.fMemberNameRange,
+ this.memberNameRange,
0,
- this.fMemberNameRange = new SourceRange[this.typeDepth * 2],
+ this.memberNameRange = new SourceRange[this.typeDepth * 2],
0,
this.typeDepth);
System.arraycopy(
- this.fMethodParameterTypes,
+ this.methodParameterTypes,
0,
- this.fMethodParameterTypes = new char[this.typeDepth * 2][][],
+ this.methodParameterTypes = new char[this.typeDepth * 2][][],
0,
this.typeDepth);
System.arraycopy(
- this.fMethodParameterNames,
+ this.methodParameterNames,
0,
- this.fMethodParameterNames = new char[this.typeDepth * 2][][],
+ this.methodParameterNames = new char[this.typeDepth * 2][][],
0,
this.typeDepth);
+ System.arraycopy(
+ this.typeModifiers,
+ 0,
+ this.typeModifiers = new int[this.typeDepth * 2],
+ 0,
+ this.typeDepth);
}
if (typeInfo.name.length == 0) {
this.anonymousCounter++;
@@ -600,11 +658,13 @@
new SourceRange(typeInfo.nameSourceStart, typeInfo.nameSourceEnd - typeInfo.nameSourceStart + 1);
this.typeDeclarationStarts[typeDepth] = typeInfo.declarationStart;
+ IType currentType = this.types[typeDepth];
+
+ // type parameters
if (typeInfo.typeParameters != null) {
- final IType currentType = this.types[typeDepth];
for (int i = 0, length = typeInfo.typeParameters.length; i < length; i++) {
- final TypeParameterInfo typeParameterInfo = typeInfo.typeParameters[i];
- final ITypeParameter typeParameter = currentType.getTypeParameter(new String(typeParameterInfo.name));
+ TypeParameterInfo typeParameterInfo = typeInfo.typeParameters[i];
+ ITypeParameter typeParameter = currentType.getTypeParameter(new String(typeParameterInfo.name));
setSourceRange(
typeParameter,
new SourceRange(
@@ -615,6 +675,12 @@
typeParameterInfo.nameSourceEnd - typeParameterInfo.nameSourceStart + 1));
}
}
+
+ // type modifiers
+ this.typeModifiers[typeDepth] = typeInfo.modifiers;
+
+ // categories
+ addCategories(currentType, typeInfo.categories);
}
/**
@@ -636,10 +702,16 @@
*/
public void enterField(FieldInfo fieldInfo) {
if (typeDepth >= 0) {
- fMemberDeclarationStart[typeDepth] = fieldInfo.declarationStart;
- fMemberNameRange[typeDepth] =
+ this.memberDeclarationStart[typeDepth] = fieldInfo.declarationStart;
+ this.memberNameRange[typeDepth] =
new SourceRange(fieldInfo.nameSourceStart, fieldInfo.nameSourceEnd - fieldInfo.nameSourceStart + 1);
- fMemberName[typeDepth] = new String(fieldInfo.name);
+ String fieldName = new String(fieldInfo.name);
+ this.memberName[typeDepth] = fieldName;
+
+ // categories
+ IType currentType = this.types[typeDepth];
+ IField field = currentType.getField(fieldName);
+ addCategories(field, fieldInfo.categories);
}
}
@@ -660,23 +732,46 @@
}
private void enterAbstractMethod(MethodInfo methodInfo) {
if (typeDepth >= 0) {
- fMemberName[typeDepth] = new String(methodInfo.name);
- fMemberNameRange[typeDepth] =
+ this.memberName[typeDepth] = new String(methodInfo.name);
+ this.memberNameRange[typeDepth] =
new SourceRange(methodInfo.nameSourceStart, methodInfo.nameSourceEnd - methodInfo.nameSourceStart + 1);
- fMemberDeclarationStart[typeDepth] = methodInfo.declarationStart;
- fMethodParameterTypes[typeDepth] = methodInfo.parameterTypes;
- fMethodParameterNames[typeDepth] = methodInfo. parameterNames;
+ this.memberDeclarationStart[typeDepth] = methodInfo.declarationStart;
+ IType currentType = this.types[typeDepth];
+ int currenTypeModifiers = this.typeModifiers[typeDepth];
+ char[][] parameterTypes = methodInfo.parameterTypes;
+ if (parameterTypes != null && methodInfo.isConstructor && currentType.getDeclaringType() != null && !Flags.isStatic(currenTypeModifiers)) {
+ IType declaringType = currentType.getDeclaringType();
+ String declaringTypeName = declaringType.getElementName();
+ if (declaringTypeName.length() == 0) {
+ IClassFile classFile = declaringType.getClassFile();
+ int length = parameterTypes.length;
+ char[][] newParameterTypes = new char[length+1][];
+ declaringTypeName = classFile.getElementName();
+ declaringTypeName = declaringTypeName.substring(0, declaringTypeName.indexOf('.'));
+ newParameterTypes[0] = declaringTypeName.toCharArray();
+ System.arraycopy(parameterTypes, 0, newParameterTypes, 1, length);
+ this.methodParameterTypes[typeDepth] = newParameterTypes;
+ } else {
+ int length = parameterTypes.length;
+ char[][] newParameterTypes = new char[length+1][];
+ newParameterTypes[0] = declaringTypeName.toCharArray();
+ System.arraycopy(parameterTypes, 0, newParameterTypes, 1, length);
+ this.methodParameterTypes[typeDepth] = newParameterTypes;
+ }
+ } else {
+ this.methodParameterTypes[typeDepth] = parameterTypes;
+ }
+ this.methodParameterNames[typeDepth] = methodInfo.parameterNames;
+ IMethod method = currentType.getMethod(
+ this.memberName[typeDepth],
+ convertTypeNamesToSigs(this.methodParameterTypes[typeDepth]));
+
+ // type parameters
if (methodInfo.typeParameters != null) {
- final IType currentType = this.types[typeDepth];
- IMethod method = currentType.getMethod(
- fMemberName[typeDepth],
- convertTypeNamesToSigs(fMethodParameterTypes[typeDepth]));
- if (method == null) return;
-
for (int i = 0, length = methodInfo.typeParameters.length; i < length; i++) {
- final TypeParameterInfo typeParameterInfo = methodInfo.typeParameters[i];
- final ITypeParameter typeParameter = method.getTypeParameter(new String(typeParameterInfo.name));
+ TypeParameterInfo typeParameterInfo = methodInfo.typeParameters[i];
+ ITypeParameter typeParameter = method.getTypeParameter(new String(typeParameterInfo.name));
setSourceRange(
typeParameter,
new SourceRange(
@@ -687,6 +782,9 @@
typeParameterInfo.nameSourceEnd - typeParameterInfo.nameSourceStart + 1));
}
}
+
+ // categories
+ addCategories(method, methodInfo.categories);
}
}
@@ -727,11 +825,11 @@
if (typeDepth >= 0) {
IType currentType = this.types[typeDepth];
setSourceRange(
- currentType.getField(fMemberName[typeDepth]),
+ currentType.getField(this.memberName[typeDepth]),
new SourceRange(
- fMemberDeclarationStart[typeDepth],
- declarationEnd - fMemberDeclarationStart[typeDepth] + 1),
- fMemberNameRange[typeDepth]);
+ this.memberDeclarationStart[typeDepth],
+ declarationEnd - this.memberDeclarationStart[typeDepth] + 1),
+ this.memberNameRange[typeDepth]);
}
}
@@ -753,18 +851,18 @@
IType currentType = this.types[typeDepth];
SourceRange sourceRange =
new SourceRange(
- fMemberDeclarationStart[typeDepth],
- declarationEnd - fMemberDeclarationStart[typeDepth] + 1);
+ this.memberDeclarationStart[typeDepth],
+ declarationEnd - this.memberDeclarationStart[typeDepth] + 1);
IMethod method = currentType.getMethod(
- fMemberName[typeDepth],
- convertTypeNamesToSigs(fMethodParameterTypes[typeDepth]));
+ this.memberName[typeDepth],
+ convertTypeNamesToSigs(this.methodParameterTypes[typeDepth]));
setSourceRange(
method,
sourceRange,
- fMemberNameRange[typeDepth]);
+ this.memberNameRange[typeDepth]);
setMethodParameterNames(
method,
- fMethodParameterNames[typeDepth]);
+ this.methodParameterNames[typeDepth]);
}
}
@@ -773,23 +871,11 @@
* SourceMapper's ZIP file, or returns <code>null</code> if source
* code cannot be found.
*/
- public char[] findSource(IType type) {
+ public char[] findSource(IType type, IBinaryType info) {
if (!type.isBinary()) {
return null;
}
- BinaryType parent = (BinaryType) type.getDeclaringType();
- BinaryType declType = (BinaryType) type;
- while (parent != null) {
- declType = parent;
- parent = (BinaryType) declType.getDeclaringType();
- }
- IBinaryType info = null;
- try {
- info = (IBinaryType) declType.getElementInfo();
- } catch (JavaModelException e) {
- return null;
- }
- String simpleSourceFileName = declType.sourceFileName(info);
+ String simpleSourceFileName = ((BinaryType) type).getSourceFileName(info);
if (simpleSourceFileName == null) {
return null;
}
@@ -818,13 +904,7 @@
}
if (source == null) {
- if (!areRootPathsComputed) {
- computeAllRootPaths((IPackageFragmentRoot) type.getPackageFragment().getParent());
- }
- /*
- * We should try all existing root paths. If none works, try to recompute it.
- * If it still doesn't work, then return null
- */
+ computeAllRootPaths(type);
if (this.rootPaths != null) {
loop: for (Iterator iterator = this.rootPaths.iterator(); iterator.hasNext(); ) {
String currentRootPath = (String) iterator.next();
@@ -919,7 +999,7 @@
case IJavaElement.METHOD :
if (((IMember) element).isBinary()) {
IJavaElement[] el = getUnqualifiedMethodHandle((IMethod) element, false);
- if(el[1] != null && fSourceRanges.get(el[0]) == null) {
+ if(el[1] != null && this.sourceRanges.get(el[0]) == null) {
element = getUnqualifiedMethodHandle((IMethod) element, true)[0];
} else {
element = el[0];
@@ -932,7 +1012,7 @@
IMethod method = (IMethod) parent;
if (method.isBinary()) {
IJavaElement[] el = getUnqualifiedMethodHandle(method, false);
- if(el[1] != null && fSourceRanges.get(el[0]) == null) {
+ if(el[1] != null && this.sourceRanges.get(el[0]) == null) {
method = (IMethod) getUnqualifiedMethodHandle(method, true)[0];
} else {
method = (IMethod) el[0];
@@ -941,9 +1021,9 @@
}
}
}
- SourceRange[] ranges = (SourceRange[]) fSourceRanges.get(element);
+ SourceRange[] ranges = (SourceRange[]) this.sourceRanges.get(element);
if (ranges == null) {
- return fgUnknownRange;
+ return UNKNOWN_RANGE;
} else {
return ranges[1];
}
@@ -956,17 +1036,17 @@
public char[][] getMethodParameterNames(IMethod method) {
if (method.isBinary()) {
IJavaElement[] el = getUnqualifiedMethodHandle(method, false);
- if(el[1] != null && fParameterNames.get(el[0]) == null) {
+ if(el[1] != null && this.parameterNames.get(el[0]) == null) {
method = (IMethod) getUnqualifiedMethodHandle(method, true)[0];
} else {
method = (IMethod) el[0];
}
}
- char[][] parameterNames = (char[][]) fParameterNames.get(method);
- if (parameterNames == null) {
+ char[][] parameters = (char[][]) this.parameterNames.get(method);
+ if (parameters == null) {
return null;
} else {
- return parameterNames;
+ return parameters;
}
}
@@ -979,7 +1059,7 @@
case IJavaElement.METHOD :
if (((IMember) element).isBinary()) {
IJavaElement[] el = getUnqualifiedMethodHandle((IMethod) element, false);
- if(el[1] != null && fSourceRanges.get(el[0]) == null) {
+ if(el[1] != null && this.sourceRanges.get(el[0]) == null) {
element = getUnqualifiedMethodHandle((IMethod) element, true)[0];
} else {
element = el[0];
@@ -992,7 +1072,7 @@
IMethod method = (IMethod) parent;
if (method.isBinary()) {
IJavaElement[] el = getUnqualifiedMethodHandle(method, false);
- if(el[1] != null && fSourceRanges.get(el[0]) == null) {
+ if(el[1] != null && this.sourceRanges.get(el[0]) == null) {
method = (IMethod) getUnqualifiedMethodHandle(method, true)[0];
} else {
method = (IMethod) el[0];
@@ -1001,9 +1081,9 @@
}
}
}
- SourceRange[] ranges = (SourceRange[]) fSourceRanges.get(element);
+ SourceRange[] ranges = (SourceRange[]) this.sourceRanges.get(element);
if (ranges == null) {
- return fgUnknownRange;
+ return UNKNOWN_RANGE;
} else {
return ranges[0];
}
@@ -1022,7 +1102,6 @@
for (int i = 0; i <= lastDollar; i++)
newClassFileName.append(classFileName.charAt(i));
newClassFileName.append(Integer.toString(this.anonymousCounter));
- newClassFileName.append(SuffixConstants.SUFFIX_class);
PackageFragment pkg = (PackageFragment) classFile.getParent();
return new BinaryType(new ClassFile(pkg, newClassFileName.toString()), typeName);
} else if (this.binaryType.getElementName().equals(typeName))
@@ -1040,48 +1119,10 @@
String[] qualifiedParameterTypes = method.getParameterTypes();
String[] unqualifiedParameterTypes = new String[qualifiedParameterTypes.length];
for (int i = 0; i < qualifiedParameterTypes.length; i++) {
- StringBuffer unqualifiedName = new StringBuffer();
- String qualifiedName = qualifiedParameterTypes[i];
- int count = 0;
- while (qualifiedName.charAt(count) == Signature.C_ARRAY) {
- unqualifiedName.append(Signature.C_ARRAY);
- ++count;
- }
- char currentChar = qualifiedName.charAt(count);
- if (currentChar == Signature.C_RESOLVED || currentChar == Signature.C_TYPE_VARIABLE) {
- unqualifiedName.append(Signature.C_UNRESOLVED);
- String simpleName = Signature.getSimpleName(qualifiedName.substring(count+1));
- int lastDollar = simpleName.lastIndexOf('$');
- hasDollar |= lastDollar != -1;
- int start = noDollar ? lastDollar + 1 : 0;
- boolean sigStart = false;
- for (int j = start, length = simpleName.length(); j < length; j++) {
- char current = simpleName.charAt(j);
- switch (current) {
- case Signature.C_SUPER:
- case Signature.C_EXTENDS:
- case Signature.C_GENERIC_START:
- case Signature.C_NAME_END:
- unqualifiedName.append(current);
- sigStart = true;
- break;
- default:
- if (sigStart) {
- if (current == Signature.C_TYPE_VARIABLE) {
- unqualifiedName.append(Signature.C_UNRESOLVED);
- } else {
- unqualifiedName.append(current);
- }
- sigStart = false;
- } else {
- unqualifiedName.append(current);
- }
- }
- }
- } else {
- unqualifiedName.append(qualifiedName.substring(count, qualifiedName.length()));
- }
- unqualifiedParameterTypes[i] = unqualifiedName.toString();
+ StringBuffer unqualifiedTypeSig = new StringBuffer();
+ getUnqualifiedTypeSignature(qualifiedParameterTypes[i], 0/*start*/, qualifiedParameterTypes[i].length(), unqualifiedTypeSig, noDollar);
+ unqualifiedParameterTypes[i] = unqualifiedTypeSig.toString();
+ hasDollar |= unqualifiedParameterTypes[i].lastIndexOf('$') != -1;
}
IJavaElement[] result = new IJavaElement[2];
@@ -1093,12 +1134,89 @@
}
return result;
}
+
+ private int getUnqualifiedTypeSignature(String qualifiedTypeSig, int start, int length, StringBuffer unqualifiedTypeSig, boolean noDollar) {
+ char firstChar = qualifiedTypeSig.charAt(start);
+ int end = start + 1;
+ boolean sigStart = false;
+ firstPass: for (int i = start; i < length; i++) {
+ char current = qualifiedTypeSig.charAt(i);
+ switch (current) {
+ case Signature.C_ARRAY :
+ case Signature.C_SUPER:
+ case Signature.C_EXTENDS:
+ unqualifiedTypeSig.append(current);
+ start = i + 1;
+ end = start + 1;
+ firstChar = qualifiedTypeSig.charAt(start);
+ break;
+ case Signature.C_RESOLVED :
+ case Signature.C_UNRESOLVED :
+ case Signature.C_TYPE_VARIABLE :
+ if (!sigStart) {
+ start = ++i;
+ sigStart = true;
+ }
+ break;
+ case Signature.C_NAME_END:
+ case Signature.C_GENERIC_START :
+ end = i;
+ break firstPass;
+ case Signature.C_STAR :
+ unqualifiedTypeSig.append(current);
+ start = i + 1;
+ end = start + 1;
+ firstChar = qualifiedTypeSig.charAt(start);
+ break;
+ case Signature.C_GENERIC_END :
+ return i;
+ case Signature.C_DOT:
+ start = ++i;
+ break;
+ }
+ }
+ switch (firstChar) {
+ case Signature.C_RESOLVED :
+ case Signature.C_UNRESOLVED :
+ case Signature.C_TYPE_VARIABLE :
+ unqualifiedTypeSig.append(Signature.C_UNRESOLVED);
+ if (noDollar) {
+ int lastDollar = qualifiedTypeSig.lastIndexOf('$', end);
+ if (lastDollar > start)
+ start = lastDollar + 1;
+ }
+ for (int i = start; i < length; i++) {
+ char current = qualifiedTypeSig.charAt(i);
+ switch (current) {
+ case Signature.C_GENERIC_START:
+ unqualifiedTypeSig.append(current);
+ i++;
+ do {
+ i = getUnqualifiedTypeSignature(qualifiedTypeSig, i, length, unqualifiedTypeSig, noDollar);
+ } while (qualifiedTypeSig.charAt(i) != Signature.C_GENERIC_END);
+ unqualifiedTypeSig.append(Signature.C_GENERIC_END);
+ break;
+ case Signature.C_NAME_END:
+ unqualifiedTypeSig.append(current);
+ return i + 1;
+ default:
+ unqualifiedTypeSig.append(current);
+ break;
+ }
+ }
+ return length;
+ default :
+ // primitive type or wildcard
+ unqualifiedTypeSig.append(qualifiedTypeSig.substring(start, end));
+ return end;
+ }
+ }
/**
* Maps the given source code to the given binary type and its children.
*/
- public void mapSource(IType type, char[] contents) {
- this.mapSource(type, contents, null);
+ public void mapSource(IType type, char[] contents, IBinaryType info) {
+ this.mapSource(type, contents, info, null);
}
/**
@@ -1109,12 +1227,13 @@
public synchronized ISourceRange mapSource(
IType type,
char[] contents,
+ IBinaryType info,
IJavaElement elementToFind) {
this.binaryType = (BinaryType) type;
// check whether it is already mapped
- if (this.fSourceRanges.get(type) != null) return (elementToFind != null) ? this.getNameRange(elementToFind) : null;
+ if (this.sourceRanges.get(type) != null) return (elementToFind != null) ? getNameRange(elementToFind) : null;
this.importsTable.remove(this.binaryType);
this.importsCounterTable.remove(this.binaryType);
@@ -1122,29 +1241,29 @@
this.types = new IType[1];
this.typeDeclarationStarts = new int[1];
this.typeNameRanges = new SourceRange[1];
+ this.typeModifiers = new int[1];
this.typeDepth = -1;
- this.fMemberDeclarationStart = new int[1];
- this.fMemberName = new String[1];
- this.fMemberNameRange = new SourceRange[1];
- this.fMethodParameterTypes = new char[1][][];
- this.fMethodParameterNames = new char[1][][];
+ this.memberDeclarationStart = new int[1];
+ this.memberName = new String[1];
+ this.memberNameRange = new SourceRange[1];
+ this.methodParameterTypes = new char[1][][];
+ this.methodParameterNames = new char[1][][];
this.anonymousCounter = 0;
- HashMap oldSourceRanges = (HashMap) fSourceRanges.clone();
+ HashMap oldSourceRanges = (HashMap) this.sourceRanges.clone();
try {
IProblemFactory factory = new DefaultProblemFactory();
SourceElementParser parser = null;
- boolean isAnonymousClass = false;
- char[] fullName = null;
this.anonymousClassName = 0;
- IBinaryType info = null;
- try {
- info = (IBinaryType) this.binaryType.getElementInfo();
- isAnonymousClass = info.isAnonymous();
- fullName = info.getName();
- } catch(JavaModelException e) {
- // ignore
+ if (info == null) {
+ try {
+ info = (IBinaryType) this.binaryType.getElementInfo();
+ } catch(JavaModelException e) {
+ return null;
+ }
}
+ boolean isAnonymousClass = info.isAnonymous();
+ char[] fullName = info.getName();
if (isAnonymousClass) {
String eltName = this.binaryType.getParent().getElementName();
eltName = eltName.substring(eltName.lastIndexOf('$') + 1, eltName.length());
@@ -1170,7 +1289,7 @@
}
} finally {
if (elementToFind != null) {
- fSourceRanges = oldSourceRanges;
+ this.sourceRanges = oldSourceRanges;
}
this.binaryType = null;
this.searchedElement = null;
@@ -1195,7 +1314,7 @@
/**
* Sets the mapping for this method to its parameter names.
*
- * @see #fParameterNames
+ * @see #parameterNames
*/
protected void setMethodParameterNames(
IMethod method,
@@ -1203,20 +1322,20 @@
if (parameterNames == null) {
parameterNames = CharOperation.NO_CHAR_CHAR;
}
- fParameterNames.put(method, parameterNames);
+ this.parameterNames.put(method, parameterNames);
}
/**
* Sets the mapping for this element to its source ranges for its source range
* and name range.
*
- * @see #fSourceRanges
+ * @see #sourceRanges
*/
protected void setSourceRange(
IJavaElement element,
SourceRange sourceRange,
SourceRange nameRange) {
- fSourceRanges.put(element, new SourceRange[] { sourceRange, nameRange });
+ this.sourceRanges.put(element, new SourceRange[] { sourceRange, nameRange });
}
/**
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMethod.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMethod.java
index e337487..4f60530 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMethod.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMethod.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -11,11 +11,6 @@
package org.eclipse.jdt.internal.core;
import org.eclipse.jdt.core.*;
-import org.eclipse.jdt.core.Flags;
-import org.eclipse.jdt.core.IMethod;
-import org.eclipse.jdt.core.IType;
-import org.eclipse.jdt.core.JavaModelException;
-import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.core.util.Util;
@@ -35,7 +30,8 @@
protected SourceMethod(JavaElement parent, String name, String[] parameterTypes) {
super(parent, name);
- Assert.isTrue(name.indexOf('.') == -1);
+ // Assertion disabled since bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=179011
+ // Assert.isTrue(name.indexOf('.') == -1);
if (parameterTypes == null) {
this.parameterTypes= CharOperation.NO_STRINGS;
} else {
@@ -170,6 +166,9 @@
IJavaElement primaryParent = this.parent.getPrimaryElement(false);
return ((IType)primaryParent).getMethod(this.name, this.parameterTypes);
}
+public String[] getRawParameterNames() throws JavaModelException {
+ return getParameterNames();
+}
/**
* @see IMethod
*/
@@ -198,6 +197,10 @@
* @see IMethod
*/
public boolean isConstructor() throws JavaModelException {
+ if (!this.getElementName().equals(this.parent.getElementName())) {
+ // faster than reaching the info
+ return false;
+ }
SourceMethodElementInfo info = (SourceMethodElementInfo) getElementInfo();
return info.isConstructor();
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMethodElementInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMethodElementInfo.java
index 5230b2f..f9ba197 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMethodElementInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMethodElementInfo.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMethodInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMethodInfo.java
index e4c54c2..ce8489c 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMethodInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMethodInfo.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004 IBM Corporation and others.
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceRange.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceRange.java
index 7332b9c..169e91b 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceRange.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceRange.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -23,6 +23,15 @@
this.offset = offset;
this.length = length;
}
+/*
+ * @see Object#equals(Object)
+ */
+public boolean equals(Object obj) {
+ if (!(obj instanceof ISourceRange))
+ return false;
+ ISourceRange sourceRange = (ISourceRange) obj;
+ return sourceRange.getOffset() == this.offset && sourceRange.getLength() == this.length;
+}
/**
* @see ISourceRange
*/
@@ -35,6 +44,12 @@
public int getOffset() {
return this.offset;
}
+/*
+ * @see Object#hashCode()
+ */
+public int hashCode() {
+ return this.length ^ this.offset;
+}
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append("[offset="); //$NON-NLS-1$
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceRefElement.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceRefElement.java
index daff756..26ce57e 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceRefElement.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceRefElement.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -16,13 +16,6 @@
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.*;
-import org.eclipse.jdt.core.IBuffer;
-import org.eclipse.jdt.core.ICompilationUnit;
-import org.eclipse.jdt.core.IJavaElement;
-import org.eclipse.jdt.core.IOpenable;
-import org.eclipse.jdt.core.ISourceRange;
-import org.eclipse.jdt.core.ISourceReference;
-import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.internal.core.util.DOMFinder;
@@ -118,7 +111,7 @@
* @see IMember
*/
public ICompilationUnit getCompilationUnit() {
- return ((JavaElement)getParent()).getCompilationUnit();
+ return (ICompilationUnit) getAncestor(COMPILATION_UNIT);
}
/**
* Elements within compilation units and class files have no
@@ -158,6 +151,12 @@
String token = memento.nextToken();
return getHandleFromMemento(token, memento, owner);
}
+/*
+ * @see IMember#getOccurrenceCount()
+ */
+public int getOccurrenceCount() {
+ return this.occurrenceCount;
+}
/**
* Return the first instance of IOpenable in the hierarchy of this
* type (going up the hierarchy from this type);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceRefElementInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceRefElementInfo.java
index fe09baf..12838c1 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceRefElementInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceRefElementInfo.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceType.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceType.java
index ff40087..a76d21b 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceType.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceType.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -12,16 +12,17 @@
import java.io.InputStream;
import java.util.ArrayList;
+import java.util.HashMap;
+import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.*;
import org.eclipse.jdt.core.compiler.*;
-import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.internal.codeassist.CompletionEngine;
import org.eclipse.jdt.internal.codeassist.ISelectionRequestor;
import org.eclipse.jdt.internal.codeassist.SelectionEngine;
-import org.eclipse.jdt.internal.compiler.env.IGenericType;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.env.ISourceType;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.core.hierarchy.TypeHierarchy;
@@ -40,7 +41,6 @@
protected SourceType(JavaElement parent, String name) {
super(parent, name);
- Assert.isTrue(name.indexOf('.') == -1, Messages.bind(Messages.sourcetype_invalidName, name));
}
protected void closing(Object info) throws JavaModelException {
super.closing(info);
@@ -168,6 +168,29 @@
return null;
}
}
+public IJavaElement[] getChildrenForCategory(String category) throws JavaModelException {
+ IJavaElement[] children = getChildren();
+ int length = children.length;
+ if (length == 0) return NO_ELEMENTS;
+ SourceTypeElementInfo info = (SourceTypeElementInfo) getElementInfo();
+ HashMap categories = info.getCategories();
+ if (categories == null) return NO_ELEMENTS;
+ IJavaElement[] result = new IJavaElement[length];
+ int index = 0;
+ for (int i = 0; i < length; i++) {
+ IJavaElement child = children[i];
+ String[] elementCategories = (String[]) categories.get(child);
+ if (elementCategories != null)
+ for (int j = 0, length2 = elementCategories.length; j < length2; j++) {
+ if (elementCategories[j].equals(category))
+ result[index++] = child;
+ }
+ }
+ if (index == 0) return NO_ELEMENTS;
+ if (index < length)
+ System.arraycopy(result, 0, result = new IJavaElement[index], 0, index);
+ return result;
+}
/**
* @see IMember
*/
@@ -274,17 +297,13 @@
String[] parameters = new String[params.size()];
params.toArray(parameters);
JavaElement method = (JavaElement)getMethod(selector, parameters);
- if (token != null) {
- switch (token.charAt(0)) {
- case JEM_TYPE:
- case JEM_TYPE_PARAMETER:
- case JEM_LOCALVARIABLE:
- return method.getHandleFromMemento(token, memento, workingCopyOwner);
- default:
- return method;
- }
- } else {
- return method;
+ switch (token.charAt(0)) {
+ case JEM_TYPE:
+ case JEM_TYPE_PARAMETER:
+ case JEM_LOCALVARIABLE:
+ return method.getHandleFromMemento(token, memento, workingCopyOwner);
+ default:
+ return method;
}
case JEM_TYPE:
String typeName;
@@ -524,7 +543,7 @@
*/
public boolean isClass() throws JavaModelException {
SourceTypeElementInfo info = (SourceTypeElementInfo) getElementInfo();
- return info.getKind() == IGenericType.CLASS_DECL;
+ return TypeDeclaration.kind(info.getModifiers()) == TypeDeclaration.CLASS_DECL;
}
/**
@@ -533,7 +552,7 @@
*/
public boolean isEnum() throws JavaModelException {
SourceTypeElementInfo info = (SourceTypeElementInfo) getElementInfo();
- return info.getKind() == IGenericType.ENUM_DECL;
+ return TypeDeclaration.kind(info.getModifiers()) == TypeDeclaration.ENUM_DECL;
}
/**
@@ -541,9 +560,9 @@
*/
public boolean isInterface() throws JavaModelException {
SourceTypeElementInfo info = (SourceTypeElementInfo) getElementInfo();
- switch (info.getKind()) {
- case IGenericType.INTERFACE_DECL:
- case IGenericType.ANNOTATION_TYPE_DECL: // annotation is interface too
+ switch (TypeDeclaration.kind(info.getModifiers())) {
+ case TypeDeclaration.INTERFACE_DECL:
+ case TypeDeclaration.ANNOTATION_TYPE_DECL: // annotation is interface too
return true;
}
return false;
@@ -555,14 +574,21 @@
*/
public boolean isAnnotation() throws JavaModelException {
SourceTypeElementInfo info = (SourceTypeElementInfo) getElementInfo();
- return info.getKind() == IGenericType.ANNOTATION_TYPE_DECL;
+ return TypeDeclaration.kind(info.getModifiers()) == TypeDeclaration.ANNOTATION_TYPE_DECL;
}
/**
* @see IType#isLocal()
*/
public boolean isLocal() {
- return this.parent instanceof IMethod || this.parent instanceof IInitializer;
+ switch (this.parent.getElementType()) {
+ case IJavaElement.METHOD:
+ case IJavaElement.INITIALIZER:
+ case IJavaElement.FIELD:
+ return true;
+ default:
+ return false;
+ }
}
/**
* @see IType#isMember()
@@ -791,13 +817,13 @@
this.answers[length] = answer;
}
}
- public void acceptError(IProblem error) {
+ public void acceptError(CategorizedProblem error) {
// ignore
}
public void acceptField(char[] declaringTypePackageName, char[] declaringTypeName, char[] fieldName, boolean isDeclaration, char[] uniqueKey, int start, int end) {
// ignore
}
- public void acceptMethod(char[] declaringTypePackageName, char[] declaringTypeName, String enclosingDeclaringTypeSignature, char[] selector, char[][] parameterPackageNames, char[][] parameterTypeNames, String[] parameterSignatures, boolean isConstructor, boolean isDeclaration, char[] uniqueKey, int start, int end) {
+ public void acceptMethod(char[] declaringTypePackageName, char[] declaringTypeName, String enclosingDeclaringTypeSignature, char[] selector, char[][] parameterPackageNames, char[][] parameterTypeNames, String[] parameterSignatures, char[][] typeParameterNames, char[][][] typeParameterBoundNames, boolean isConstructor, boolean isDeclaration, char[] uniqueKey, int start, int end) {
// ignore
}
public void acceptPackage(char[] packageName){
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceTypeElementInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceTypeElementInfo.java
index ec9777a..de57e1c 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceTypeElementInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceTypeElementInfo.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,13 +10,10 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core;
+import java.util.HashMap;
+
import org.eclipse.jdt.core.*;
-import org.eclipse.jdt.core.IJavaElement;
-import org.eclipse.jdt.core.IType;
-import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.compiler.env.IConstants;
-import org.eclipse.jdt.internal.compiler.env.IGenericType;
import org.eclipse.jdt.internal.compiler.env.ISourceField;
import org.eclipse.jdt.internal.compiler.env.ISourceImport;
import org.eclipse.jdt.internal.compiler.env.ISourceMethod;
@@ -57,6 +54,25 @@
* The type parameters of this source type. Empty if none.
*/
protected ITypeParameter[] typeParameters = TypeParameter.NO_TYPE_PARAMETERS;
+
+ /*
+ * A map from an IJavaElement (this type or a child of this type) to a String[] (the categories of this element)
+ */
+ protected HashMap categories;
+
+protected void addCategories(IJavaElement element, char[][] elementCategories) {
+ if (elementCategories == null) return;
+ if (this.categories == null)
+ this.categories = new HashMap();
+ this.categories.put(element, CharOperation.toStrings(elementCategories));
+}
+
+/*
+ * Return a map from an IJavaElement (this type or a child of this type) to a String[] (the categories of this element)
+ */
+public HashMap getCategories() {
+ return this.categories;
+}
/**
* Returns the ISourceType that is the enclosing type for this
@@ -151,18 +167,7 @@
}
return this.superInterfaceNames;
}
-/**
- * @see org.eclipse.jdt.internal.compiler.env.IGenericType#getKind()
- */
-public int getKind() {
- if ((this.flags & IConstants.AccInterface) != 0) {
- if ((this.flags & IConstants.AccAnnotation) != 0)
- return IGenericType.ANNOTATION_TYPE_DECL;
- return IGenericType.INTERFACE_DECL;
- }
- if ((this.flags & IConstants.AccEnum) != 0) return IGenericType.ENUM_DECL;
- return IGenericType.CLASS_DECL;
-}
+
/**
* @see ISourceType
*/
@@ -274,6 +279,12 @@
public boolean isBinaryType() {
return false;
}
+/*
+ * Returns whether the source type is an anonymous type of a member type.
+ */
+public boolean isAnonymousMember() {
+ return false;
+}
/**
* Sets the handle for this type info
*/
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/TypeParameter.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/TypeParameter.java
index a3361a6..2fac008 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/TypeParameter.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/TypeParameter.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004 IBM Corporation and others.
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,6 +10,9 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core;
+import java.util.HashMap;
+
+import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.*;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.ITypeParameter;
@@ -32,6 +35,16 @@
return super.equals(o);
}
+ /*
+ * @see JavaElement#generateInfos
+ */
+ protected void generateInfos(Object info, HashMap newElements, IProgressMonitor pm) throws JavaModelException {
+ Openable openableParent = (Openable)getOpenableParent();
+ if (JavaModelManager.getJavaModelManager().getInfo(openableParent) == null) {
+ openableParent.generateInfos(openableParent.createElementInfo(), newElements, pm);
+ }
+ }
+
public String[] getBounds() throws JavaModelException {
TypeParameterElementInfo info = (TypeParameterElementInfo) getElementInfo();
return CharOperation.toStrings(info.bounds);
@@ -54,6 +67,15 @@
}
public ISourceRange getNameRange() throws JavaModelException {
+ SourceMapper mapper= getSourceMapper();
+ if (mapper != null) {
+ // ensure the class file's buffer is open so that source ranges are computed
+ ClassFile classFile = (ClassFile)getClassFile();
+ if (classFile != null) {
+ classFile.getBuffer();
+ return mapper.getNameRange(this);
+ }
+ }
TypeParameterElementInfo info = (TypeParameterElementInfo) getElementInfo();
return new SourceRange(info.nameStart, info.nameEnd - info.nameStart + 1);
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/TypeParameterElementInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/TypeParameterElementInfo.java
index 75b0422..28affc4 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/TypeParameterElementInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/TypeParameterElementInfo.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004 IBM Corporation and others.
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/TypeVector.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/TypeVector.java
index a4d86f2..2db65db 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/TypeVector.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/TypeVector.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/UserLibrary.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/UserLibrary.java
index 14c3a78..bf43bf3 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/UserLibrary.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/UserLibrary.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -19,6 +19,8 @@
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
+
+import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IAccessRule;
@@ -96,18 +98,18 @@
return hashCode;
}
- /* package */ String serialize() throws IOException {
+ public static String serialize(IClasspathEntry[] entries, boolean isSystemLibrary) throws IOException {
ByteArrayOutputStream s = new ByteArrayOutputStream();
OutputStreamWriter writer = new OutputStreamWriter(s, "UTF8"); //$NON-NLS-1$
- XMLWriter xmlWriter = new XMLWriter(writer, null/*use the workspace line delimiter*/);
+ XMLWriter xmlWriter = new XMLWriter(writer, null/*use the workspace line delimiter*/, true/*print XML version*/);
HashMap library = new HashMap();
library.put(TAG_VERSION, String.valueOf(CURRENT_VERSION));
- library.put(TAG_SYSTEMLIBRARY, String.valueOf(this.isSystemLibrary));
+ library.put(TAG_SYSTEMLIBRARY, String.valueOf(isSystemLibrary));
xmlWriter.printTag(TAG_USERLIBRARY, library, true, true, false);
- for (int i = 0; i < this.entries.length; ++i) {
- ClasspathEntry cpEntry = (ClasspathEntry) this.entries[i];
+ for (int i = 0, length = entries.length; i < length; ++i) {
+ ClasspathEntry cpEntry = (ClasspathEntry) entries[i];
HashMap archive = new HashMap();
archive.put(TAG_PATH, cpEntry.getPath().toString());
@@ -134,16 +136,16 @@
// write archive end tag if necessary
if (hasExtraAttributes || hasRestrictions) {
- xmlWriter.endTag(TAG_ARCHIVE, true);
+ xmlWriter.endTag(TAG_ARCHIVE, true/*insert tab*/, true/*insert new line*/);
}
}
- xmlWriter.endTag(TAG_USERLIBRARY, true);
+ xmlWriter.endTag(TAG_USERLIBRARY, true/*insert tab*/, true/*insert new line*/);
writer.flush();
writer.close();
return s.toString("UTF8");//$NON-NLS-1$
}
- /* package */ static UserLibrary createFromString(Reader reader) throws IOException {
+ public static UserLibrary createFromString(Reader reader) throws IOException {
Element cpElement;
try {
DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
@@ -156,7 +158,7 @@
reader.close();
}
- if (!cpElement.getNodeName().equalsIgnoreCase(TAG_USERLIBRARY)) { //$NON-NLS-1$
+ if (!cpElement.getNodeName().equalsIgnoreCase(TAG_USERLIBRARY)) {
throw new IOException(Messages.file_badFormat);
}
// String version= cpElement.getAttribute(TAG_VERSION);
@@ -177,8 +179,12 @@
String path = element.getAttribute(TAG_PATH);
IPath sourceAttach= element.hasAttribute(TAG_SOURCEATTACHMENT) ? new Path(element.getAttribute(TAG_SOURCEATTACHMENT)) : null;
IPath sourceAttachRoot= element.hasAttribute(TAG_SOURCEATTACHMENTROOT) ? new Path(element.getAttribute(TAG_SOURCEATTACHMENTROOT)) : null;
- IClasspathAttribute[] extraAttributes = ClasspathEntry.decodeExtraAttributes(element);
- IAccessRule[] accessRules = ClasspathEntry.decodeAccessRules(element);
+ NodeList children = element.getElementsByTagName("*"); //$NON-NLS-1$
+ boolean[] foundChildren = new boolean[children.getLength()];
+ NodeList attributeList = ClasspathEntry.getChildAttributes(ClasspathEntry.TAG_ATTRIBUTES, children, foundChildren);
+ IClasspathAttribute[] extraAttributes = ClasspathEntry.decodeExtraAttributes(attributeList);
+ attributeList = ClasspathEntry.getChildAttributes(ClasspathEntry.TAG_ACCESS_RULES, children, foundChildren);
+ IAccessRule[] accessRules = ClasspathEntry.decodeAccessRules(attributeList);
IClasspathEntry entry = JavaCore.newLibraryEntry(new Path(path), sourceAttach, sourceAttachRoot, accessRules, extraAttributes, false/*not exported*/);
res.add(entry);
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/UserLibraryClasspathContainer.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/UserLibraryClasspathContainer.java
index c5e9b89..c02310e 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/UserLibraryClasspathContainer.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/UserLibraryClasspathContainer.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -15,6 +15,7 @@
import org.eclipse.jdt.core.IClasspathContainer;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.internal.core.util.Util;
/**
*
@@ -23,14 +24,10 @@
private String name;
- public UserLibraryClasspathContainer(String libName) {
- this.name= libName;
+ public UserLibraryClasspathContainer(String name) {
+ this.name = name;
}
- private UserLibrary getUserLibrary() {
- return UserLibraryManager.getUserLibrary(this.name);
- }
-
/* (non-Javadoc)
* @see org.eclipse.jdt.core.IClasspathContainer#getClasspathEntries()
*/
@@ -40,7 +37,6 @@
return library.getEntries();
}
return new IClasspathEntry[0];
-
}
/* (non-Javadoc)
@@ -67,4 +63,18 @@
public IPath getPath() {
return new Path(JavaCore.USER_LIBRARY_CONTAINER_ID).append(this.name);
}
+
+ private UserLibrary getUserLibrary() {
+ UserLibrary userLibrary = JavaModelManager.getUserLibraryManager().getUserLibrary(this.name);
+ if (userLibrary == null && JavaModelManager.CP_RESOLVE_VERBOSE) {
+ verbose_no_user_library_found(this.name);
+ }
+ return userLibrary;
+ }
+
+ private void verbose_no_user_library_found(String userLibraryName) {
+ Util.verbose(
+ "UserLibrary INIT - FAILED (no user library found)\n" + //$NON-NLS-1$
+ " userLibraryName: " + userLibraryName); //$NON-NLS-1$
+ }
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/UserLibraryClasspathContainerInitializer.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/UserLibraryClasspathContainerInitializer.java
index a516a38..1b02260 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/UserLibraryClasspathContainerInitializer.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/UserLibraryClasspathContainerInitializer.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -16,6 +16,7 @@
import org.eclipse.jdt.core.IClasspathContainer;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.internal.core.util.Util;
/**
*
@@ -23,46 +24,19 @@
public class UserLibraryClasspathContainerInitializer extends ClasspathContainerInitializer {
/* (non-Javadoc)
- * @see org.eclipse.jdt.core.ClasspathContainerInitializer#initialize(org.eclipse.core.runtime.IPath, org.eclipse.jdt.core.IJavaProject)
- */
- public void initialize(IPath containerPath, IJavaProject project) throws CoreException {
- if (isUserLibraryContainer(containerPath)) {
- String userLibName= containerPath.segment(1);
-
- UserLibrary entries= UserLibraryManager.getUserLibrary(userLibName);
- if (entries != null) {
- UserLibraryClasspathContainer container= new UserLibraryClasspathContainer(userLibName);
- JavaCore.setClasspathContainer(containerPath, new IJavaProject[] { project }, new IClasspathContainer[] { container }, null);
- }
- }
- }
-
- private boolean isUserLibraryContainer(IPath path) {
- return path != null && path.segmentCount() == 2 && JavaCore.USER_LIBRARY_CONTAINER_ID.equals(path.segment(0));
- }
-
- /* (non-Javadoc)
* @see org.eclipse.jdt.core.ClasspathContainerInitializer#canUpdateClasspathContainer(org.eclipse.core.runtime.IPath, org.eclipse.jdt.core.IJavaProject)
*/
public boolean canUpdateClasspathContainer(IPath containerPath, IJavaProject project) {
return isUserLibraryContainer(containerPath);
}
- /**
- * @see org.eclipse.jdt.core.ClasspathContainerInitializer#requestClasspathContainerUpdate(org.eclipse.core.runtime.IPath, org.eclipse.jdt.core.IJavaProject, org.eclipse.jdt.core.IClasspathContainer)
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.ClasspathContainerInitializer#getComparisonID(org.eclipse.core.runtime.IPath, org.eclipse.jdt.core.IJavaProject)
*/
- public void requestClasspathContainerUpdate(IPath containerPath, IJavaProject project, IClasspathContainer containerSuggestion) throws CoreException {
- if (isUserLibraryContainer(containerPath)) {
- String name= containerPath.segment(1);
- if (containerSuggestion != null) {
- UserLibrary library= new UserLibrary(containerSuggestion.getClasspathEntries(), containerSuggestion.getKind() == IClasspathContainer.K_SYSTEM);
- UserLibraryManager.setUserLibrary(name, library, null); // should use a real progress monitor
- } else {
- UserLibraryManager.setUserLibrary(name, null, null); // should use a real progress monitor
- }
- }
+ public Object getComparisonID(IPath containerPath, IJavaProject project) {
+ return containerPath;
}
-
+
/**
* @see org.eclipse.jdt.core.ClasspathContainerInitializer#getDescription(org.eclipse.core.runtime.IPath, org.eclipse.jdt.core.IJavaProject)
*/
@@ -73,10 +47,51 @@
return super.getDescription(containerPath, project);
}
- /* (non-Javadoc)
- * @see org.eclipse.jdt.core.ClasspathContainerInitializer#getComparisonID(org.eclipse.core.runtime.IPath, org.eclipse.jdt.core.IJavaProject)
+ public void initialize(IPath containerPath, IJavaProject project) throws CoreException {
+ if (isUserLibraryContainer(containerPath)) {
+ String userLibName = containerPath.segment(1);
+ UserLibrary userLibrary = JavaModelManager.getUserLibraryManager().getUserLibrary(userLibName);
+ if (userLibrary != null) {
+ UserLibraryClasspathContainer container = new UserLibraryClasspathContainer(userLibName);
+ JavaCore.setClasspathContainer(containerPath, new IJavaProject[] { project }, new IClasspathContainer[] { container }, null);
+ } else if (JavaModelManager.CP_RESOLVE_VERBOSE) {
+ verbose_no_user_library_found(project, userLibName);
+ }
+ } else if (JavaModelManager.CP_RESOLVE_VERBOSE) {
+ verbose_not_a_user_library(project, containerPath);
+ }
+ }
+
+ private boolean isUserLibraryContainer(IPath path) {
+ return path != null && path.segmentCount() == 2 && JavaCore.USER_LIBRARY_CONTAINER_ID.equals(path.segment(0));
+ }
+
+ /**
+ * @see org.eclipse.jdt.core.ClasspathContainerInitializer#requestClasspathContainerUpdate(org.eclipse.core.runtime.IPath, org.eclipse.jdt.core.IJavaProject, org.eclipse.jdt.core.IClasspathContainer)
*/
- public Object getComparisonID(IPath containerPath, IJavaProject project) {
- return containerPath;
+ public void requestClasspathContainerUpdate(IPath containerPath, IJavaProject project, IClasspathContainer containerSuggestion) throws CoreException {
+ if (isUserLibraryContainer(containerPath)) {
+ String name = containerPath.segment(1);
+ if (containerSuggestion != null) {
+ JavaModelManager.getUserLibraryManager().setUserLibrary(name, containerSuggestion.getClasspathEntries(), containerSuggestion.getKind() == IClasspathContainer.K_SYSTEM);
+ } else {
+ JavaModelManager.getUserLibraryManager().removeUserLibrary(name);
+ }
+ // update of affected projects was done as a consequence of setUserLibrary() or removeUserLibrary()
+ }
+ }
+
+ private void verbose_no_user_library_found(IJavaProject project, String userLibraryName) {
+ Util.verbose(
+ "UserLibrary INIT - FAILED (no user library found)\n" + //$NON-NLS-1$
+ " project: " + project.getElementName() + '\n' + //$NON-NLS-1$
+ " userLibraryName: " + userLibraryName); //$NON-NLS-1$
+ }
+
+ private void verbose_not_a_user_library(IJavaProject project, IPath containerPath) {
+ Util.verbose(
+ "UserLibrary INIT - FAILED (not a user library)\n" + //$NON-NLS-1$
+ " project: " + project.getElementName() + '\n' + //$NON-NLS-1$
+ " container path: " + containerPath); //$NON-NLS-1$
}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/UserLibraryManager.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/UserLibraryManager.java
index d53df3b..a64ce16 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/UserLibraryManager.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/UserLibraryManager.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -16,13 +16,9 @@
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
-import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
-import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.jdt.core.IClasspathContainer;
import org.eclipse.jdt.core.IClasspathEntry;
@@ -35,226 +31,157 @@
/**
*
*/
-public class UserLibraryManager {
+public class UserLibraryManager implements IEclipsePreferences.IPreferenceChangeListener {
public final static String CP_USERLIBRARY_PREFERENCES_PREFIX = JavaCore.PLUGIN_ID+".userLibrary."; //$NON-NLS-1$
- public final static String CP_ENTRY_IGNORE = "##<cp entry ignore>##"; //$NON-NLS-1$
- private static Map userLibraries;
- private static final boolean logProblems= false;
- private static IEclipsePreferences.IPreferenceChangeListener listener= new IEclipsePreferences.IPreferenceChangeListener() {
+ private Map userLibraries;
- public void preferenceChange(IEclipsePreferences.PreferenceChangeEvent event) {
- String key= event.getKey();
- if (key.startsWith(CP_USERLIBRARY_PREFERENCES_PREFIX)) {
- try {
- recreatePersistedUserLibraryEntry(key, (String) event.getNewValue(), false, true);
- } catch (JavaModelException e) {
- if (logProblems) {
- Util.log(e, "Exception while rebinding user library '"+ key.substring(CP_USERLIBRARY_PREFERENCES_PREFIX.length()) +"'."); //$NON-NLS-1$ //$NON-NLS-2$
- }
-
- }
- }
- }
- };
-
- private UserLibraryManager() {
- // do not instantiate
+ public UserLibraryManager() {
+ initialize();
}
- /**
+ /*
+ * Gets the library for a given name or <code>null</code> if no such library exists.
+ */
+ public synchronized UserLibrary getUserLibrary(String libName) {
+ return (UserLibrary) this.userLibraries.get(libName);
+ }
+
+ /*
* Returns the names of all defined user libraries. The corresponding classpath container path
* is the name appended to the CONTAINER_ID.
- * @return Return an array containing the names of all known user defined.
*/
- public static String[] getUserLibraryNames() {
- Set set= getLibraryMap().keySet();
+ public synchronized String[] getUserLibraryNames() {
+ Set set = this.userLibraries.keySet();
return (String[]) set.toArray(new String[set.size()]);
}
- /**
- * Gets the library for a given name or <code>null</code> if no such library exists.
- * @param name The name of the library
- * @return The library registered for the given name or <code>null</code>.
- */
- public static UserLibrary getUserLibrary(String name) {
- return (UserLibrary) getLibraryMap().get(name);
- }
-
- /**
- * Registers user libraries for given names. If a library for the given name already exists, its value will be updated.
- * This call will also rebind all related classpath container.
- * @param newNames The names to register the libraries for
- * @param newLibs The libraries to register
- * @param monitor A progress monitor used when rebinding the classpath containers
- * @throws JavaModelException
- */
- public static void setUserLibraries(String[] newNames, UserLibrary[] newLibs, IProgressMonitor monitor) throws JavaModelException {
- Assert.isTrue(newNames.length == newLibs.length, "names and libraries should have the same length"); //$NON-NLS-1$
-
- if (monitor == null) {
- monitor= new NullProgressMonitor();
- }
-
- monitor.beginTask("Configure user libraries...", newNames.length); //$NON-NLS-1$
+ private void initialize() {
+ this.userLibraries = new HashMap();
+ IEclipsePreferences instancePreferences = JavaModelManager.getJavaModelManager().getInstancePreferences();
+ String[] propertyNames;
try {
- int last= newNames.length - 1;
- for (int i= 0; i < newLibs.length; i++) {
- internalSetUserLibrary(newNames[i], newLibs[i], i == last, true, new SubProgressMonitor(monitor, 1));
+ propertyNames = instancePreferences.keys();
+ } catch (BackingStoreException e) {
+ Util.log(e, "Exception while initializing user libraries"); //$NON-NLS-1$
+ return;
+ }
+
+ boolean preferencesNeedFlush = false;
+ for (int i = 0, length = propertyNames.length; i < length; i++) {
+ String propertyName = propertyNames[i];
+ if (propertyName.startsWith(CP_USERLIBRARY_PREFERENCES_PREFIX)) {
+ String propertyValue = instancePreferences.get(propertyName, null);
+ if (propertyValue != null) {
+ String libName= propertyName.substring(CP_USERLIBRARY_PREFERENCES_PREFIX.length());
+ StringReader reader = new StringReader(propertyValue);
+ UserLibrary library;
+ try {
+ library = UserLibrary.createFromString(reader);
+ } catch (IOException e) {
+ Util.log(e, "Exception while initializing user library " + libName); //$NON-NLS-1$
+ instancePreferences.remove(propertyName);
+ preferencesNeedFlush = true;
+ continue;
+ }
+ this.userLibraries.put(libName, library);
+ }
}
- } finally {
- monitor.done();
+ }
+ if (preferencesNeedFlush) {
+ try {
+ instancePreferences.flush();
+ } catch (BackingStoreException e) {
+ Util.log(e, "Exception while flusing instance preferences"); //$NON-NLS-1$
+ }
}
}
-
- /**
- * Registers a user library for a given name. If a library for the given name already exists, its value will be updated.
- * This call will also rebind all related classpath container.
- * @param name The name to register the library for
- * @param library The library to register
- * @param monitor A progress monitor used when rebinding the classpath containers
- * @throws JavaModelException
- */
- public static void setUserLibrary(String name, UserLibrary library, IProgressMonitor monitor) throws JavaModelException {
- internalSetUserLibrary(name, library, true, true, monitor);
- }
-
- static Map getLibraryMap() {
- if (userLibraries == null) {
- userLibraries= new HashMap();
- // load variables and containers from preferences into cache
- IEclipsePreferences instancePreferences = JavaModelManager.getJavaModelManager().getInstancePreferences();
- instancePreferences.addPreferenceChangeListener(listener);
- // only get variable from preferences not set to their default
+ public void preferenceChange(IEclipsePreferences.PreferenceChangeEvent event) {
+ String key = event.getKey();
+ if (key.startsWith(CP_USERLIBRARY_PREFERENCES_PREFIX)) {
+ String libName = key.substring(CP_USERLIBRARY_PREFERENCES_PREFIX.length());
try {
- String[] propertyNames = instancePreferences.keys();
- for (int i = 0; i < propertyNames.length; i++) {
- String propertyName = propertyNames[i];
- if (propertyName.startsWith(CP_USERLIBRARY_PREFERENCES_PREFIX)) {
- try {
- String propertyValue = instancePreferences.get(propertyName, null);
- if (propertyValue != null)
- recreatePersistedUserLibraryEntry(propertyName,propertyValue, false, false);
- } catch (JavaModelException e) {
- // won't happen: no rebinding
+ // find affected projects
+ IPath containerPath = new Path(JavaCore.USER_LIBRARY_CONTAINER_ID).append(libName);
+ IJavaProject[] allJavaProjects = JavaCore.create(ResourcesPlugin.getWorkspace().getRoot()).getJavaProjects();
+ ArrayList affectedProjects = new ArrayList();
+ for (int i= 0; i < allJavaProjects.length; i++) {
+ IJavaProject javaProject = allJavaProjects[i];
+ IClasspathEntry[] entries= javaProject.getRawClasspath();
+ for (int j= 0; j < entries.length; j++) {
+ IClasspathEntry entry = entries[j];
+ if (entry.getEntryKind() == IClasspathEntry.CPE_CONTAINER) {
+ if (containerPath.equals(entry.getPath())) {
+ affectedProjects.add(javaProject);
+ break;
+ }
}
}
}
- } catch (BackingStoreException e) {
- // nothing to do in this case
+
+ // decode user library
+ String encodedUserLibrary = (String) event.getNewValue();
+ UserLibrary userLibrary = encodedUserLibrary == null ? null : UserLibrary.createFromString(new StringReader(encodedUserLibrary));
+
+ // update user libraries map
+ if (userLibrary != null) {
+ this.userLibraries.put(libName, userLibrary);
+ } else {
+ this.userLibraries.remove(libName);
+ }
+
+ // update affected projects
+ int length = affectedProjects.size();
+ if (length == 0)
+ return;
+ IJavaProject[] projects = new IJavaProject[length];
+ affectedProjects.toArray(projects);
+ IClasspathContainer[] containers = new IClasspathContainer[length];
+ if (userLibrary != null) {
+ UserLibraryClasspathContainer container = new UserLibraryClasspathContainer(libName);
+ for (int i = 0; i < length; i++) {
+ containers[i] = container;
+ }
+ }
+ JavaCore.setClasspathContainer(containerPath, projects, containers, null);
+ } catch (IOException e) {
+ Util.log(e, "Exception while decoding user library '"+ libName +"'."); //$NON-NLS-1$ //$NON-NLS-2$
+ } catch (JavaModelException e) {
+ Util.log(e, "Exception while setting user library '"+ libName +"'."); //$NON-NLS-1$ //$NON-NLS-2$
}
}
- return userLibraries;
}
- static void recreatePersistedUserLibraryEntry(String propertyName, String savedString, boolean save, boolean rebind) throws JavaModelException {
- String libName= propertyName.substring(CP_USERLIBRARY_PREFERENCES_PREFIX.length());
- if (savedString == null || savedString.equals(CP_ENTRY_IGNORE)) {
- internalSetUserLibrary(libName, null, save, rebind, null);
- } else {
- try {
- StringReader reader = new StringReader(savedString);
- UserLibrary library= UserLibrary.createFromString(reader);
- internalSetUserLibrary(libName, library, save, rebind, null);
- } catch (IOException e) {
- if (logProblems) {
- Util.log(e, "Exception while retrieving user library '"+ propertyName +"', library will be removed."); //$NON-NLS-1$ //$NON-NLS-2$
- }
- internalSetUserLibrary(libName, null, save, rebind, null);
- }
- }
- }
-
-
-
- static void internalSetUserLibrary(String name, UserLibrary library, boolean save, boolean rebind, IProgressMonitor monitor) throws JavaModelException {
- if (library == null) {
- Object previous= getLibraryMap().remove(name);
- if (previous == null) {
- return; // no change
- }
- } else {
- Object previous= getLibraryMap().put(name, library);
- if (library.equals(previous)) {
- return; // no change
- }
- }
-
+ public synchronized void removeUserLibrary(String libName) {
IEclipsePreferences instancePreferences = JavaModelManager.getJavaModelManager().getInstancePreferences();
- String containerKey = CP_USERLIBRARY_PREFERENCES_PREFIX+name;
- String containerString = CP_ENTRY_IGNORE;
- if (library != null) {
- try {
- containerString= library.serialize();
- } catch (IOException e) {
- // could not encode entry: leave it as CP_ENTRY_IGNORE
- }
- }
- instancePreferences.removePreferenceChangeListener(listener);
+ String propertyName = CP_USERLIBRARY_PREFERENCES_PREFIX+libName;
+ instancePreferences.remove(propertyName);
try {
- instancePreferences.put(containerKey, containerString);
- if (save) {
- try {
- instancePreferences.flush();
- } catch (BackingStoreException e) {
- // nothing to do in this case
- }
- }
- if (rebind) {
- rebindClasspathEntries(name, library==null, monitor);
- }
-
- } finally {
- instancePreferences.addPreferenceChangeListener(listener);
+ instancePreferences.flush();
+ } catch (BackingStoreException e) {
+ Util.log(e, "Exception while removing user library " + libName); //$NON-NLS-1$
}
+ // this.userLibraries was updated during the PreferenceChangeEvent (see preferenceChange(...))
}
-
- private static void rebindClasspathEntries(String name, boolean remove, IProgressMonitor monitor) throws JavaModelException {
- IWorkspaceRoot root= ResourcesPlugin.getWorkspace().getRoot();
- IJavaProject[] projects= JavaCore.create(root).getJavaProjects();
- IPath containerPath= new Path(JavaCore.USER_LIBRARY_CONTAINER_ID).append(name);
-
- ArrayList affectedProjects= new ArrayList();
-
- for (int i= 0; i < projects.length; i++) {
- IJavaProject project= projects[i];
- IClasspathEntry[] entries= project.getRawClasspath();
- for (int k= 0; k < entries.length; k++) {
- IClasspathEntry curr= entries[k];
- if (curr.getEntryKind() == IClasspathEntry.CPE_CONTAINER) {
- if (containerPath.equals(curr.getPath())) {
- affectedProjects.add(project);
- break;
- }
- }
- }
+
+ public synchronized void setUserLibrary(String libName, IClasspathEntry[] entries, boolean isSystemLibrary) {
+ IEclipsePreferences instancePreferences = JavaModelManager.getJavaModelManager().getInstancePreferences();
+ String propertyName = CP_USERLIBRARY_PREFERENCES_PREFIX+libName;
+ try {
+ String propertyValue = UserLibrary.serialize(entries, isSystemLibrary);
+ instancePreferences.put(propertyName, propertyValue); // sends out a PreferenceChangeEvent (see preferenceChange(...))
+ } catch (IOException e) {
+ Util.log(e, "Exception while serializing user library " + libName); //$NON-NLS-1$
+ return;
}
- if (!affectedProjects.isEmpty()) {
- IJavaProject[] affected= (IJavaProject[]) affectedProjects.toArray(new IJavaProject[affectedProjects.size()]);
- IClasspathContainer[] containers= new IClasspathContainer[affected.length];
- if (!remove) {
- // Previously, containers array only contained a null value. Then, user library classpath entry was first removed
- // and then added a while after when post change delta event on .classpath file was fired...
- // Unfortunately, in some cases, this event was fired a little bit too late and missed the refresh of Package Explorer
- // (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=61872)
- // So now, instanciate a new user library classpath container instead which allow to refresh its content immediately
- // as there's no classpath entry removal...
- // Note that it works because equals(Object) method is not overridden for UserLibraryClasspathContainer.
- // If it was, the update wouldn't happen while setting classpath container
- // @see javaCore.setClasspathContainer(IPath, IJavaProject[], IClasspathContainer[], IProgressMonitor)
- UserLibraryClasspathContainer container= new UserLibraryClasspathContainer(name);
- containers[0] = container;
- }
- JavaCore.setClasspathContainer(containerPath, affected, containers, monitor);
- } else {
- if (monitor != null) {
- monitor.done();
- }
+ try {
+ instancePreferences.flush();
+ } catch (BackingStoreException e) {
+ Util.log(e, "Exception while saving user library " + libName); //$NON-NLS-1$
}
+ // this.userLibraries was updated during the PreferenceChangeEvent (see preferenceChange(...))
}
-
-
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/VerboseElementCache.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/VerboseElementCache.java
new file mode 100755
index 0000000..374ce2b
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/VerboseElementCache.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core;
+
+import java.text.NumberFormat;
+import java.util.Date;
+
+public class VerboseElementCache extends ElementCache {
+
+ private Object beingAdded;
+ private String name;
+
+ public VerboseElementCache(int size, String name) {
+ super(size);
+ this.name = name;
+ }
+
+ protected boolean makeSpace(int space) {
+ if (this.beingAdded == null) return super.makeSpace(space);
+ String fillingRatio = toStringFillingRation(this.name);
+ boolean result = super.makeSpace(space);
+ String newFillingRatio = toStringFillingRation(this.name);
+ if (!fillingRatio.equals(newFillingRatio)) {
+ System.out.println(Thread.currentThread() + " " + new Date(System.currentTimeMillis()).toString()); //$NON-NLS-1$
+ System.out.println(Thread.currentThread() + " MADE SPACE FOR " + fillingRatio + " (NOW " + NumberFormat.getInstance().format(fillingRatio()) + "% full)"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ System.out.println(Thread.currentThread() + " WHILE OPENING "+ ((JavaElement) this.beingAdded).toStringWithAncestors()); //$NON-NLS-1$
+ System.out.println();
+ }
+ return result;
+ }
+
+ public Object put(Object key, Object value) {
+ try {
+ if (this.beingAdded == null)
+ this.beingAdded = key;
+ return super.put(key, value);
+ } finally {
+ if (key.equals(this.beingAdded))
+ this.beingAdded = null;
+ }
+ }
+
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/XMLWriter.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/XMLWriter.java
index 7fad140..cc41dd8 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/XMLWriter.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/XMLWriter.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -9,102 +9,17 @@
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.core;
-import java.io.PrintWriter;
import java.io.Writer;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.internal.compiler.util.GenericXMLWriter;
import org.eclipse.jdt.internal.core.util.Util;
/**
* @since 3.0
*/
-class XMLWriter extends PrintWriter {
- /* constants */
- private static final String XML_VERSION= "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; //$NON-NLS-1$
- private static void appendEscapedChar(StringBuffer buffer, char c) {
- String replacement= getReplacement(c);
- if (replacement != null) {
- buffer.append('&');
- buffer.append(replacement);
- buffer.append(';');
- } else {
- buffer.append(c);
- }
- }
- private static String getEscaped(String s) {
- StringBuffer result= new StringBuffer(s.length() + 10);
- for (int i= 0; i < s.length(); ++i)
- appendEscapedChar(result, s.charAt(i));
- return result.toString();
- }
- private static String getReplacement(char c) {
- // Encode special XML characters into the equivalent character references.
- // These five are defined by default for all XML documents.
- switch (c) {
- case '<' :
- return "lt"; //$NON-NLS-1$
- case '>' :
- return "gt"; //$NON-NLS-1$
- case '"' :
- return "quot"; //$NON-NLS-1$
- case '\'' :
- return "apos"; //$NON-NLS-1$
- case '&' :
- return "amp"; //$NON-NLS-1$
- }
- return null;
- }
- private int tab;
- private String lineSeparator;
- public XMLWriter(Writer writer, IJavaProject project) {
- super(writer);
- this.tab= 0;
- this.lineSeparator = Util.getLineSeparator((String) null, project);
- print(XML_VERSION);
- print(this.lineSeparator);
- }
- public void endTag(String name, boolean insertTab) {
- this.tab --;
- printTag('/' + name, null/*no parameters*/, insertTab, true/*insert new line*/, false/*don't close tag*/);
- }
- private void printTabulation() {
- for (int i= 0; i < tab; i++)
- super.print('\t');
- }
- public void printTag(String name, HashMap parameters, boolean insertTab, boolean insertNewLine, boolean closeTag) {
- StringBuffer sb= new StringBuffer();
- sb.append("<"); //$NON-NLS-1$
- sb.append(name);
- if (parameters != null) {
- for (Enumeration en = Collections.enumeration(parameters.keySet()); en.hasMoreElements();) {
- sb.append(" "); //$NON-NLS-1$
- String key= (String) en.nextElement();
- sb.append(key);
- sb.append("=\""); //$NON-NLS-1$
- sb.append(getEscaped(String.valueOf(parameters.get(key))));
- sb.append("\""); //$NON-NLS-1$
- }
- }
- if (closeTag) {
- sb.append("/>"); //$NON-NLS-1$
- } else {
- sb.append(">"); //$NON-NLS-1$
- }
- if (insertTab) {
- printTabulation();
- }
- print(sb.toString());
- if (insertNewLine) {
- print(this.lineSeparator);
- }
- if (parameters != null && !closeTag)
- this.tab++;
+class XMLWriter extends GenericXMLWriter {
- }
- public void startTag(String name, boolean insertTab) {
- printTag(name, null/*no parameters*/, insertTab, true/*insert new line*/, false/*don't close tag*/);
- this.tab++;
+ public XMLWriter(Writer writer, IJavaProject project, boolean printXmlVersion) {
+ super(writer, Util.getLineSeparator((String) null, project), printXmlVersion);
}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/AbortIncrementalBuildException.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/AbortIncrementalBuildException.java
index 7d11742..2f314c8 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/AbortIncrementalBuildException.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/AbortIncrementalBuildException.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java
index b253f44..3a88ee5 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -15,13 +15,15 @@
import org.eclipse.jdt.core.*;
import org.eclipse.jdt.core.compiler.*;
-import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.internal.compiler.*;
-import org.eclipse.jdt.internal.compiler.ClassFile;
import org.eclipse.jdt.internal.compiler.Compiler;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.problem.*;
+import org.eclipse.jdt.internal.compiler.util.SimpleSet;
import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
+import org.eclipse.jdt.internal.core.JavaModelManager;
import org.eclipse.jdt.internal.core.util.Messages;
import org.eclipse.jdt.internal.core.util.Util;
@@ -33,7 +35,7 @@
* Provides the building and compilation mechanism
* in common with the batch and incremental builders.
*/
-public abstract class AbstractImageBuilder implements ICompilerRequestor {
+public abstract class AbstractImageBuilder implements ICompilerRequestor, ICompilationUnitLocator {
protected JavaBuilder javaBuilder;
protected State newState;
@@ -50,15 +52,20 @@
private boolean inCompiler;
-public static int MAX_AT_ONCE = 1000;
+protected boolean keepStoringProblemMarkers;
+protected SimpleSet filesWithAnnotations = null;
+
+public static int MAX_AT_ONCE = 2000; // best compromise between space used and speed
public final static String[] JAVA_PROBLEM_MARKER_ATTRIBUTE_NAMES = {
- IMarker.MESSAGE,
- IMarker.SEVERITY,
- IJavaModelMarker.ID,
- IMarker.CHAR_START,
- IMarker.CHAR_END,
- IMarker.LINE_NUMBER,
- IJavaModelMarker.ARGUMENTS};
+ IMarker.MESSAGE,
+ IMarker.SEVERITY,
+ IJavaModelMarker.ID,
+ IMarker.CHAR_START,
+ IMarker.CHAR_END,
+ IMarker.LINE_NUMBER,
+ IJavaModelMarker.ARGUMENTS,
+ IJavaModelMarker.CATEGORY_ID,
+};
public final static String[] JAVA_TASK_MARKER_ATTRIBUTE_NAMES = {
IMarker.MESSAGE,
IMarker.PRIORITY,
@@ -66,25 +73,41 @@
IMarker.CHAR_START,
IMarker.CHAR_END,
IMarker.LINE_NUMBER,
- IJavaModelMarker.ARGUMENTS};
+ IMarker.USER_EDITABLE,
+ IMarker.SOURCE_ID,
+};
public final static Integer S_ERROR = new Integer(IMarker.SEVERITY_ERROR);
public final static Integer S_WARNING = new Integer(IMarker.SEVERITY_WARNING);
public final static Integer P_HIGH = new Integer(IMarker.PRIORITY_HIGH);
public final static Integer P_NORMAL = new Integer(IMarker.PRIORITY_NORMAL);
public final static Integer P_LOW = new Integer(IMarker.PRIORITY_LOW);
-protected AbstractImageBuilder(JavaBuilder javaBuilder) {
- this.javaBuilder = javaBuilder;
- this.newState = new State(javaBuilder);
-
+protected AbstractImageBuilder(JavaBuilder javaBuilder, boolean buildStarting, State newState) {
// local copies
+ this.javaBuilder = javaBuilder;
this.nameEnvironment = javaBuilder.nameEnvironment;
this.sourceLocations = this.nameEnvironment.sourceLocations;
this.notifier = javaBuilder.notifier;
+ this.keepStoringProblemMarkers = true; // may get disabled when missing classfiles are encountered
- this.compiler = newCompiler();
- this.workQueue = new WorkQueue();
- this.problemSourceFiles = new ArrayList(3);
+ if (buildStarting) {
+ this.newState = newState == null ? new State(javaBuilder) : newState;
+ this.compiler = newCompiler();
+ this.workQueue = new WorkQueue();
+ this.problemSourceFiles = new ArrayList(3);
+
+ if (this.javaBuilder.participants != null) {
+ for (int i = 0, l = this.javaBuilder.participants.length; i < l; i++) {
+ if (this.javaBuilder.participants[i].isAnnotationProcessor()) {
+ // initialize this set so the builder knows to gather CUs that define Annotation types
+ // each Annotation processor participant is then asked to process these files AFTER
+ // the compile loop. The normal dependency loop will then recompile all affected types
+ this.filesWithAnnotations = new SimpleSet(1);
+ break;
+ }
+ }
+ }
+ }
}
public void acceptResult(CompilationResult result) {
@@ -137,17 +160,18 @@
if (duplicateTypeNames == null)
duplicateTypeNames = new ArrayList();
duplicateTypeNames.add(compoundName);
- if (mainType == null)
+ if (mainType == null) {
try {
mainTypeName = compilationUnit.initialTypeName; // slash separated qualified name "p1/p1/A"
mainType = javaBuilder.javaProject.findType(mainTypeName.replace('/', '.'));
} catch (JavaModelException e) {
// ignore
}
+ }
IType type;
- if (qualifiedTypeName.equals(mainTypeName))
+ if (qualifiedTypeName.equals(mainTypeName)) {
type = mainType;
- else {
+ } else {
String simpleName = qualifiedTypeName.substring(qualifiedTypeName.lastIndexOf('/')+1);
type = mainType == null ? null : mainType.getCompilationUnit().getType(simpleName);
}
@@ -155,6 +179,8 @@
continue;
}
newState.recordLocatorForType(qualifiedTypeName, typeLocator);
+ if (!qualifiedTypeName.equals(compilationUnit.initialTypeName))
+ acceptSecondaryType(classFile);
}
try {
definedTypeNames.add(writeClassFile(classFile, compilationUnit, !isNestedType));
@@ -166,11 +192,75 @@
createProblemFor(compilationUnit.resource, null, Messages.build_inconsistentClassFile, JavaCore.ERROR);
}
}
+ if (result.hasAnnotations && this.filesWithAnnotations != null) // only initialized if an annotation processor is attached
+ this.filesWithAnnotations.add(compilationUnit);
+
finishedWith(typeLocator, result, compilationUnit.getMainTypeName(), definedTypeNames, duplicateTypeNames);
notifier.compiled(compilationUnit);
}
}
+protected void acceptSecondaryType(ClassFile classFile) {
+ // noop
+}
+
+protected void addAllSourceFiles(final ArrayList sourceFiles) throws CoreException {
+ for (int i = 0, l = sourceLocations.length; i < l; i++) {
+ final ClasspathMultiDirectory sourceLocation = sourceLocations[i];
+ final char[][] exclusionPatterns = sourceLocation.exclusionPatterns;
+ final char[][] inclusionPatterns = sourceLocation.inclusionPatterns;
+ final boolean isAlsoProject = sourceLocation.sourceFolder.equals(javaBuilder.currentProject);
+ final int segmentCount = sourceLocation.sourceFolder.getFullPath().segmentCount();
+ final IContainer outputFolder = sourceLocation.binaryFolder;
+ final boolean isOutputFolder = sourceLocation.sourceFolder.equals(outputFolder);
+ sourceLocation.sourceFolder.accept(
+ new IResourceProxyVisitor() {
+ public boolean visit(IResourceProxy proxy) throws CoreException {
+ switch(proxy.getType()) {
+ case IResource.FILE :
+ if (org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(proxy.getName())) {
+ IResource resource = proxy.requestResource();
+ if (exclusionPatterns != null || inclusionPatterns != null)
+ if (Util.isExcluded(resource.getFullPath(), inclusionPatterns, exclusionPatterns, false))
+ return false;
+ sourceFiles.add(new SourceFile((IFile) resource, sourceLocation));
+ }
+ return false;
+ case IResource.FOLDER :
+ IPath folderPath = null;
+ if (isAlsoProject)
+ if (isExcludedFromProject(folderPath = proxy.requestFullPath()))
+ return false;
+ if (exclusionPatterns != null) {
+ if (folderPath == null)
+ folderPath = proxy.requestFullPath();
+ if (Util.isExcluded(folderPath, inclusionPatterns, exclusionPatterns, true)) {
+ // must walk children if inclusionPatterns != null, can skip them if == null
+ // but folder is excluded so do not create it in the output folder
+ return inclusionPatterns != null;
+ }
+ }
+ if (!isOutputFolder) {
+ if (folderPath == null)
+ folderPath = proxy.requestFullPath();
+ String packageName = folderPath.lastSegment();
+ if (packageName.length() > 0) {
+ String sourceLevel = javaBuilder.javaProject.getOption(JavaCore.COMPILER_SOURCE, true);
+ String complianceLevel = javaBuilder.javaProject.getOption(JavaCore.COMPILER_COMPLIANCE, true);
+ if (JavaConventions.validatePackageName(packageName, sourceLevel, complianceLevel).getSeverity() != IStatus.ERROR)
+ createFolder(folderPath.removeFirstSegments(segmentCount), outputFolder);
+ }
+ }
+ }
+ return true;
+ }
+ },
+ IResource.NONE
+ );
+ notifier.checkCancel();
+ }
+}
+
protected void cleanUp() {
this.nameEnvironment.cleanup();
@@ -187,43 +277,67 @@
* if they are affected by the changes.
*/
protected void compile(SourceFile[] units) {
- int unitsLength = units.length;
+ if (this.filesWithAnnotations != null && this.filesWithAnnotations.elementSize > 0)
+ // will add files that have annotations in acceptResult() & then processAnnotations() before exitting this method
+ this.filesWithAnnotations.clear();
+ // notify CompilationParticipants which source files are about to be compiled
+ BuildContext[] participantResults = this.javaBuilder.participants == null ? null : notifyParticipants(units);
+ if (participantResults != null && participantResults.length > units.length) {
+ units = new SourceFile[participantResults.length];
+ for (int i = participantResults.length; --i >= 0;)
+ units[i] = participantResults[i].sourceFile;
+ }
+
+ int unitsLength = units.length;
this.compiledAllAtOnce = unitsLength <= MAX_AT_ONCE;
if (this.compiledAllAtOnce) {
// do them all now
if (JavaBuilder.DEBUG)
for (int i = 0; i < unitsLength; i++)
System.out.println("About to compile " + units[i].typeLocator()); //$NON-NLS-1$
- compile(units, null);
+ compile(units, null, true);
} else {
- int i = 0;
+ SourceFile[] remainingUnits = new SourceFile[unitsLength]; // copy of units, removing units when about to compile
+ System.arraycopy(units, 0, remainingUnits, 0, unitsLength);
+ int doNow = unitsLength < MAX_AT_ONCE ? unitsLength : MAX_AT_ONCE;
+ SourceFile[] toCompile = new SourceFile[doNow];
+ int remainingIndex = 0;
boolean compilingFirstGroup = true;
- while (i < unitsLength) {
- int doNow = unitsLength < MAX_AT_ONCE ? unitsLength : MAX_AT_ONCE;
- int index = 0;
- SourceFile[] toCompile = new SourceFile[doNow];
- while (i < unitsLength && index < doNow) {
+ while (remainingIndex < unitsLength) {
+ int count = 0;
+ while (remainingIndex < unitsLength && count < doNow) {
// Although it needed compiling when this method was called, it may have
// already been compiled when it was referenced by another unit.
- SourceFile unit = units[i++];
- if (compilingFirstGroup || workQueue.isWaiting(unit)) {
+ SourceFile unit = remainingUnits[remainingIndex];
+ if (unit != null && (compilingFirstGroup || this.workQueue.isWaiting(unit))) {
if (JavaBuilder.DEBUG)
- System.out.println("About to compile " + unit.typeLocator()); //$NON-NLS-1$
- toCompile[index++] = unit;
+ System.out.println("About to compile #" + remainingIndex + " : "+ unit.typeLocator()); //$NON-NLS-1$ //$NON-NLS-2$
+ toCompile[count++] = unit;
}
+ remainingUnits[remainingIndex++] = null;
}
- if (index < doNow)
- System.arraycopy(toCompile, 0, toCompile = new SourceFile[index], 0, index);
- SourceFile[] additionalUnits = new SourceFile[unitsLength - i];
- System.arraycopy(units, i, additionalUnits, 0, additionalUnits.length);
+ if (count < doNow)
+ System.arraycopy(toCompile, 0, toCompile = new SourceFile[count], 0, count);
+ if (!compilingFirstGroup)
+ for (int a = remainingIndex; a < unitsLength; a++)
+ if (remainingUnits[a] != null && this.workQueue.isCompiled(remainingUnits[a]))
+ remainingUnits[a] = null; // use the class file for this source file since its been compiled
+ compile(toCompile, remainingUnits, compilingFirstGroup);
compilingFirstGroup = false;
- compile(toCompile, additionalUnits);
}
}
+
+ if (participantResults != null) {
+ for (int i = participantResults.length; --i >= 0;)
+ if (participantResults[i] != null)
+ recordParticipantResult(participantResults[i]);
+
+ processAnnotations(participantResults);
+ }
}
-void compile(SourceFile[] units, SourceFile[] additionalUnits) {
+protected void compile(SourceFile[] units, SourceFile[] additionalUnits, boolean compilingFirstGroup) {
if (units.length == 0) return;
notifier.aboutToCompile(units[0]); // just to change the message
@@ -266,13 +380,37 @@
int start = range == null ? 0 : range.getOffset();
int end = range == null ? 1 : start + range.getLength();
marker.setAttributes(
- new String[] {IMarker.MESSAGE, IMarker.SEVERITY, IMarker.CHAR_START, IMarker.CHAR_END},
- new Object[] {message, new Integer(severity), new Integer(start), new Integer(end)});
+ new String[] {IMarker.MESSAGE, IMarker.SEVERITY, IMarker.CHAR_START, IMarker.CHAR_END, IMarker.SOURCE_ID},
+ new Object[] {message, new Integer(severity), new Integer(start), new Integer(end), JavaBuilder.SOURCE_ID});
} catch (CoreException e) {
throw internalException(e);
}
}
+protected void deleteGeneratedFiles(IFile[] deletedGeneratedFiles) {
+ // no op by default
+}
+
+protected SourceFile findSourceFile(IFile file, boolean mustExist) {
+ if (mustExist && !file.exists()) return null;
+
+ // assumes the file exists in at least one of the source folders & is not excluded
+ ClasspathMultiDirectory md = sourceLocations[0];
+ if (sourceLocations.length > 1) {
+ IPath sourceFileFullPath = file.getFullPath();
+ for (int j = 0, m = sourceLocations.length; j < m; j++) {
+ if (sourceLocations[j].sourceFolder.getFullPath().isPrefixOf(sourceFileFullPath)) {
+ md = sourceLocations[j];
+ if (md.exclusionPatterns == null && md.inclusionPatterns == null)
+ break;
+ if (!Util.isExcluded(file, md.inclusionPatterns, md.exclusionPatterns))
+ break;
+ }
+ }
+ }
+ return new SourceFile(file, md);
+}
+
protected void finishedWith(String sourceLocator, CompilationResult result, char[] mainTypeName, ArrayList definedTypeNames, ArrayList duplicateTypeNames) {
if (duplicateTypeNames == null) {
newState.record(sourceLocator, result.qualifiedReferences, result.simpleNameReferences, mainTypeName, definedTypeNames);
@@ -300,12 +438,30 @@
IFolder folder = outputFolder.getFolder(packagePath);
if (!folder.exists()) {
createFolder(packagePath.removeLastSegments(1), outputFolder);
- folder.create(true, true, null);
- folder.setDerived(true);
+ folder.create(IResource.FORCE | IResource.DERIVED, true, null);
}
return folder;
}
+
+
+/* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.core.builder.ICompilationUnitLocator#fromIFile(org.eclipse.core.resources.IFile)
+ */
+public ICompilationUnit fromIFile(IFile file) {
+ return findSourceFile(file, true);
+}
+
+protected void initializeAnnotationProcessorManager(Compiler newCompiler) {
+ AbstractAnnotationProcessorManager annotationManager = JavaModelManager.getJavaModelManager().createAnnotationProcessorManager();
+ if (annotationManager != null) {
+ annotationManager.configureFromPlatform(newCompiler, this, javaBuilder.javaProject);
+ annotationManager.setErr(new PrintWriter(System.err));
+ annotationManager.setOut(new PrintWriter(System.out));
+ }
+ newCompiler.annotationProcessorManager = annotationManager;
+}
+
protected RuntimeException internalException(CoreException t) {
ImageBuilderInternalException imageBuilderException = new ImageBuilderInternalException(t);
if (inCompiler)
@@ -313,6 +469,18 @@
return imageBuilderException;
}
+protected boolean isExcludedFromProject(IPath childPath) throws JavaModelException {
+ // answer whether the folder should be ignored when walking the project as a source folder
+ if (childPath.segmentCount() > 2) return false; // is a subfolder of a package
+
+ for (int j = 0, k = sourceLocations.length; j < k; j++) {
+ if (childPath.equals(sourceLocations[j].binaryFolder.getFullPath())) return true;
+ if (childPath.equals(sourceLocations[j].sourceFolder.getFullPath())) return true;
+ }
+ // skip default output folder which may not be used by any source folder
+ return childPath.equals(javaBuilder.javaProject.getOutputLocation());
+}
+
protected Compiler newCompiler() {
// disable entire javadoc support if not interested in diagnostics
Map projectOptions = javaBuilder.javaProject.getOptions(true);
@@ -331,38 +499,126 @@
}
// called once when the builder is initialized... can override if needed
+ CompilerOptions compilerOptions = new CompilerOptions(projectOptions);
+ compilerOptions.performMethodsFullRecovery = true;
+ compilerOptions.performStatementsRecovery = true;
Compiler newCompiler = new Compiler(
nameEnvironment,
DefaultErrorHandlingPolicies.proceedWithAllProblems(),
- projectOptions,
+ compilerOptions,
this,
ProblemFactory.getProblemFactory(Locale.getDefault()));
CompilerOptions options = newCompiler.options;
-
+
// enable the compiler reference info support
options.produceReferenceInfo = true;
-
- org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment env = newCompiler.lookupEnvironment;
- synchronized (env) {
- // enable shared byte[]'s used by ClassFile to avoid allocating MBs during a build
- env.sharedArraysUsed = false;
- env.sharedClassFileHeader = new byte[30000];
- env.sharedClassFileContents = new byte[30000];
- }
+ if (options.complianceLevel >= ClassFileConstants.JDK1_6
+ && options.processAnnotations) {
+ // support for Java 6 annotation processors
+ initializeAnnotationProcessorManager(newCompiler);
+ }
+
return newCompiler;
}
-protected boolean isExcludedFromProject(IPath childPath) throws JavaModelException {
- // answer whether the folder should be ignored when walking the project as a source folder
- if (childPath.segmentCount() > 2) return false; // is a subfolder of a package
+protected BuildContext[] notifyParticipants(SourceFile[] unitsAboutToCompile) {
+ BuildContext[] results = new BuildContext[unitsAboutToCompile.length];
+ for (int i = unitsAboutToCompile.length; --i >= 0;)
+ results[i] = new BuildContext(unitsAboutToCompile[i]);
- for (int j = 0, k = sourceLocations.length; j < k; j++) {
- if (childPath.equals(sourceLocations[j].binaryFolder.getFullPath())) return true;
- if (childPath.equals(sourceLocations[j].sourceFolder.getFullPath())) return true;
+ // TODO (kent) do we expect to have more than one participant?
+ // and if so should we pass the generated files from the each processor to the others to process?
+ // and what happens if some participants do not expect to be called with only a few files, after seeing 'all' the files?
+ for (int i = 0, l = this.javaBuilder.participants.length; i < l; i++)
+ this.javaBuilder.participants[i].buildStarting(results, this instanceof BatchImageBuilder);
+
+ SimpleSet uniqueFiles = null;
+ CompilationParticipantResult[] toAdd = null;
+ int added = 0;
+ for (int i = results.length; --i >= 0;) {
+ CompilationParticipantResult result = results[i];
+ if (result == null) continue;
+
+ IFile[] deletedGeneratedFiles = result.deletedFiles;
+ if (deletedGeneratedFiles != null)
+ deleteGeneratedFiles(deletedGeneratedFiles);
+
+ IFile[] addedGeneratedFiles = result.addedFiles;
+ if (addedGeneratedFiles != null) {
+ for (int j = addedGeneratedFiles.length; --j >= 0;) {
+ SourceFile sourceFile = findSourceFile(addedGeneratedFiles[j], true);
+ if (sourceFile == null) continue;
+ if (uniqueFiles == null) {
+ uniqueFiles = new SimpleSet(unitsAboutToCompile.length + 3);
+ for (int f = unitsAboutToCompile.length; --f >= 0;)
+ uniqueFiles.add(unitsAboutToCompile[f]);
+ }
+ if (uniqueFiles.addIfNotIncluded(sourceFile) == sourceFile) {
+ CompilationParticipantResult newResult = new BuildContext(sourceFile);
+ // is there enough room to add all the addedGeneratedFiles.length ?
+ if (toAdd == null) {
+ toAdd = new CompilationParticipantResult[addedGeneratedFiles.length];
+ } else {
+ int length = toAdd.length;
+ if (added == length)
+ System.arraycopy(toAdd, 0, toAdd = new CompilationParticipantResult[length + addedGeneratedFiles.length], 0, length);
+ }
+ toAdd[added++] = newResult;
+ }
+ }
+ }
}
- // skip default output folder which may not be used by any source folder
- return childPath.equals(javaBuilder.javaProject.getOutputLocation());
+
+ if (added >0 ) {
+ int length = results.length;
+ System.arraycopy(results, 0, results = new BuildContext[length + added], 0 , length);
+ System.arraycopy(toAdd, 0, results, length, added);
+ }
+ return results;
+}
+
+protected abstract void processAnnotationResults(CompilationParticipantResult[] results);
+
+protected void processAnnotations(BuildContext[] results) {
+ boolean hasAnnotationProcessor = false;
+ for (int i = 0, l = this.javaBuilder.participants.length; !hasAnnotationProcessor && i < l; i++)
+ hasAnnotationProcessor = this.javaBuilder.participants[i].isAnnotationProcessor();
+ if (!hasAnnotationProcessor) return;
+
+ boolean foundAnnotations = this.filesWithAnnotations != null && this.filesWithAnnotations.elementSize > 0;
+ for (int i = results.length; --i >= 0;)
+ ((CompilationParticipantResult) results[i]).reset(foundAnnotations && this.filesWithAnnotations.includes(results[i].sourceFile));
+
+ // even if no files have annotations, must still tell every annotation processor in case the file used to have them
+ for (int i = 0, l = this.javaBuilder.participants.length; i < l; i++)
+ if (this.javaBuilder.participants[i].isAnnotationProcessor())
+ this.javaBuilder.participants[i].processAnnotations(results);
+ processAnnotationResults(results);
+}
+
+protected void recordParticipantResult(CompilationParticipantResult result) {
+ // any added/changed/deleted generated files have already been taken care
+ // just record the problems and dependencies - do not expect there to be many
+ // must be called after we're finished with the compilation unit results but before incremental loop adds affected files
+ CategorizedProblem[] problems = result.problems;
+ if (problems != null && problems.length > 0) {
+ // existing problems have already been removed so just add these as new problems
+ this.notifier.updateProblemCounts(problems);
+ try {
+ storeProblemsFor(result.sourceFile, problems);
+ } catch (CoreException e) {
+ // must continue with compile loop so just log the CoreException
+ e.printStackTrace();
+ }
+ }
+
+ String[] dependencies = result.dependencies;
+ if (dependencies != null) {
+ ReferenceCollection refs = (ReferenceCollection) this.newState.references.get(result.sourceFile.typeLocator());
+ if (refs != null)
+ refs.addDependencies(dependencies);
+ }
}
/**
@@ -374,65 +630,98 @@
* - its priority reflects the severity of the problem
* - its range is the problem's range
* - it has an extra attribute "ID" which holds the problem's id
+ * - it's GENERATED_BY attribute is positioned to JavaBuilder.GENERATED_BY if
+ * the problem was generated by JDT; else the GENERATED_BY attribute is
+ * carried from the problem to the marker in extra attributes, if present.
*/
-protected void storeProblemsFor(SourceFile sourceFile, IProblem[] problems) throws CoreException {
+protected void storeProblemsFor(SourceFile sourceFile, CategorizedProblem[] problems) throws CoreException {
if (sourceFile == null || problems == null || problems.length == 0) return;
+ // once a classpath error is found, ignore all other problems for this project so the user can see the main error
+ // but still try to compile as many source files as possible to help the case when the base libraries are in source
+ if (!this.keepStoringProblemMarkers) return; // only want the one error recorded on this source file
- String missingClassFile = null;
IResource resource = sourceFile.resource;
+ HashSet managedMarkerTypes = JavaModelManager.getJavaModelManager().compilationParticipants.managedMarkerTypes();
for (int i = 0, l = problems.length; i < l; i++) {
- IProblem problem = problems[i];
+ CategorizedProblem problem = problems[i];
int id = problem.getID();
+
+ // handle missing classfile situation
if (id == IProblem.IsClassPathCorrect) {
- JavaBuilder.removeProblemsAndTasksFor(javaBuilder.currentProject); // make this the only problem for this project
- String[] args = problem.getArguments();
- missingClassFile = args[0];
- }
-
- if (id != IProblem.Task) {
- IMarker marker = resource.createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER);
+ String missingClassfileName = problem.getArguments()[0];
+ if (JavaBuilder.DEBUG)
+ System.out.println(Messages.bind(Messages.build_incompleteClassPath, missingClassfileName));
+ boolean isInvalidClasspathError = JavaCore.ERROR.equals(javaBuilder.javaProject.getOption(JavaCore.CORE_INCOMPLETE_CLASSPATH, true));
+ // insert extra classpath problem, and make it the only problem for this project (optional)
+ if (isInvalidClasspathError && JavaCore.ABORT.equals(javaBuilder.javaProject.getOption(JavaCore.CORE_JAVA_BUILD_INVALID_CLASSPATH, true))) {
+ JavaBuilder.removeProblemsAndTasksFor(javaBuilder.currentProject); // make this the only problem for this project
+ this.keepStoringProblemMarkers = false;
+ }
+ IMarker marker = this.javaBuilder.currentProject.createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER);
marker.setAttributes(
- JAVA_PROBLEM_MARKER_ATTRIBUTE_NAMES,
- new Object[] {
- problem.getMessage(),
- problem.isError() ? S_ERROR : S_WARNING,
- new Integer(id),
- new Integer(problem.getSourceStart()),
- new Integer(problem.getSourceEnd() + 1),
- new Integer(problem.getSourceLineNumber()),
- Util.getProblemArgumentsForMarker(problem.getArguments())
- });
+ new String[] {IMarker.MESSAGE, IMarker.SEVERITY, IJavaModelMarker.CATEGORY_ID, IMarker.SOURCE_ID},
+ new Object[] {
+ Messages.bind(Messages.build_incompleteClassPath, missingClassfileName),
+ new Integer(isInvalidClasspathError ? IMarker.SEVERITY_ERROR : IMarker.SEVERITY_WARNING),
+ new Integer(CategorizedProblem.CAT_BUILDPATH),
+ JavaBuilder.SOURCE_ID
+ }
+ );
+ // even if we're not keeping more markers, still fall through rest of the problem reporting, so that offending
+ // IsClassPathCorrect problem gets recorded since it may help locate the offending reference
}
-/* Do NOT want to populate the Java Model just to find the matching Java element.
- * Also cannot query compilation units located in folders with invalid package
- * names such as 'a/b.c.d/e'.
+ String markerType = problem.getMarkerType();
+ boolean managedProblem = false;
+ if (IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER.equals(markerType)
+ || (managedProblem = managedMarkerTypes.contains(markerType))) {
+ IMarker marker = resource.createMarker(markerType);
- // compute a user-friendly location
- IJavaElement element = JavaCore.create(resource);
- if (element instanceof org.eclipse.jdt.core.ICompilationUnit) { // try to find a finer grain element
- org.eclipse.jdt.core.ICompilationUnit unit = (org.eclipse.jdt.core.ICompilationUnit) element;
- IJavaElement fragment = unit.getElementAt(problem.getSourceStart());
- if (fragment != null) element = fragment;
+ String[] attributeNames = JAVA_PROBLEM_MARKER_ATTRIBUTE_NAMES;
+ int standardLength = attributeNames.length;
+ String[] allNames = attributeNames;
+ int managedLength = managedProblem ? 0 : 1;
+ String[] extraAttributeNames = problem.getExtraMarkerAttributeNames();
+ int extraLength = extraAttributeNames == null ? 0 : extraAttributeNames.length;
+ if (managedLength > 0 || extraLength > 0) {
+ allNames = new String[standardLength + managedLength + extraLength];
+ System.arraycopy(attributeNames, 0, allNames, 0, standardLength);
+ if (managedLength > 0)
+ allNames[standardLength] = IMarker.SOURCE_ID;
+ System.arraycopy(extraAttributeNames, 0, allNames, standardLength + managedLength, extraLength);
+ }
+
+ Object[] allValues = new Object[allNames.length];
+ // standard attributes
+ int index = 0;
+ allValues[index++] = problem.getMessage(); // message
+ allValues[index++] = problem.isError() ? S_ERROR : S_WARNING; // severity
+ allValues[index++] = new Integer(id); // ID
+ allValues[index++] = new Integer(problem.getSourceStart()); // start
+ allValues[index++] = new Integer(problem.getSourceEnd() + 1); // end
+ allValues[index++] = new Integer(problem.getSourceLineNumber()); // line
+ allValues[index++] = Util.getProblemArgumentsForMarker(problem.getArguments()); // arguments
+ allValues[index++] = new Integer(problem.getCategoryID()); // category ID
+ // GENERATED_BY attribute for JDT problems
+ if (managedLength > 0)
+ allValues[index++] = JavaBuilder.SOURCE_ID;
+ // optional extra attributes
+ if (extraLength > 0)
+ System.arraycopy(problem.getExtraMarkerAttributeValues(), 0, allValues, index, extraLength);
+
+ marker.setAttributes(allNames, allValues);
+
+ if (!this.keepStoringProblemMarkers) return; // only want the one error recorded on this source file
}
- String location = null;
- if (element instanceof JavaElement)
- location = ((JavaElement) element).readableName();
- if (location != null)
- marker.setAttribute(IMarker.LOCATION, location);
-*/
-
- if (missingClassFile != null)
- throw new MissingClassFileException(missingClassFile);
}
}
-protected void storeTasksFor(SourceFile sourceFile, IProblem[] tasks) throws CoreException {
+protected void storeTasksFor(SourceFile sourceFile, CategorizedProblem[] tasks) throws CoreException {
if (sourceFile == null || tasks == null || tasks.length == 0) return;
IResource resource = sourceFile.resource;
for (int i = 0, l = tasks.length; i < l; i++) {
- IProblem task = tasks[i];
+ CategorizedProblem task = tasks[i];
if (task.getID() == IProblem.Task) {
IMarker marker = resource.createMarker(IJavaModelMarker.TASK_MARKER);
Integer priority = P_NORMAL;
@@ -441,23 +730,40 @@
priority = P_HIGH;
else if (JavaCore.COMPILER_TASK_PRIORITY_LOW.equals(compilerPriority))
priority = P_LOW;
- marker.setAttributes(
- JAVA_TASK_MARKER_ATTRIBUTE_NAMES,
- new Object[] {
- task.getMessage(),
- priority,
- new Integer(task.getID()),
- new Integer(task.getSourceStart()),
- new Integer(task.getSourceEnd() + 1),
- new Integer(task.getSourceLineNumber()),
- Boolean.FALSE,
- });
+
+ String[] attributeNames = JAVA_TASK_MARKER_ATTRIBUTE_NAMES;
+ int standardLength = attributeNames.length;
+ String[] allNames = attributeNames;
+ String[] extraAttributeNames = task.getExtraMarkerAttributeNames();
+ int extraLength = extraAttributeNames == null ? 0 : extraAttributeNames.length;
+ if (extraLength > 0) {
+ allNames = new String[standardLength + extraLength];
+ System.arraycopy(attributeNames, 0, allNames, 0, standardLength);
+ System.arraycopy(extraAttributeNames, 0, allNames, standardLength, extraLength);
+ }
+
+ Object[] allValues = new Object[allNames.length];
+ // standard attributes
+ int index = 0;
+ allValues[index++] = task.getMessage();
+ allValues[index++] = priority;
+ allValues[index++] = new Integer(task.getID());
+ allValues[index++] = new Integer(task.getSourceStart());
+ allValues[index++] = new Integer(task.getSourceEnd() + 1);
+ allValues[index++] = new Integer(task.getSourceLineNumber());
+ allValues[index++] = Boolean.FALSE;
+ allValues[index++] = JavaBuilder.SOURCE_ID;
+ // optional extra attributes
+ if (extraLength > 0)
+ System.arraycopy(task.getExtraMarkerAttributeValues(), 0, allValues, index, extraLength);
+
+ marker.setAttributes(allNames, allValues);
}
}
}
protected void updateProblemsFor(SourceFile sourceFile, CompilationResult result) throws CoreException {
- IProblem[] problems = result.getProblems();
+ CategorizedProblem[] problems = result.getProblems();
if (problems == null || problems.length == 0) return;
notifier.updateProblemCounts(problems);
@@ -465,13 +771,13 @@
}
protected void updateTasksFor(SourceFile sourceFile, CompilationResult result) throws CoreException {
- IProblem[] tasks = result.getTasks();
+ CategorizedProblem[] tasks = result.getTasks();
if (tasks == null || tasks.length == 0) return;
storeTasksFor(sourceFile, tasks);
}
-protected char[] writeClassFile(ClassFile classFile, SourceFile compilationUnit, boolean isSecondaryType) throws CoreException {
+protected char[] writeClassFile(ClassFile classFile, SourceFile compilationUnit, boolean isTopLevelType) throws CoreException {
String fileName = new String(classFile.fileName()); // the qualified type name "p1/p2/A"
IPath filePath = new Path(fileName);
IContainer outputFolder = compilationUnit.sourceLocation.binaryFolder;
@@ -482,32 +788,27 @@
}
IFile file = container.getFile(filePath.addFileExtension(SuffixConstants.EXTENSION_class));
- writeClassFileBytes(classFile.getBytes(), file, fileName, isSecondaryType, compilationUnit.updateClassFile);
- if (classFile.ownSharedArrays) {
- org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment env = this.compiler.lookupEnvironment;
- synchronized (env) {
- env.sharedArraysUsed = false;
- }
+ writeClassFileBytes(classFile.getBytes(), file, fileName, isTopLevelType, compilationUnit);
+ if (classFile.isShared) {
+ this.compiler.lookupEnvironment.classFilePool.release(classFile);
}
-
// answer the name of the class file as in Y or Y$M
return filePath.lastSegment().toCharArray();
}
-protected void writeClassFileBytes(byte[] bytes, IFile file, String qualifiedFileName, boolean isSecondaryType, boolean updateClassFile) throws CoreException {
+protected void writeClassFileBytes(byte[] bytes, IFile file, String qualifiedFileName, boolean isTopLevelType, SourceFile compilationUnit) throws CoreException {
if (file.exists()) {
// Deal with shared output folders... last one wins... no collision cases detected
if (JavaBuilder.DEBUG)
System.out.println("Writing changed class file " + file.getName());//$NON-NLS-1$
- file.setContents(new ByteArrayInputStream(bytes), true, false, null);
if (!file.isDerived())
file.setDerived(true);
+ file.setContents(new ByteArrayInputStream(bytes), true, false, null);
} else {
// Default implementation just writes out the bytes for the new class file...
if (JavaBuilder.DEBUG)
System.out.println("Writing new class file " + file.getName());//$NON-NLS-1$
- file.create(new ByteArrayInputStream(bytes), IResource.FORCE, null);
- file.setDerived(true);
+ file.create(new ByteArrayInputStream(bytes), IResource.FORCE | IResource.DERIVED, null);
}
}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/AdditionalTypeCollection.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/AdditionalTypeCollection.java
index 6adf478..2597273 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/AdditionalTypeCollection.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/AdditionalTypeCollection.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/BatchImageBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/BatchImageBuilder.java
index 046b1fb..0615520 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/BatchImageBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/BatchImageBuilder.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -14,6 +14,8 @@
import org.eclipse.core.runtime.*;
import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.compiler.*;
+import org.eclipse.jdt.internal.compiler.ClassFile;
import org.eclipse.jdt.internal.core.util.Messages;
import org.eclipse.jdt.internal.core.util.Util;
@@ -21,9 +23,16 @@
public class BatchImageBuilder extends AbstractImageBuilder {
-protected BatchImageBuilder(JavaBuilder javaBuilder) {
- super(javaBuilder);
+ IncrementalImageBuilder incrementalBuilder; // if annotations or secondary types have to be processed after the compile loop
+ ArrayList secondaryTypes; // qualified names for all secondary types found during batch compile
+ StringSet typeLocatorsWithUndefinedTypes; // type locators for all source files with errors that may be caused by 'not found' secondary types
+
+protected BatchImageBuilder(JavaBuilder javaBuilder, boolean buildStarting) {
+ super(javaBuilder, buildStarting, null);
this.nameEnvironment.isIncrementalBuild = false;
+ this.incrementalBuilder = null;
+ this.secondaryTypes = null;
+ this.typeLocatorsWithUndefinedTypes = null;
}
public void build() {
@@ -31,15 +40,15 @@
System.out.println("FULL build"); //$NON-NLS-1$
try {
- notifier.subTask(Messages.build_cleaningOutput);
+ notifier.subTask(Messages.bind(Messages.build_cleaningOutput, this.javaBuilder.currentProject.getName()));
JavaBuilder.removeProblemsAndTasksFor(javaBuilder.currentProject);
cleanOutputFolders(true);
- notifier.updateProgressDelta(0.1f);
+ notifier.updateProgressDelta(0.05f);
notifier.subTask(Messages.build_analyzingSources);
ArrayList sourceFiles = new ArrayList(33);
addAllSourceFiles(sourceFiles);
- notifier.updateProgressDelta(0.15f);
+ notifier.updateProgressDelta(0.10f);
if (sourceFiles.size() > 0) {
SourceFile[] allSourceFiles = new SourceFile[sourceFiles.size()];
@@ -48,6 +57,12 @@
notifier.setProgressPerCompilationUnit(0.75f / allSourceFiles.length);
workQueue.addAll(allSourceFiles);
compile(allSourceFiles);
+
+ if (this.typeLocatorsWithUndefinedTypes != null)
+ if (this.secondaryTypes != null && !this.secondaryTypes.isEmpty())
+ rebuildTypesAffectedBySecondaryTypes();
+ if (this.incrementalBuilder != null)
+ this.incrementalBuilder.buildAfterBatchBuild();
}
if (javaBuilder.javaProject.hasCycleMarker())
@@ -59,52 +74,22 @@
}
}
-protected void addAllSourceFiles(final ArrayList sourceFiles) throws CoreException {
- for (int i = 0, l = sourceLocations.length; i < l; i++) {
- final ClasspathMultiDirectory sourceLocation = sourceLocations[i];
- final char[][] exclusionPatterns = sourceLocation.exclusionPatterns;
- final char[][] inclusionPatterns = sourceLocation.inclusionPatterns;
- final boolean isAlsoProject = sourceLocation.sourceFolder.equals(javaBuilder.currentProject);
- sourceLocation.sourceFolder.accept(
- new IResourceProxyVisitor() {
- public boolean visit(IResourceProxy proxy) throws CoreException {
- IResource resource = null;
- switch(proxy.getType()) {
- case IResource.FILE :
- if (exclusionPatterns != null || inclusionPatterns != null) {
- resource = proxy.requestResource();
- if (Util.isExcluded(resource, inclusionPatterns, exclusionPatterns)) return false;
- }
- if (org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(proxy.getName())) {
- if (resource == null)
- resource = proxy.requestResource();
- sourceFiles.add(new SourceFile((IFile) resource, sourceLocation));
- }
- return false;
- case IResource.FOLDER :
- if (exclusionPatterns != null && inclusionPatterns == null) {
- // if there are inclusion patterns then we must walk the children
- resource = proxy.requestResource();
- if (Util.isExcluded(resource, inclusionPatterns, exclusionPatterns)) return false;
- }
- if (isAlsoProject && isExcludedFromProject(proxy.requestFullPath())) return false;
- }
- return true;
- }
- },
- IResource.NONE
- );
- notifier.checkCancel();
- }
+protected void acceptSecondaryType(ClassFile classFile) {
+ if (this.secondaryTypes != null)
+ this.secondaryTypes.add(classFile.fileName());
}
protected void cleanOutputFolders(boolean copyBack) throws CoreException {
boolean deleteAll = JavaCore.CLEAN.equals(
javaBuilder.javaProject.getOption(JavaCore.CORE_JAVA_BUILD_CLEAN_OUTPUT_FOLDER, true));
if (deleteAll) {
+ if (this.javaBuilder.participants != null)
+ for (int i = 0, l = this.javaBuilder.participants.length; i < l; i++)
+ this.javaBuilder.participants[i].cleanStarting(this.javaBuilder.javaProject);
+
ArrayList visited = new ArrayList(sourceLocations.length);
for (int i = 0, l = sourceLocations.length; i < l; i++) {
- notifier.subTask(Messages.build_cleaningOutput);
+ notifier.subTask(Messages.bind(Messages.build_cleaningOutput, this.javaBuilder.currentProject.getName()));
ClasspathMultiDirectory sourceLocation = sourceLocations[i];
if (sourceLocation.hasIndependentOutputFolder) {
IContainer outputFolder = sourceLocation.binaryFolder;
@@ -142,34 +127,26 @@
sourceLocation.binaryFolder.accept(
new IResourceProxyVisitor() {
public boolean visit(IResourceProxy proxy) throws CoreException {
- IResource resource = null;
if (proxy.getType() == IResource.FILE) {
- if (exclusionPatterns != null || inclusionPatterns != null) {
- resource = proxy.requestResource();
- if (Util.isExcluded(resource, inclusionPatterns, exclusionPatterns)) return false;
- }
if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(proxy.getName())) {
- if (resource == null)
- resource = proxy.requestResource();
+ IResource resource = proxy.requestResource();
+ if (exclusionPatterns != null || inclusionPatterns != null)
+ if (Util.isExcluded(resource.getFullPath(), inclusionPatterns, exclusionPatterns, false))
+ return false;
resource.delete(IResource.FORCE, null);
}
return false;
}
- if (exclusionPatterns != null && inclusionPatterns == null) {
- // if there are inclusion patterns then we must walk the children
- resource = proxy.requestResource();
- if (Util.isExcluded(resource, inclusionPatterns, exclusionPatterns)) return false;
- }
+ if (exclusionPatterns != null && inclusionPatterns == null) // must walk children if inclusionPatterns != null
+ if (Util.isExcluded(proxy.requestFullPath(), null, exclusionPatterns, true))
+ return false;
notifier.checkCancel();
return true;
}
},
IResource.NONE
);
- if (!isOutputFolder && copyBack) {
- notifier.checkCancel();
- copyPackages(sourceLocation);
- }
+ notifier.checkCancel();
}
notifier.checkCancel();
}
@@ -178,13 +155,24 @@
ClasspathMultiDirectory sourceLocation = sourceLocations[i];
if (sourceLocation.hasIndependentOutputFolder)
copyExtraResourcesBack(sourceLocation, false);
- else if (!sourceLocation.sourceFolder.equals(sourceLocation.binaryFolder))
- copyPackages(sourceLocation); // output folder is different from source folder
notifier.checkCancel();
}
}
}
+protected void cleanUp() {
+ this.incrementalBuilder = null;
+ this.secondaryTypes = null;
+ this.typeLocatorsWithUndefinedTypes = null;
+ super.cleanUp();
+}
+
+protected void compile(SourceFile[] units, SourceFile[] additionalUnits, boolean compilingFirstGroup) {
+ if (additionalUnits != null && this.secondaryTypes == null)
+ this.secondaryTypes = new ArrayList(7);
+ super.compile(units, additionalUnits, compilingFirstGroup);
+}
+
protected void copyExtraResourcesBack(ClasspathMultiDirectory sourceLocation, final boolean deletedAll) throws CoreException {
// When, if ever, does a builder need to copy resources files (not .java or .class) into the output folder?
// If we wipe the output folder at the beginning of the build then all 'extra' resources must be copied to the output folder.
@@ -207,7 +195,7 @@
resource = proxy.requestResource();
if (javaBuilder.filterExtraResource(resource)) return false;
if (exclusionPatterns != null || inclusionPatterns != null)
- if (Util.isExcluded(resource, inclusionPatterns, exclusionPatterns))
+ if (Util.isExcluded(resource.getFullPath(), inclusionPatterns, exclusionPatterns, false))
return false;
IPath partialPath = resource.getFullPath().removeFirstSegments(segmentCount);
@@ -225,46 +213,17 @@
}
copiedResource.delete(IResource.FORCE, null); // last one wins
}
- resource.copy(copiedResource.getFullPath(), IResource.FORCE, null);
- copiedResource.setDerived(true);
+ createFolder(partialPath.removeLastSegments(1), outputFolder); // ensure package folder exists
+ resource.copy(copiedResource.getFullPath(), IResource.FORCE | IResource.DERIVED, null);
Util.setReadOnly(copiedResource, false); // just in case the original was read only
return false;
case IResource.FOLDER :
resource = proxy.requestResource();
if (javaBuilder.filterExtraResource(resource)) return false;
- IPath folderPath = resource.getFullPath();
- if (isAlsoProject && isExcludedFromProject(folderPath)) return false; // the sourceFolder == project
- if (exclusionPatterns != null && Util.isExcluded(resource, inclusionPatterns, exclusionPatterns))
- return inclusionPatterns != null; // need to go further only if inclusionPatterns are set
- createFolder(folderPath.removeFirstSegments(segmentCount), outputFolder);
- }
- return true;
- }
- },
- IResource.NONE
- );
-}
-
-protected void copyPackages(ClasspathMultiDirectory sourceLocation) throws CoreException {
- final int segmentCount = sourceLocation.sourceFolder.getFullPath().segmentCount();
- final char[][] exclusionPatterns = sourceLocation.exclusionPatterns;
- final char[][] inclusionPatterns = sourceLocation.inclusionPatterns;
- final IContainer outputFolder = sourceLocation.binaryFolder;
- final boolean isAlsoProject = sourceLocation.sourceFolder.equals(javaBuilder.currentProject);
- sourceLocation.sourceFolder.accept(
- new IResourceProxyVisitor() {
- public boolean visit(IResourceProxy proxy) throws CoreException {
- switch(proxy.getType()) {
- case IResource.FILE :
- return false;
- case IResource.FOLDER :
- IResource resource = proxy.requestResource();
- if (javaBuilder.filterExtraResource(resource)) return false;
- IPath folderPath = resource.getFullPath();
- if (isAlsoProject && isExcludedFromProject(folderPath)) return false; // the sourceFolder == project
- if (exclusionPatterns != null && Util.isExcluded(resource, inclusionPatterns, exclusionPatterns))
- return inclusionPatterns != null; // need to go further only if inclusionPatterns are set
- createFolder(folderPath.removeFirstSegments(segmentCount), outputFolder);
+ if (isAlsoProject && isExcludedFromProject(resource.getFullPath())) return false; // the sourceFolder == project
+ if (exclusionPatterns != null && inclusionPatterns == null) // must walk children if inclusionPatterns != null
+ if (Util.isExcluded(resource.getFullPath(), null, exclusionPatterns, true))
+ return false;
}
return true;
}
@@ -284,6 +243,48 @@
return null;
}
+protected void processAnnotationResults(CompilationParticipantResult[] results) {
+ // to compile the compilation participant results, we need to incrementally recompile all affected types
+ // whenever the generated types are initially added or structurally changed
+ if (this.incrementalBuilder == null)
+ this.incrementalBuilder = new IncrementalImageBuilder(this);
+ this.incrementalBuilder.processAnnotationResults(results);
+}
+
+protected void rebuildTypesAffectedBySecondaryTypes() {
+ // to compile types that could not find 'missing' secondary types because of multiple
+ // compile groups, we need to incrementally recompile all affected types as if the missing
+ // secondary types have just been added, see bug 146324
+ if (this.incrementalBuilder == null)
+ this.incrementalBuilder = new IncrementalImageBuilder(this);
+
+ for (int i = this.secondaryTypes.size(); --i >=0;) {
+ char[] secondaryTypeName = (char[]) this.secondaryTypes.get(i);
+ IPath path = new Path(null, new String(secondaryTypeName));
+ this.incrementalBuilder.addDependentsOf(path, false);
+ }
+ this.incrementalBuilder.addAffectedSourceFiles(
+ this.incrementalBuilder.qualifiedStrings,
+ this.incrementalBuilder.simpleStrings,
+ this.typeLocatorsWithUndefinedTypes);
+}
+
+protected void storeProblemsFor(SourceFile sourceFile, CategorizedProblem[] problems) throws CoreException {
+ if (sourceFile == null || problems == null || problems.length == 0) return;
+
+ for (int i = problems.length; --i >= 0;) {
+ CategorizedProblem problem = problems[i];
+ if (problem != null && problem.getID() == IProblem.UndefinedType) {
+ if (this.typeLocatorsWithUndefinedTypes == null)
+ this.typeLocatorsWithUndefinedTypes = new StringSet(3);
+ this.typeLocatorsWithUndefinedTypes.add(sourceFile.typeLocator());
+ break;
+ }
+ }
+
+ super.storeProblemsFor(sourceFile, problems);
+}
+
public String toString() {
return "batch image builder for:\n\tnew state: " + newState; //$NON-NLS-1$
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/BuildNotifier.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/BuildNotifier.java
index 8d661fb..dbe17bc 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/BuildNotifier.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/BuildNotifier.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -13,6 +13,7 @@
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
+import org.eclipse.jdt.core.compiler.CategorizedProblem;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
import org.eclipse.jdt.internal.core.util.Messages;
@@ -203,7 +204,7 @@
this.previousSubtask = msg;
}
-protected void updateProblemCounts(IProblem[] newProblems) {
+protected void updateProblemCounts(CategorizedProblem[] newProblems) {
for (int i = 0, l = newProblems.length; i < l; i++)
if (newProblems[i].isError()) newErrorCount++; else newWarningCount++;
}
@@ -212,10 +213,10 @@
* Update the problem counts from one compilation result given the old and new problems,
* either of which may be null.
*/
-protected void updateProblemCounts(IMarker[] oldProblems, IProblem[] newProblems) {
+protected void updateProblemCounts(IMarker[] oldProblems, CategorizedProblem[] newProblems) {
if (newProblems != null) {
next : for (int i = 0, l = newProblems.length; i < l; i++) {
- IProblem newProblem = newProblems[i];
+ CategorizedProblem newProblem = newProblems[i];
if (newProblem.getID() == IProblem.Task) continue; // skip task
boolean isError = newProblem.isError();
String message = newProblem.getMessage();
@@ -245,7 +246,7 @@
if (newProblems != null) {
for (int j = 0, m = newProblems.length; j < m; j++) {
- IProblem pb = newProblems[j];
+ CategorizedProblem pb = newProblems[j];
if (pb.getID() == IProblem.Task) continue; // skip task
if (wasError == pb.isError() && message.equals(pb.getMessage()))
continue next;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathDirectory.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathDirectory.java
index 24d54a9..724fd0b 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathDirectory.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathDirectory.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,20 +10,23 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core.builder;
+import java.io.IOException;
+
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
+import org.eclipse.jdt.internal.core.util.Util;
public class ClasspathDirectory extends ClasspathLocation {
IContainer binaryFolder; // includes .class files for a single directory
boolean isOutputFolder;
-String binaryLocation;
SimpleLookupTable directoryCache;
String[] missingPackageHolder = new String[1];
AccessRuleSet accessRuleSet;
@@ -31,8 +34,6 @@
ClasspathDirectory(IContainer binaryFolder, boolean isOutputFolder, AccessRuleSet accessRuleSet) {
this.binaryFolder = binaryFolder;
this.isOutputFolder = isOutputFolder;
- IPath location = binaryFolder.getLocation();
- this.binaryLocation = location != null ? location.addTrailingSeparator().toString() : ""; //$NON-NLS-1$
this.directoryCache = new SimpleLookupTable(5);
this.accessRuleSet = accessRuleSet;
}
@@ -48,7 +49,7 @@
try {
IResource container = binaryFolder.findMember(qualifiedPackageName); // this is a case-sensitive check
- if (container instanceof IContainer && !isExcluded(container)) {
+ if (container instanceof IContainer) {
IResource[] members = ((IContainer) container).members();
dirList = new String[members.length];
int index = 0;
@@ -94,34 +95,21 @@
public NameEnvironmentAnswer findClass(String binaryFileName, String qualifiedPackageName, String qualifiedBinaryFileName) {
if (!doesFileExist(binaryFileName, qualifiedPackageName, qualifiedBinaryFileName)) return null; // most common case
+ ClassFileReader reader = null;
try {
- ClassFileReader reader = ClassFileReader.read(binaryLocation + qualifiedBinaryFileName);
- if (reader != null) {
- if (this.accessRuleSet == null)
- return new NameEnvironmentAnswer(reader, null);
- String fileNameWithoutExtension = qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length() - SuffixConstants.SUFFIX_CLASS.length);
- return new NameEnvironmentAnswer(reader, this.accessRuleSet.getViolatedRestriction(fileNameWithoutExtension.toCharArray()));
- }
- } catch (Exception e) {
- // handle the case when the project is the output folder and the top-level package is a linked folder
- if (binaryFolder instanceof IProject) {
- IResource file = binaryFolder.findMember(qualifiedBinaryFileName);
- if (file instanceof IFile) {
- IPath location = file.getLocation();
- if (location != null) {
- try {
- ClassFileReader reader = ClassFileReader.read(location.toString());
- if (reader != null) {
- if (this.accessRuleSet == null)
- return new NameEnvironmentAnswer(reader, null);
- String fileNameWithoutExtension = qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length() - SuffixConstants.SUFFIX_CLASS.length);
- return new NameEnvironmentAnswer(reader, this.accessRuleSet.getViolatedRestriction(fileNameWithoutExtension.toCharArray()));
- }
- } catch (Exception ignored) { // treat as if class file is missing
- }
- }
- }
- }
+ reader = Util.newClassFileReader(this.binaryFolder.getFile(new Path(qualifiedBinaryFileName)));
+ } catch (CoreException e) {
+ return null;
+ } catch (ClassFormatException e) {
+ return null;
+ } catch (IOException e) {
+ return null;
+ }
+ if (reader != null) {
+ if (this.accessRuleSet == null)
+ return new NameEnvironmentAnswer(reader, null);
+ String fileNameWithoutExtension = qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length() - SuffixConstants.SUFFIX_CLASS.length);
+ return new NameEnvironmentAnswer(reader, this.accessRuleSet.getViolatedRestriction(fileNameWithoutExtension.toCharArray()));
}
return null;
}
@@ -154,7 +142,7 @@
}
public String debugPathString() {
- return this.binaryLocation;
+ return this.binaryFolder.getFullPath().toString();
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java
index 45bcc8c..000a090 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -18,8 +18,9 @@
import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
+import org.eclipse.jdt.internal.compiler.util.SimpleSet;
import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
-import org.eclipse.jdt.internal.core.util.SimpleSet;
+import org.eclipse.jdt.internal.core.util.Util;
import java.io.*;
import java.util.*;
@@ -64,9 +65,8 @@
while (last > 0) {
// extract the package name
String packageName = fileName.substring(0, last);
- if (packageSet.includes(packageName))
- continue nextEntry;
- packageSet.add(packageName);
+ if (packageSet.addIfNotIncluded(packageName) == null)
+ continue nextEntry; // already existed
last = packageName.lastIndexOf('/');
}
}
@@ -86,8 +86,17 @@
ClasspathJar(IFile resource, AccessRuleSet accessRuleSet) {
this.resource = resource;
- IPath location = resource.getLocation();
- this.zipFilename = location != null ? location.toString() : ""; //$NON-NLS-1$
+ try {
+ java.net.URI location = resource.getLocationURI();
+ if (location == null) {
+ this.zipFilename = ""; //$NON-NLS-1$
+ } else {
+ File localFile = Util.toLocalFile(location, null);
+ this.zipFilename = localFile.getPath();
+ }
+ } catch (CoreException e) {
+ // ignore
+ }
this.zipFile = null;
this.knownPackageNames = null;
this.accessRuleSet = accessRuleSet;
@@ -185,9 +194,10 @@
}
public String debugPathString() {
- if (this.lastModified == 0)
+ long time = lastModified();
+ if (time == 0)
return this.zipFilename;
- return this.zipFilename + '(' + (new Date(this.lastModified)) + " : " + this.lastModified + ')'; //$NON-NLS-1$
+ return this.zipFilename + '(' + (new Date(time)) + " : " + time + ')'; //$NON-NLS-1$
}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java
index d7cb036..89d1d67 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/CompilationParticipantResult.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/CompilationParticipantResult.java
new file mode 100755
index 0000000..1a71574
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/CompilationParticipantResult.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM - rewrote spec
+ *
+ *******************************************************************************/
+
+package org.eclipse.jdt.internal.core.builder;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jdt.core.compiler.*;
+
+public class CompilationParticipantResult {
+ protected SourceFile sourceFile;
+ protected boolean hasAnnotations; // only set during processAnnotations
+ protected IFile[] addedFiles; // added/changed generated source files that need to be compiled
+ protected IFile[] deletedFiles; // previously generated source files that should be deleted
+ protected CategorizedProblem[] problems; // new problems to report against this compilationUnit
+ protected String[] dependencies; // fully-qualified type names of any new dependencies, each name is of the form 'p1.p2.A.B'
+
+protected CompilationParticipantResult(SourceFile sourceFile) {
+ this.sourceFile = sourceFile;
+ this.hasAnnotations = false;
+ this.addedFiles = null;
+ this.deletedFiles = null;
+ this.problems = null;
+ this.dependencies = null;
+}
+
+void reset(boolean detectedAnnotations) {
+ // called prior to processAnnotations
+ this.hasAnnotations = detectedAnnotations;
+ this.addedFiles = null;
+ this.deletedFiles = null;
+ this.problems = null;
+ this.dependencies = null;
+}
+
+public String toString() {
+ return this.sourceFile.toString();
+}
+
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ICompilationUnitLocator.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ICompilationUnitLocator.java
new file mode 100755
index 0000000..c3cdb56
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ICompilationUnitLocator.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2007 BEA Systems, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * wharley@bea.com - initial API and implementation
+ *
+ *******************************************************************************/
+
+package org.eclipse.jdt.internal.core.builder;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
+
+/**
+ * Used to convert an IFile into an ICompilationUnit,
+ * for clients outside of this package.
+ * @since 3.3
+ */
+public interface ICompilationUnitLocator {
+ public ICompilationUnit fromIFile(IFile file);
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ImageBuilderInternalException.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ImageBuilderInternalException.java
index 959f439..555539c 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ImageBuilderInternalException.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ImageBuilderInternalException.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/IncrementalImageBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/IncrementalImageBuilder.java
index 653bb23..1981876 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/IncrementalImageBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/IncrementalImageBuilder.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -13,8 +13,8 @@
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
+import org.eclipse.jdt.core.*;
import org.eclipse.jdt.core.compiler.*;
-import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.internal.compiler.*;
import org.eclipse.jdt.internal.compiler.classfmt.*;
import org.eclipse.jdt.internal.compiler.problem.*;
@@ -24,6 +24,7 @@
import org.eclipse.jdt.internal.core.util.Util;
import java.io.*;
+import java.net.URI;
import java.util.*;
/**
@@ -38,20 +39,25 @@
protected SimpleLookupTable secondaryTypesToRemove;
protected boolean hasStructuralChanges;
protected int compileLoop;
+protected boolean makeOutputFolderConsistent;
public static int MaxCompileLoop = 5; // perform a full build if it takes more than ? incremental compile loops
-protected IncrementalImageBuilder(JavaBuilder javaBuilder) {
- super(javaBuilder);
+protected IncrementalImageBuilder(JavaBuilder javaBuilder, State buildState) {
+ super(javaBuilder, true, buildState);
this.nameEnvironment.isIncrementalBuild = true;
- this.newState.copyFrom(javaBuilder.lastState);
+ this.makeOutputFolderConsistent = JavaCore.ENABLED.equals(
+ javaBuilder.javaProject.getOption(JavaCore.CORE_JAVA_BUILD_RECREATE_MODIFIED_CLASS_FILES_IN_OUTPUT_FOLDER, true));
+}
- this.sourceFiles = new ArrayList(33);
- this.previousSourceFiles = null;
- this.qualifiedStrings = new StringSet(3);
- this.simpleStrings = new StringSet(3);
- this.hasStructuralChanges = false;
- this.compileLoop = 0;
+protected IncrementalImageBuilder(JavaBuilder javaBuilder) {
+ this(javaBuilder, null);
+ this.newState.copyFrom(javaBuilder.lastState);
+}
+
+protected IncrementalImageBuilder(BatchImageBuilder batchBuilder) {
+ this(batchBuilder.javaBuilder, batchBuilder.newState);
+ resetCollections();
}
public boolean build(SimpleLookupTable deltas) {
@@ -71,28 +77,38 @@
try {
resetCollections();
- notifier.subTask(Messages.build_analyzingDeltas);
- IResourceDelta sourceDelta = (IResourceDelta) deltas.get(javaBuilder.currentProject);
- if (sourceDelta != null)
- if (!findSourceFiles(sourceDelta)) return false;
- notifier.updateProgressDelta(0.10f);
+ notifier.subTask(Messages.build_analyzingDeltas);
+ if (javaBuilder.hasBuildpathErrors()) {
+ // if a mssing class file was detected in the last build, a build state was saved since its no longer fatal
+ // but we need to rebuild every source file since problems were not recorded
+ // AND to avoid the infinite build scenario if this project is involved in a cycle, see bug 160550
+ // we need to avoid unnecessary deltas caused by doing a full build in this case
+ javaBuilder.currentProject.deleteMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, false, IResource.DEPTH_ZERO);
+ addAllSourceFiles(sourceFiles);
+ notifier.updateProgressDelta(0.25f);
+ } else {
+ IResourceDelta sourceDelta = (IResourceDelta) deltas.get(javaBuilder.currentProject);
+ if (sourceDelta != null)
+ if (!findSourceFiles(sourceDelta)) return false;
+ notifier.updateProgressDelta(0.10f);
- Object[] keyTable = deltas.keyTable;
- Object[] valueTable = deltas.valueTable;
- for (int i = 0, l = valueTable.length; i < l; i++) {
- IResourceDelta delta = (IResourceDelta) valueTable[i];
- if (delta != null) {
- IProject p = (IProject) keyTable[i];
- ClasspathLocation[] classFoldersAndJars = (ClasspathLocation[]) javaBuilder.binaryLocationsPerProject.get(p);
- if (classFoldersAndJars != null)
- if (!findAffectedSourceFiles(delta, classFoldersAndJars, p)) return false;
+ Object[] keyTable = deltas.keyTable;
+ Object[] valueTable = deltas.valueTable;
+ for (int i = 0, l = valueTable.length; i < l; i++) {
+ IResourceDelta delta = (IResourceDelta) valueTable[i];
+ if (delta != null) {
+ IProject p = (IProject) keyTable[i];
+ ClasspathLocation[] classFoldersAndJars = (ClasspathLocation[]) javaBuilder.binaryLocationsPerProject.get(p);
+ if (classFoldersAndJars != null)
+ if (!findAffectedSourceFiles(delta, classFoldersAndJars, p)) return false;
+ }
}
- }
- notifier.updateProgressDelta(0.10f);
+ notifier.updateProgressDelta(0.10f);
- notifier.subTask(Messages.build_analyzingSources);
- addAffectedSourceFiles();
- notifier.updateProgressDelta(0.05f);
+ notifier.subTask(Messages.build_analyzingSources);
+ addAffectedSourceFiles();
+ notifier.updateProgressDelta(0.05f);
+ }
this.compileLoop = 0;
float increment = 0.40f;
@@ -131,45 +147,66 @@
return true;
}
+protected void buildAfterBatchBuild() {
+ // called from a batch builder once all source files have been compiled AND some changes
+ // need to be propagated incrementally (annotations, missing secondary types)
+
+ if (JavaBuilder.DEBUG)
+ System.out.println("INCREMENTAL build after batch build @ " + new Date(System.currentTimeMillis())); //$NON-NLS-1$
+
+ // this is a copy of the incremental build loop
+ try {
+ addAffectedSourceFiles();
+ while (this.sourceFiles.size() > 0) {
+ notifier.checkCancel();
+ SourceFile[] allSourceFiles = new SourceFile[this.sourceFiles.size()];
+ this.sourceFiles.toArray(allSourceFiles);
+ resetCollections();
+ notifier.setProgressPerCompilationUnit(0.08f / allSourceFiles.length);
+ this.workQueue.addAll(allSourceFiles);
+ compile(allSourceFiles);
+ removeSecondaryTypes();
+ addAffectedSourceFiles();
+ }
+ } catch (CoreException e) {
+ throw internalException(e);
+ } finally {
+ cleanUp();
+ }
+}
+
protected void addAffectedSourceFiles() {
if (qualifiedStrings.elementSize == 0 && simpleStrings.elementSize == 0) return;
+ addAffectedSourceFiles(qualifiedStrings, simpleStrings, null);
+}
+
+protected void addAffectedSourceFiles(StringSet qualifiedSet, StringSet simpleSet, StringSet affectedTypes) {
// the qualifiedStrings are of the form 'p1/p2' & the simpleStrings are just 'X'
- char[][][] qualifiedNames = ReferenceCollection.internQualifiedNames(qualifiedStrings);
+ char[][][] internedQualifiedNames = ReferenceCollection.internQualifiedNames(qualifiedSet);
// if a well known qualified name was found then we can skip over these
- if (qualifiedNames.length < qualifiedStrings.elementSize)
- qualifiedNames = null;
- char[][] simpleNames = ReferenceCollection.internSimpleNames(simpleStrings);
+ if (internedQualifiedNames.length < qualifiedSet.elementSize)
+ internedQualifiedNames = null;
+ char[][] internedSimpleNames = ReferenceCollection.internSimpleNames(simpleSet);
// if a well known name was found then we can skip over these
- if (simpleNames.length < simpleStrings.elementSize)
- simpleNames = null;
+ if (internedSimpleNames.length < simpleSet.elementSize)
+ internedSimpleNames = null;
Object[] keyTable = newState.references.keyTable;
Object[] valueTable = newState.references.valueTable;
next : for (int i = 0, l = valueTable.length; i < l; i++) {
- ReferenceCollection refs = (ReferenceCollection) valueTable[i];
- if (refs != null && refs.includes(qualifiedNames, simpleNames)) {
- String typeLocator = (String) keyTable[i];
- IFile file = javaBuilder.currentProject.getFile(typeLocator);
- if (file.exists()) {
- ClasspathMultiDirectory md = sourceLocations[0];
- if (sourceLocations.length > 1) {
- IPath sourceFileFullPath = file.getFullPath();
- for (int j = 0, m = sourceLocations.length; j < m; j++) {
- if (sourceLocations[j].sourceFolder.getFullPath().isPrefixOf(sourceFileFullPath)) {
- md = sourceLocations[j];
- if (md.exclusionPatterns == null && md.inclusionPatterns == null)
- break;
- if (!Util.isExcluded(file, md.inclusionPatterns, md.exclusionPatterns))
- break;
- }
- }
- }
- SourceFile sourceFile = new SourceFile(file, md);
+ String typeLocator = (String) keyTable[i];
+ if (typeLocator != null) {
+ if (affectedTypes != null && !affectedTypes.includes(typeLocator)) continue next;
+ ReferenceCollection refs = (ReferenceCollection) valueTable[i];
+ if (refs.includes(internedQualifiedNames, internedSimpleNames)) {
+ IFile file = javaBuilder.currentProject.getFile(typeLocator);
+ SourceFile sourceFile = findSourceFile(file, true);
+ if (sourceFile == null) continue next;
if (sourceFiles.contains(sourceFile)) continue next;
if (compiledAllAtOnce && previousSourceFiles != null && previousSourceFiles.contains(sourceFile))
continue next; // can skip previously compiled files since already saw hierarchy related problems
-
+
if (JavaBuilder.DEBUG)
System.out.println(" adding affected source file " + typeLocator); //$NON-NLS-1$
sourceFiles.add(sourceFile);
@@ -196,6 +233,36 @@
+ typeName + " in " + packageName); //$NON-NLS-1$
}
+protected boolean checkForClassFileChanges(IResourceDelta binaryDelta, ClasspathMultiDirectory md, int segmentCount) throws CoreException {
+ IResource resource = binaryDelta.getResource();
+ // remember that if inclusion & exclusion patterns change then a full build is done
+ boolean isExcluded = (md.exclusionPatterns != null || md.inclusionPatterns != null)
+ && Util.isExcluded(resource, md.inclusionPatterns, md.exclusionPatterns);
+ switch(resource.getType()) {
+ case IResource.FOLDER :
+ if (isExcluded && md.inclusionPatterns == null)
+ return true; // no need to go further with this delta since its children cannot be included
+
+ IResourceDelta[] children = binaryDelta.getAffectedChildren();
+ for (int i = 0, l = children.length; i < l; i++)
+ if (!checkForClassFileChanges(children[i], md, segmentCount))
+ return false;
+ return true;
+ case IResource.FILE :
+ if (!isExcluded && org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(resource.getName())) {
+ // perform full build if a managed class file has been changed
+ IPath typePath = resource.getFullPath().removeFirstSegments(segmentCount).removeFileExtension();
+ if (newState.isKnownType(typePath.toString())) {
+ if (JavaBuilder.DEBUG)
+ System.out.println("MUST DO FULL BUILD. Found change to class file " + typePath); //$NON-NLS-1$
+ return false;
+ }
+ return true;
+ }
+ }
+ return true;
+}
+
protected void cleanUp() {
super.cleanUp();
@@ -208,6 +275,64 @@
this.compileLoop = 0;
}
+protected void compile(SourceFile[] units, SourceFile[] additionalUnits, boolean compilingFirstGroup) {
+ if (compilingFirstGroup && additionalUnits != null) {
+ // add any source file from additionalUnits to units if it defines secondary types
+ // otherwise its possible during testing with MAX_AT_ONCE == 1 that a secondary type
+ // can cause an infinite loop as it alternates between not found and defined, see bug 146324
+ ArrayList extras = null;
+ for (int i = 0, l = additionalUnits.length; i < l; i++) {
+ SourceFile unit = additionalUnits[i];
+ if (unit != null && newState.getDefinedTypeNamesFor(unit.typeLocator()) != null) {
+ if (JavaBuilder.DEBUG)
+ System.out.println("About to compile file with secondary types "+ unit.typeLocator()); //$NON-NLS-1$
+ if (extras == null)
+ extras = new ArrayList(3);
+ extras.add(unit);
+ }
+ }
+ if (extras != null) {
+ int oldLength = units.length;
+ int toAdd = extras.size();
+ System.arraycopy(units, 0, units = new SourceFile[oldLength + toAdd], 0, oldLength);
+ for (int i = 0; i < toAdd; i++)
+ units[oldLength++] = (SourceFile) extras.get(i);
+ }
+ }
+ super.compile(units, additionalUnits, compilingFirstGroup);
+}
+
+protected void deleteGeneratedFiles(IFile[] deletedGeneratedFiles) {
+ // delete generated files and recompile any affected source files
+ try {
+ for (int j = deletedGeneratedFiles.length; --j >= 0;) {
+ IFile deletedFile = deletedGeneratedFiles[j];
+ if (deletedFile.exists()) continue; // only delete .class files for source files that were actually deleted
+
+ SourceFile sourceFile = findSourceFile(deletedFile, false);
+ String typeLocator = sourceFile.typeLocator();
+ int mdSegmentCount = sourceFile.sourceLocation.sourceFolder.getFullPath().segmentCount();
+ IPath typePath = sourceFile.resource.getFullPath().removeFirstSegments(mdSegmentCount).removeFileExtension();
+ addDependentsOf(typePath, true); // add dependents of the source file since its now deleted
+ previousSourceFiles = null; // existing source files did not see it as deleted since they were compiled before it was
+ char[][] definedTypeNames = newState.getDefinedTypeNamesFor(typeLocator);
+ if (definedTypeNames == null) { // defined a single type matching typePath
+ removeClassFile(typePath, sourceFile.sourceLocation.binaryFolder);
+ } else {
+ if (definedTypeNames.length > 0) { // skip it if it failed to successfully define a type
+ IPath packagePath = typePath.removeLastSegments(1);
+ for (int d = 0, l = definedTypeNames.length; d < l; d++)
+ removeClassFile(packagePath.append(new String(definedTypeNames[d])), sourceFile.sourceLocation.binaryFolder);
+ }
+ }
+ this.newState.removeLocator(typeLocator);
+ }
+ } catch (CoreException e) {
+ // must continue with compile loop so just log the CoreException
+ e.printStackTrace();
+ }
+}
+
protected boolean findAffectedSourceFiles(IResourceDelta delta, ClasspathLocation[] classFoldersAndJars, IProject prereqProject) {
for (int i = 0, l = classFoldersAndJars.length; i < l; i++) {
ClasspathLocation bLocation = classFoldersAndJars[i];
@@ -306,15 +431,29 @@
}
protected boolean findSourceFiles(IResourceDelta delta) throws CoreException {
+ ArrayList visited = this.makeOutputFolderConsistent ? new ArrayList(sourceLocations.length) : null;
for (int i = 0, l = sourceLocations.length; i < l; i++) {
ClasspathMultiDirectory md = sourceLocations[i];
+ if (this.makeOutputFolderConsistent && md.hasIndependentOutputFolder && !visited.contains(md.binaryFolder)) {
+ // even a project which acts as its own source folder can have an independent/nested output folder
+ visited.add(md.binaryFolder);
+ IResourceDelta binaryDelta = delta.findMember(md.binaryFolder.getProjectRelativePath());
+ if (binaryDelta != null) {
+ int segmentCount = binaryDelta.getFullPath().segmentCount();
+ IResourceDelta[] children = binaryDelta.getAffectedChildren();
+ for (int j = 0, m = children.length; j < m; j++)
+ if (!checkForClassFileChanges(children[j], md, segmentCount))
+ return false;
+ }
+ }
if (md.sourceFolder.equals(javaBuilder.currentProject)) {
// skip nested source & output folders when the project is a source folder
int segmentCount = delta.getFullPath().segmentCount();
IResourceDelta[] children = delta.getAffectedChildren();
for (int j = 0, m = children.length; j < m; j++)
if (!isExcludedFromProject(children[j].getFullPath()))
- findSourceFiles(children[j], md, segmentCount);
+ if (!findSourceFiles(children[j], md, segmentCount))
+ return false;
} else {
IResourceDelta sourceDelta = delta.findMember(md.sourceFolder.getProjectRelativePath());
if (sourceDelta != null) {
@@ -327,7 +466,8 @@
IResourceDelta[] children = sourceDelta.getAffectedChildren();
try {
for (int j = 0, m = children.length; j < m; j++)
- findSourceFiles(children[j], md, segmentCount);
+ if (!findSourceFiles(children[j], md, segmentCount))
+ return false;
} catch (CoreException e) {
// catch the case that a package has been renamed and collides on disk with an as-yet-to-be-deleted package
if (e.getStatus().getCode() == IResourceStatus.CASE_VARIANT_EXISTS) {
@@ -344,7 +484,7 @@
return true;
}
-protected void findSourceFiles(IResourceDelta sourceDelta, ClasspathMultiDirectory md, int segmentCount) throws CoreException {
+protected boolean findSourceFiles(IResourceDelta sourceDelta, ClasspathMultiDirectory md, int segmentCount) throws CoreException {
// When a package becomes a type or vice versa, expect 2 deltas,
// one on the folder & one on the source file
IResource resource = sourceDelta.getResource();
@@ -354,31 +494,38 @@
switch(resource.getType()) {
case IResource.FOLDER :
if (isExcluded && md.inclusionPatterns == null)
- return; // no need to go further with this delta since its children cannot be included
+ return true; // no need to go further with this delta since its children cannot be included
switch (sourceDelta.getKind()) {
case IResourceDelta.ADDED :
if (!isExcluded) {
IPath addedPackagePath = resource.getFullPath().removeFirstSegments(segmentCount);
createFolder(addedPackagePath, md.binaryFolder); // ensure package exists in the output folder
- // add dependents even when the package thinks it exists to be on the safe side
- if (JavaBuilder.DEBUG)
- System.out.println("Found added package " + addedPackagePath); //$NON-NLS-1$
- addDependentsOf(addedPackagePath, true);
- }
+ // see if any known source file is from the same package... classpath already includes new package
+ if (sourceLocations.length > 1 && newState.isKnownPackage(addedPackagePath.toString())) {
+ if (JavaBuilder.DEBUG)
+ System.out.println("Skipped dependents of added package " + addedPackagePath); //$NON-NLS-1$
+ } else {
+ if (JavaBuilder.DEBUG)
+ System.out.println("Found added package " + addedPackagePath); //$NON-NLS-1$
+ addDependentsOf(addedPackagePath, true);
+ }
+ }
// fall thru & collect all the source files
case IResourceDelta.CHANGED :
IResourceDelta[] children = sourceDelta.getAffectedChildren();
for (int i = 0, l = children.length; i < l; i++)
- findSourceFiles(children[i], md, segmentCount);
- return;
+ if (!findSourceFiles(children[i], md, segmentCount))
+ return false;
+ return true;
case IResourceDelta.REMOVED :
if (isExcluded) {
// since this folder is excluded then there is nothing to delete (from this md), but must walk any included subfolders
children = sourceDelta.getAffectedChildren();
for (int i = 0, l = children.length; i < l; i++)
- findSourceFiles(children[i], md, segmentCount);
- return;
+ if (!findSourceFiles(children[i], md, segmentCount))
+ return false;
+ return true;
}
IPath removedPackagePath = resource.getFullPath().removeFirstSegments(segmentCount);
if (sourceLocations.length > 1) {
@@ -388,8 +535,9 @@
createFolder(removedPackagePath, md.binaryFolder); // ensure package exists in the output folder
IResourceDelta[] removedChildren = sourceDelta.getAffectedChildren();
for (int j = 0, m = removedChildren.length; j < m; j++)
- findSourceFiles(removedChildren[j], md, segmentCount);
- return;
+ if (!findSourceFiles(removedChildren[j], md, segmentCount))
+ return false;
+ return true;
}
}
}
@@ -402,9 +550,9 @@
addDependentsOf(removedPackagePath, true);
newState.removePackage(sourceDelta);
}
- return;
+ return true;
case IResource.FILE :
- if (isExcluded) return;
+ if (isExcluded) return true;
String resourceName = resource.getName();
if (org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(resourceName)) {
@@ -421,7 +569,7 @@
System.out.println("Found added source file " + typeName); //$NON-NLS-1$
addDependentsOf(typePath, true);
}
- return;
+ return true;
case IResourceDelta.REMOVED :
char[][] definedTypeNames = newState.getDefinedTypeNamesFor(typeLocator);
if (definedTypeNames == null) { // defined a single type matching typePath
@@ -445,20 +593,29 @@
}
}
newState.removeLocator(typeLocator);
- return;
+ return true;
case IResourceDelta.CHANGED :
if ((sourceDelta.getFlags() & IResourceDelta.CONTENT) == 0
&& (sourceDelta.getFlags() & IResourceDelta.ENCODING) == 0)
- return; // skip it since it really isn't changed
+ return true; // skip it since it really isn't changed
if (JavaBuilder.DEBUG)
System.out.println("Compile this changed source file " + typeLocator); //$NON-NLS-1$
sourceFiles.add(new SourceFile((IFile) resource, md, true));
}
- return;
+ return true;
} else if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(resourceName)) {
- return; // skip class files
+ // perform full build if a managed class file has been changed
+ if (this.makeOutputFolderConsistent) {
+ IPath typePath = resource.getFullPath().removeFirstSegments(segmentCount).removeFileExtension();
+ if (newState.isKnownType(typePath.toString())) {
+ if (JavaBuilder.DEBUG)
+ System.out.println("MUST DO FULL BUILD. Found change to class file " + typePath); //$NON-NLS-1$
+ return false;
+ }
+ }
+ return true;
} else if (md.hasIndependentOutputFolder) {
- if (javaBuilder.filterExtraResource(resource)) return;
+ if (javaBuilder.filterExtraResource(resource)) return true;
// copy all other resource deltas to the output folder
IPath resourcePath = resource.getFullPath().removeFirstSegments(segmentCount);
@@ -473,21 +630,20 @@
if (JavaBuilder.DEBUG)
System.out.println("Copying added file " + resourcePath); //$NON-NLS-1$
createFolder(resourcePath.removeLastSegments(1), md.binaryFolder); // ensure package exists in the output folder
- resource.copy(outputFile.getFullPath(), IResource.FORCE, null);
- outputFile.setDerived(true);
+ resource.copy(outputFile.getFullPath(), IResource.FORCE | IResource.DERIVED, null);
Util.setReadOnly(outputFile, false); // just in case the original was read only
- return;
+ return true;
case IResourceDelta.REMOVED :
if (outputFile.exists()) {
if (JavaBuilder.DEBUG)
System.out.println("Deleting removed file " + resourcePath); //$NON-NLS-1$
outputFile.delete(IResource.FORCE, null);
}
- return;
+ return true;
case IResourceDelta.CHANGED :
if ((sourceDelta.getFlags() & IResourceDelta.CONTENT) == 0
&& (sourceDelta.getFlags() & IResourceDelta.ENCODING) == 0)
- return; // skip it since it really isn't changed
+ return true; // skip it since it really isn't changed
if (outputFile.exists()) {
if (JavaBuilder.DEBUG)
System.out.println("Deleting existing file " + resourcePath); //$NON-NLS-1$
@@ -496,13 +652,13 @@
if (JavaBuilder.DEBUG)
System.out.println("Copying changed file " + resourcePath); //$NON-NLS-1$
createFolder(resourcePath.removeLastSegments(1), md.binaryFolder); // ensure package exists in the output folder
- resource.copy(outputFile.getFullPath(), IResource.FORCE, null);
- outputFile.setDerived(true);
+ resource.copy(outputFile.getFullPath(), IResource.FORCE | IResource.DERIVED, null);
Util.setReadOnly(outputFile, false); // just in case the original was read only
}
- return;
+ return true;
}
}
+ return true;
}
protected void finishedWith(String sourceLocator, CompilationResult result, char[] mainTypeName, ArrayList definedTypeNames, ArrayList duplicateTypeNames) {
@@ -532,6 +688,28 @@
super.finishedWith(sourceLocator, result, mainTypeName, definedTypeNames, duplicateTypeNames);
}
+protected void processAnnotationResults(CompilationParticipantResult[] results) {
+ for (int i = results.length; --i >= 0;) {
+ CompilationParticipantResult result = results[i];
+ if (result == null) continue;
+
+ IFile[] deletedGeneratedFiles = result.deletedFiles;
+ if (deletedGeneratedFiles != null)
+ deleteGeneratedFiles(deletedGeneratedFiles);
+
+ IFile[] addedGeneratedFiles = result.addedFiles;
+ if (addedGeneratedFiles != null) {
+ for (int j = addedGeneratedFiles.length; --j >= 0;) {
+ SourceFile sourceFile = findSourceFile(addedGeneratedFiles[j], true);
+ if (sourceFile != null && !sourceFiles.contains(sourceFile))
+ this.sourceFiles.add(sourceFile);
+ }
+ }
+
+ recordParticipantResult(result);
+ }
+}
+
protected void removeClassFile(IPath typePath, IContainer outputFolder) throws CoreException {
if (typePath.lastSegment().indexOf('$') == -1) { // is not a nested type
newState.removeQualifiedTypeName(typePath.toString());
@@ -561,23 +739,32 @@
}
}
this.secondaryTypesToRemove = null;
- if (previousSourceFiles != null && previousSourceFiles.size() > 1)
- this.previousSourceFiles = null; // cannot optimize recompile case when a secondary type is deleted
+ if (previousSourceFiles != null)
+ this.previousSourceFiles = null; // cannot optimize recompile case when a secondary type is deleted, see 181269
}
}
protected void resetCollections() {
- previousSourceFiles = sourceFiles.isEmpty() ? null : (ArrayList) sourceFiles.clone();
+ if (this.sourceFiles == null) {
+ this.sourceFiles = new ArrayList(33);
+ this.previousSourceFiles = null;
+ this.qualifiedStrings = new StringSet(3);
+ this.simpleStrings = new StringSet(3);
+ this.hasStructuralChanges = false;
+ this.compileLoop = 0;
+ } else {
+ this.previousSourceFiles = this.sourceFiles.isEmpty() ? null : (ArrayList) this.sourceFiles.clone();
- sourceFiles.clear();
- qualifiedStrings.clear();
- simpleStrings.clear();
- workQueue.clear();
+ this.sourceFiles.clear();
+ this.qualifiedStrings.clear();
+ this.simpleStrings.clear();
+ this.workQueue.clear();
+ }
}
protected void updateProblemsFor(SourceFile sourceFile, CompilationResult result) throws CoreException {
IMarker[] markers = JavaBuilder.getProblemsFor(sourceFile.resource);
- IProblem[] problems = result.getProblems();
+ CategorizedProblem[] problems = result.getProblems();
if (problems == null && markers.length == 0) return;
notifier.updateProblemCounts(markers, problems);
@@ -587,40 +774,70 @@
protected void updateTasksFor(SourceFile sourceFile, CompilationResult result) throws CoreException {
IMarker[] markers = JavaBuilder.getTasksFor(sourceFile.resource);
- IProblem[] tasks = result.getTasks();
+ CategorizedProblem[] tasks = result.getTasks();
if (tasks == null && markers.length == 0) return;
JavaBuilder.removeTasksFor(sourceFile.resource);
storeTasksFor(sourceFile, tasks);
}
-protected void writeClassFileBytes(byte[] bytes, IFile file, String qualifiedFileName, boolean isSecondaryType, boolean updateClassFile) throws CoreException {
+protected void writeClassFileBytes(byte[] bytes, IFile file, String qualifiedFileName, boolean isTopLevelType, SourceFile compilationUnit) throws CoreException {
// Before writing out the class file, compare it to the previous file
- // If structural changes occured then add dependent source files
+ // If structural changes occurred then add dependent source files
if (file.exists()) {
- if (writeClassFileCheck(file, qualifiedFileName, bytes) || updateClassFile) { // see 46093
+ if (writeClassFileCheck(file, qualifiedFileName, bytes) || compilationUnit.updateClassFile) { // see 46093
if (JavaBuilder.DEBUG)
System.out.println("Writing changed class file " + file.getName());//$NON-NLS-1$
- file.setContents(new ByteArrayInputStream(bytes), true, false, null);
if (!file.isDerived())
file.setDerived(true);
+ file.setContents(new ByteArrayInputStream(bytes), true, false, null);
} else if (JavaBuilder.DEBUG) {
System.out.println("Skipped over unchanged class file " + file.getName());//$NON-NLS-1$
}
} else {
- if (isSecondaryType)
- addDependentsOf(new Path(qualifiedFileName), true); // new secondary type
+ if (isTopLevelType)
+ addDependentsOf(new Path(qualifiedFileName), true); // new type
if (JavaBuilder.DEBUG)
System.out.println("Writing new class file " + file.getName());//$NON-NLS-1$
try {
- file.create(new ByteArrayInputStream(bytes), IResource.FORCE, null);
+ file.create(new ByteArrayInputStream(bytes), IResource.FORCE | IResource.DERIVED, null);
} catch (CoreException e) {
- if (e.getStatus().getCode() == IResourceStatus.CASE_VARIANT_EXISTS)
- // catch the case that a nested type has been renamed and collides on disk with an as-yet-to-be-deleted type
+ if (e.getStatus().getCode() == IResourceStatus.CASE_VARIANT_EXISTS) {
+ IStatus status = e.getStatus();
+ if (status instanceof IResourceStatus) {
+ IPath oldFilePath = ((IResourceStatus) status).getPath();
+ char[] oldTypeName = oldFilePath.removeFileExtension().lastSegment().toCharArray();
+ char[][] previousTypeNames = newState.getDefinedTypeNamesFor(compilationUnit.typeLocator());
+ boolean fromSameFile = false;
+ if (previousTypeNames == null) {
+ fromSameFile = CharOperation.equals(compilationUnit.getMainTypeName(), oldTypeName);
+ } else {
+ for (int i = 0, l = previousTypeNames.length; i < l; i++) {
+ if (CharOperation.equals(previousTypeNames[i], oldTypeName)) {
+ fromSameFile = true;
+ break;
+ }
+ }
+ }
+ if (fromSameFile) {
+ // file is defined by the same compilationUnit, but won't be deleted until later so do it now
+ IFile collision = file.getParent().getFile(new Path(oldFilePath.lastSegment()));
+ collision.delete(true, false, null);
+ boolean success = false;
+ try {
+ file.create(new ByteArrayInputStream(bytes), IResource.FORCE | IResource.DERIVED, null);
+ success = true;
+ } catch (CoreException ignored) {
+ // ignore the second exception
+ }
+ if (success) return;
+ }
+ }
+ // catch the case that a type has been renamed and collides on disk with an as-yet-to-be-deleted type
throw new AbortCompilation(true, new AbortIncrementalBuildException(qualifiedFileName));
+ }
throw e; // rethrow
}
- file.setDerived(true);
}
}
@@ -632,9 +849,10 @@
if (newBytes[i] != oldBytes[i]) break notEqual;
return false; // bytes are identical so skip them
}
- IPath location = file.getLocation();
+ URI location = file.getLocationURI();
if (location == null) return false; // unable to determine location of this class file
- ClassFileReader reader = new ClassFileReader(oldBytes, location.toString().toCharArray());
+ String filePath = location.getSchemeSpecificPart();
+ ClassFileReader reader = new ClassFileReader(oldBytes, filePath.toCharArray());
// ignore local types since they're only visible inside a single method
if (!(reader.isLocal() || reader.isAnonymous()) && reader.hasStructuralChanges(newBytes)) {
if (JavaBuilder.DEBUG)
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java
index da7935d..e0e6173 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -14,7 +14,7 @@
import org.eclipse.core.runtime.*;
import org.eclipse.jdt.core.*;
-import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.compiler.*;
import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
import org.eclipse.jdt.internal.core.*;
import org.eclipse.jdt.internal.core.util.Messages;
@@ -28,12 +28,14 @@
IProject currentProject;
JavaProject javaProject;
IWorkspaceRoot workspaceRoot;
+CompilationParticipant[] participants;
NameEnvironment nameEnvironment;
SimpleLookupTable binaryLocationsPerProject; // maps a project to its binary resources (output folders, class folders, zip/jar files)
-State lastState;
+public State lastState;
BuildNotifier notifier;
char[][] extraResourceFileFilters;
String[] extraResourceFolderFilters;
+public static final String SOURCE_ID = "JDT"; //$NON-NLS-1$
public static boolean DEBUG = false;
@@ -46,8 +48,25 @@
public static IMarker[] getProblemsFor(IResource resource) {
try {
- if (resource != null && resource.exists())
- return resource.findMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE);
+ if (resource != null && resource.exists()) {
+ IMarker[] markers = resource.findMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE);
+ Set markerTypes = JavaModelManager.getJavaModelManager().compilationParticipants.managedMarkerTypes();
+ if (markerTypes.isEmpty()) return markers;
+ ArrayList markerList = new ArrayList(5);
+ for (int i = 0, length = markers.length; i < length; i++) {
+ markerList.add(markers[i]);
+ }
+ Iterator iterator = markerTypes.iterator();
+ while (iterator.hasNext()) {
+ markers = resource.findMarkers((String) iterator.next(), false, IResource.DEPTH_INFINITE);
+ for (int i = 0, length = markers.length; i < length; i++) {
+ markerList.add(markers[i]);
+ }
+ }
+ IMarker[] result;
+ markerList.toArray(result = new IMarker[markerList.size()]);
+ return result;
+ }
} catch (CoreException e) {
// assume there are no problems
}
@@ -82,8 +101,16 @@
public static void removeProblemsFor(IResource resource) {
try {
- if (resource != null && resource.exists())
+ if (resource != null && resource.exists()) {
resource.deleteMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE);
+
+ // delete managed markers
+ Set markerTypes = JavaModelManager.getJavaModelManager().compilationParticipants.managedMarkerTypes();
+ if (markerTypes.size() == 0) return;
+ Iterator iterator = markerTypes.iterator();
+ while (iterator.hasNext())
+ resource.deleteMarkers((String) iterator.next(), false, IResource.DEPTH_INFINITE);
+ }
} catch (CoreException e) {
// assume there were no problems
}
@@ -103,6 +130,13 @@
if (resource != null && resource.exists()) {
resource.deleteMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE);
resource.deleteMarkers(IJavaModelMarker.TASK_MARKER, false, IResource.DEPTH_INFINITE);
+
+ // delete managed markers
+ Set markerTypes = JavaModelManager.getJavaModelManager().compilationParticipants.managedMarkerTypes();
+ if (markerTypes.size() == 0) return;
+ Iterator iterator = markerTypes.iterator();
+ while (iterator.hasNext())
+ resource.deleteMarkers((String) iterator.next(), false, IResource.DEPTH_INFINITE);
}
} catch (CoreException e) {
// assume there were no problems
@@ -129,10 +163,12 @@
boolean ok = false;
try {
notifier.checkCancel();
- initializeBuilder();
+ kind = initializeBuilder(kind, true);
if (isWorthBuilding()) {
if (kind == FULL_BUILD) {
+ if (DEBUG)
+ System.out.println("Performing full build as requested by user"); //$NON-NLS-1$
buildAll();
} else {
if ((this.lastState = getLastState(currentProject)) == null) {
@@ -142,18 +178,25 @@
} else if (hasClasspathChanged()) {
// if the output location changes, do not delete the binary files from old location
// the user may be trying something
+ if (DEBUG)
+ System.out.println("Performing full build since classpath has changed"); //$NON-NLS-1$
buildAll();
} else if (nameEnvironment.sourceLocations.length > 0) {
// if there is no source to compile & no classpath changes then we are done
SimpleLookupTable deltas = findDeltas();
- if (deltas == null)
+ if (deltas == null) {
+ if (DEBUG)
+ System.out.println("Performing full build since deltas are missing after incremental request"); //$NON-NLS-1$
buildAll();
- else if (deltas.elementSize > 0)
+ } else if (deltas.elementSize > 0) {
buildDeltas(deltas);
- else if (DEBUG)
+ } else if (DEBUG) {
System.out.println("Nothing to build since deltas were empty"); //$NON-NLS-1$
+ }
} else {
if (hasStructuralDelta()) { // double check that a jar file didn't get replaced in a binary project
+ if (DEBUG)
+ System.out.println("Performing full build since there are structural deltas"); //$NON-NLS-1$
buildAll();
} else {
if (DEBUG)
@@ -167,28 +210,41 @@
} catch (CoreException e) {
Util.log(e, "JavaBuilder handling CoreException while building: " + currentProject.getName()); //$NON-NLS-1$
IMarker marker = currentProject.createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER);
- marker.setAttribute(IMarker.MESSAGE, Messages.bind(Messages.build_inconsistentProject, e.getLocalizedMessage()));
- marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
+ marker.setAttributes(
+ new String[] {IMarker.MESSAGE, IMarker.SEVERITY, IJavaModelMarker.CATEGORY_ID, IMarker.SOURCE_ID},
+ new Object[] {
+ Messages.bind(Messages.build_inconsistentProject, e.getLocalizedMessage()),
+ new Integer(IMarker.SEVERITY_ERROR),
+ new Integer(CategorizedProblem.CAT_BUILDPATH),
+ JavaBuilder.SOURCE_ID
+ }
+ );
} catch (ImageBuilderInternalException e) {
Util.log(e.getThrowable(), "JavaBuilder handling ImageBuilderInternalException while building: " + currentProject.getName()); //$NON-NLS-1$
IMarker marker = currentProject.createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER);
- marker.setAttribute(IMarker.MESSAGE, Messages.bind(Messages.build_inconsistentProject, e.getLocalizedMessage()));
- marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
- } catch (MissingClassFileException e) {
- // do not log this exception since its thrown to handle aborted compiles because of missing class files
- if (DEBUG)
- System.out.println(Messages.bind(Messages.build_incompleteClassPath, e.missingClassFile));
- IMarker marker = currentProject.createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER);
- marker.setAttribute(IMarker.MESSAGE, Messages.bind(Messages.build_incompleteClassPath, e.missingClassFile));
- marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
+ marker.setAttributes(
+ new String[] {IMarker.MESSAGE, IMarker.SEVERITY, IJavaModelMarker.CATEGORY_ID, IMarker.SOURCE_ID},
+ new Object[] {
+ Messages.bind(Messages.build_inconsistentProject, e.getLocalizedMessage()),
+ new Integer(IMarker.SEVERITY_ERROR),
+ new Integer(CategorizedProblem.CAT_BUILDPATH),
+ JavaBuilder.SOURCE_ID
+ }
+ );
} catch (MissingSourceFileException e) {
// do not log this exception since its thrown to handle aborted compiles because of missing source files
if (DEBUG)
- System.out.println(Messages.bind(Messages.build_missingSourceFile, e.missingSourceFile));
+ System.out.println(Messages.bind(Messages.build_missingSourceFile, e.missingSourceFile));
removeProblemsAndTasksFor(currentProject); // make this the only problem for this project
IMarker marker = currentProject.createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER);
- marker.setAttribute(IMarker.MESSAGE, Messages.bind(Messages.build_missingSourceFile, e.missingSourceFile));
- marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
+ marker.setAttributes(
+ new String[] {IMarker.MESSAGE, IMarker.SEVERITY, IMarker.SOURCE_ID},
+ new Object[] {
+ Messages.bind(Messages.build_missingSourceFile, e.missingSourceFile),
+ new Integer(IMarker.SEVERITY_ERROR),
+ JavaBuilder.SOURCE_ID
+ }
+ );
} finally {
if (!ok)
// If the build failed, clear the previously built state, forcing a full build next time.
@@ -205,26 +261,29 @@
private void buildAll() {
notifier.checkCancel();
- notifier.subTask(Messages.build_preparingBuild);
+ notifier.subTask(Messages.bind(Messages.build_preparingBuild, this.currentProject.getName()));
if (DEBUG && lastState != null)
System.out.println("Clearing last state : " + lastState); //$NON-NLS-1$
clearLastState();
- BatchImageBuilder imageBuilder = new BatchImageBuilder(this);
+ BatchImageBuilder imageBuilder = new BatchImageBuilder(this, true);
imageBuilder.build();
recordNewState(imageBuilder.newState);
}
private void buildDeltas(SimpleLookupTable deltas) {
notifier.checkCancel();
- notifier.subTask(Messages.build_preparingBuild);
+ notifier.subTask(Messages.bind(Messages.build_preparingBuild, this.currentProject.getName()));
if (DEBUG && lastState != null)
System.out.println("Clearing last state : " + lastState); //$NON-NLS-1$
clearLastState(); // clear the previously built state so if the build fails, a full build will occur next time
IncrementalImageBuilder imageBuilder = new IncrementalImageBuilder(this);
- if (imageBuilder.build(deltas))
+ if (imageBuilder.build(deltas)) {
recordNewState(imageBuilder.newState);
- else
+ } else {
+ if (DEBUG)
+ System.out.println("Performing full build since incremental build failed"); //$NON-NLS-1$
buildAll();
+ }
}
protected void clean(IProgressMonitor monitor) throws CoreException {
@@ -239,17 +298,23 @@
try {
notifier.checkCancel();
- initializeBuilder();
+ initializeBuilder(CLEAN_BUILD, true);
if (DEBUG)
System.out.println("Clearing last state as part of clean : " + lastState); //$NON-NLS-1$
clearLastState();
removeProblemsAndTasksFor(currentProject);
- new BatchImageBuilder(this).cleanOutputFolders(false);
+ new BatchImageBuilder(this, false).cleanOutputFolders(false);
} catch (CoreException e) {
Util.log(e, "JavaBuilder handling CoreException while cleaning: " + currentProject.getName()); //$NON-NLS-1$
IMarker marker = currentProject.createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER);
- marker.setAttribute(IMarker.MESSAGE, Messages.bind(Messages.build_inconsistentProject, e.getLocalizedMessage()));
- marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
+ marker.setAttributes(
+ new String[] {IMarker.MESSAGE, IMarker.SEVERITY, IMarker.SOURCE_ID},
+ new Object[] {
+ Messages.bind(Messages.build_inconsistentProject, e.getLocalizedMessage()),
+ new Integer(IMarker.SEVERITY_ERROR),
+ JavaBuilder.SOURCE_ID
+ }
+ );
} finally {
notifier.done();
cleanup();
@@ -260,6 +325,7 @@
}
private void cleanup() {
+ this.participants = null;
this.nameEnvironment = null;
this.binaryLocationsPerProject = null;
this.lastState = null;
@@ -294,7 +360,7 @@
}
private SimpleLookupTable findDeltas() {
- notifier.subTask(Messages.bind(Messages.build_readingDelta, currentProject.getName()));
+ notifier.subTask(Messages.bind(Messages.build_readingDelta, currentProject.getName()));
IResourceDelta delta = getDelta(currentProject);
SimpleLookupTable deltas = new SimpleLookupTable(3);
if (delta != null) {
@@ -330,7 +396,7 @@
if (canSkip) continue nextProject; // project has no structural changes in its output folders
}
- notifier.subTask(Messages.bind(Messages.build_readingDelta, p.getName()));
+ notifier.subTask(Messages.bind(Messages.build_readingDelta, p.getName()));
delta = getDelta(p);
if (delta != null) {
if (delta.getKind() != IResourceDelta.NO_CHANGE) {
@@ -355,7 +421,7 @@
}
/* Return the list of projects for which it requires a resource delta. This builder's project
-* is implicitly included and need not be specified. Builders must re-specify the list
+* is implicitly included and need not be specified. Builders must re-specify the list
* of interesting projects every time they are run as this is not carried forward
* beyond the next build. Missing projects should be specified but will be ignored until
* they are added to the workspace.
@@ -365,7 +431,7 @@
ArrayList projects = new ArrayList();
try {
- IClasspathEntry[] entries = javaProject.getExpandedClasspath(true);
+ IClasspathEntry[] entries = javaProject.getExpandedClasspath();
for (int i = 0, l = entries.length; i < l; i++) {
IClasspathEntry entry = entries[i];
IPath path = entry.getPath();
@@ -373,6 +439,8 @@
switch (entry.getEntryKind()) {
case IClasspathEntry.CPE_PROJECT :
p = workspaceRoot.getProject(path.lastSegment()); // missing projects are considered too
+ if (((ClasspathEntry) entry).isOptional() && !JavaProject.hasJavaNature(p)) // except if entry is optional
+ p = null;
break;
case IClasspathEntry.CPE_LIBRARY :
if (includeBinaryPrerequisites && path.segmentCount() > 1) {
@@ -393,6 +461,14 @@
return result;
}
+boolean hasBuildpathErrors() throws CoreException {
+ IMarker[] markers = this.currentProject.findMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, false, IResource.DEPTH_ZERO);
+ for (int i = 0, l = markers.length; i < l; i++)
+ if (markers[i].getAttribute(IJavaModelMarker.CATEGORY_ID, -1) == CategorizedProblem.CAT_BUILDPATH)
+ return true;
+ return false;
+}
+
private boolean hasClasspathChanged() {
ClasspathMultiDirectory[] newSourceLocations = nameEnvironment.sourceLocations;
ClasspathMultiDirectory[] oldSourceLocations = lastState.sourceLocations;
@@ -458,6 +534,14 @@
return false;
}
+private boolean hasJavaBuilder(IProject project) throws CoreException {
+ ICommand[] buildCommands = project.getDescription().getBuildSpec();
+ for (int i = 0, l = buildCommands.length; i < l; i++)
+ if (buildCommands[i].getBuilderName().equals(JavaCore.BUILDER_ID))
+ return true;
+ return false;
+}
+
private boolean hasStructuralDelta() {
// handle case when currentProject has only .class file folders and/or jar files... no source/output folders
IResourceDelta delta = getDelta(currentProject);
@@ -480,55 +564,65 @@
return false;
}
-private void initializeBuilder() throws CoreException {
+private int initializeBuilder(int kind, boolean forBuild) throws CoreException {
+ // some calls just need the nameEnvironment initialized so skip the rest
this.javaProject = (JavaProject) JavaCore.create(currentProject);
this.workspaceRoot = currentProject.getWorkspace().getRoot();
- // Flush the existing external files cache if this is the beginning of a build cycle
- String projectName = currentProject.getName();
- if (builtProjects == null || builtProjects.contains(projectName)) {
- JavaModel.flushExternalFileCache();
- builtProjects = new ArrayList();
+ if (forBuild) {
+ // cache the known participants for this project
+ this.participants = JavaModelManager.getJavaModelManager().compilationParticipants.getCompilationParticipants(this.javaProject);
+ if (this.participants != null)
+ for (int i = 0, l = this.participants.length; i < l; i++)
+ if (this.participants[i].aboutToBuild(this.javaProject) == CompilationParticipant.NEEDS_FULL_BUILD)
+ kind = FULL_BUILD;
+
+ // Flush the existing external files cache if this is the beginning of a build cycle
+ String projectName = currentProject.getName();
+ if (builtProjects == null || builtProjects.contains(projectName)) {
+ JavaModel.flushExternalFileCache();
+ builtProjects = new ArrayList();
+ }
+ builtProjects.add(projectName);
}
- builtProjects.add(projectName);
this.binaryLocationsPerProject = new SimpleLookupTable(3);
- this.nameEnvironment = new NameEnvironment(workspaceRoot, javaProject, binaryLocationsPerProject);
+ this.nameEnvironment = new NameEnvironment(workspaceRoot, javaProject, binaryLocationsPerProject, notifier);
- String filterSequence = javaProject.getOption(JavaCore.CORE_JAVA_BUILD_RESOURCE_COPY_FILTER, true);
- char[][] filters = filterSequence != null && filterSequence.length() > 0
- ? CharOperation.splitAndTrimOn(',', filterSequence.toCharArray())
- : null;
- if (filters == null) {
- this.extraResourceFileFilters = null;
- this.extraResourceFolderFilters = null;
- } else {
- int fileCount = 0, folderCount = 0;
- for (int i = 0, l = filters.length; i < l; i++) {
- char[] f = filters[i];
- if (f.length == 0) continue;
- if (f[f.length - 1] == '/') folderCount++; else fileCount++;
- }
- this.extraResourceFileFilters = new char[fileCount][];
- this.extraResourceFolderFilters = new String[folderCount];
- for (int i = 0, l = filters.length; i < l; i++) {
- char[] f = filters[i];
- if (f.length == 0) continue;
- if (f[f.length - 1] == '/')
- extraResourceFolderFilters[--folderCount] = new String(f, 0, f.length - 1);
- else
- extraResourceFileFilters[--fileCount] = f;
+ if (forBuild) {
+ String filterSequence = javaProject.getOption(JavaCore.CORE_JAVA_BUILD_RESOURCE_COPY_FILTER, true);
+ char[][] filters = filterSequence != null && filterSequence.length() > 0
+ ? CharOperation.splitAndTrimOn(',', filterSequence.toCharArray())
+ : null;
+ if (filters == null) {
+ this.extraResourceFileFilters = null;
+ this.extraResourceFolderFilters = null;
+ } else {
+ int fileCount = 0, folderCount = 0;
+ for (int i = 0, l = filters.length; i < l; i++) {
+ char[] f = filters[i];
+ if (f.length == 0) continue;
+ if (f[f.length - 1] == '/') folderCount++; else fileCount++;
+ }
+ this.extraResourceFileFilters = new char[fileCount][];
+ this.extraResourceFolderFilters = new String[folderCount];
+ for (int i = 0, l = filters.length; i < l; i++) {
+ char[] f = filters[i];
+ if (f.length == 0) continue;
+ if (f[f.length - 1] == '/')
+ extraResourceFolderFilters[--folderCount] = new String(f, 0, f.length - 1);
+ else
+ extraResourceFileFilters[--fileCount] = f;
+ }
}
}
+ return kind;
}
private boolean isClasspathBroken(IClasspathEntry[] classpath, IProject p) throws CoreException {
- if (classpath == JavaProject.INVALID_CLASSPATH) // the .classpath file could not be read
- return true;
-
IMarker[] markers = p.findMarkers(IJavaModelMarker.BUILDPATH_PROBLEM_MARKER, false, IResource.DEPTH_ZERO);
for (int i = 0, l = markers.length; i < l; i++)
- if (((Integer) markers[i].getAttribute(IMarker.SEVERITY)).intValue() == IMarker.SEVERITY_ERROR)
+ if (markers[i].getAttribute(IMarker.SEVERITY, -1) == IMarker.SEVERITY_ERROR)
return true;
return false;
}
@@ -546,8 +640,15 @@
removeProblemsAndTasksFor(currentProject); // remove all compilation problems
IMarker marker = currentProject.createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER);
- marker.setAttribute(IMarker.MESSAGE, Messages.build_abortDueToClasspathProblems);
- marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
+ marker.setAttributes(
+ new String[] {IMarker.MESSAGE, IMarker.SEVERITY, IJavaModelMarker.CATEGORY_ID, IMarker.SOURCE_ID},
+ new Object[] {
+ Messages.build_abortDueToClasspathProblems,
+ new Integer(IMarker.SEVERITY_ERROR),
+ new Integer(CategorizedProblem.CAT_BUILDPATH),
+ JavaBuilder.SOURCE_ID
+ }
+ );
return false;
}
@@ -557,24 +658,40 @@
// make sure all prereq projects have valid build states... only when aborting builds since projects in cycles do not have build states
// except for projects involved in a 'warning' cycle (see below)
IProject[] requiredProjects = getRequiredProjects(false);
- next : for (int i = 0, l = requiredProjects.length; i < l; i++) {
+ for (int i = 0, l = requiredProjects.length; i < l; i++) {
IProject p = requiredProjects[i];
if (getLastState(p) == null) {
// The prereq project has no build state: if this prereq project has a 'warning' cycle marker then allow build (see bug id 23357)
JavaProject prereq = (JavaProject) JavaCore.create(p);
- if (prereq.hasCycleMarker() && JavaCore.WARNING.equals(javaProject.getOption(JavaCore.CORE_CIRCULAR_CLASSPATH, true)))
+ if (prereq.hasCycleMarker() && JavaCore.WARNING.equals(javaProject.getOption(JavaCore.CORE_CIRCULAR_CLASSPATH, true))) {
+ if (DEBUG)
+ System.out.println("Continued to build even though prereq project " + p.getName() //$NON-NLS-1$
+ + " was not built since its part of a cycle"); //$NON-NLS-1$
continue;
+ }
+ if (!hasJavaBuilder(p)) {
+ if (DEBUG)
+ System.out.println("Continued to build even though prereq project " + p.getName() //$NON-NLS-1$
+ + " is not built by JavaBuilder"); //$NON-NLS-1$
+ continue;
+ }
if (DEBUG)
System.out.println("Aborted build because prereq project " + p.getName() //$NON-NLS-1$
+ " was not built"); //$NON-NLS-1$
removeProblemsAndTasksFor(currentProject); // make this the only problem for this project
IMarker marker = currentProject.createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER);
- marker.setAttribute(IMarker.MESSAGE,
- isClasspathBroken(prereq.getRawClasspath(), p)
- ? Messages.bind(Messages.build_prereqProjectHasClasspathProblems, p.getName())
- : Messages.bind(Messages.build_prereqProjectMustBeRebuilt, p.getName()));
- marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
+ marker.setAttributes(
+ new String[] {IMarker.MESSAGE, IMarker.SEVERITY, IJavaModelMarker.CATEGORY_ID, IMarker.SOURCE_ID},
+ new Object[] {
+ isClasspathBroken(prereq.getRawClasspath(), p)
+ ? Messages.bind(Messages.build_prereqProjectHasClasspathProblems, p.getName())
+ : Messages.bind(Messages.build_prereqProjectMustBeRebuilt, p.getName()),
+ new Integer(IMarker.SEVERITY_ERROR),
+ new Integer(CategorizedProblem.CAT_BUILDPATH),
+ JavaBuilder.SOURCE_ID
+ }
+ );
return false;
}
}
@@ -595,7 +712,7 @@
if (participantPath != currentPath) {
IProject project = workspaceRoot.getProject(participantPath.segment(0));
if (hasBeenBuilt(project)) {
- if (DEBUG)
+ if (DEBUG)
System.out.println("Requesting another build iteration since cycle participant " + project.getName() //$NON-NLS-1$
+ " has not yet seen some structural changes"); //$NON-NLS-1$
needRebuild();
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/MissingClassFileException.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/MissingClassFileException.java
deleted file mode 100644
index 481bc45..0000000
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/MissingClassFileException.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.jdt.internal.core.builder;
-
-/**
- * Exception thrown when the build should be aborted because a referenced
- * class file cannot be found.
- */
-public class MissingClassFileException extends RuntimeException {
-
- protected String missingClassFile;
- private static final long serialVersionUID = 3060418973806972616L; // backward compatible
-
-public MissingClassFileException(String missingClassFile) {
- this.missingClassFile = missingClassFile;
-}
-}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/MissingSourceFileException.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/MissingSourceFileException.java
index f19b704..328f235 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/MissingSourceFileException.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/MissingSourceFileException.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java
index 3fe31fc..23b7163 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -18,9 +18,9 @@
import org.eclipse.jdt.internal.compiler.env.*;
import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
+import org.eclipse.jdt.internal.compiler.util.SimpleSet;
import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
import org.eclipse.jdt.internal.core.*;
-import org.eclipse.jdt.internal.core.util.Util;
import java.io.*;
import java.util.*;
@@ -30,12 +30,14 @@
boolean isIncrementalBuild;
ClasspathMultiDirectory[] sourceLocations;
ClasspathLocation[] binaryLocations;
-
-String[] initialTypeNames; // assumed that each name is of the form "a/b/ClassName"
-SourceFile[] additionalUnits;
+BuildNotifier notifier;
-NameEnvironment(IWorkspaceRoot root, JavaProject javaProject, SimpleLookupTable binaryLocationsPerProject) throws CoreException {
+SimpleSet initialTypeNames; // assumed that each name is of the form "a/b/ClassName"
+SimpleLookupTable additionalUnits;
+
+NameEnvironment(IWorkspaceRoot root, JavaProject javaProject, SimpleLookupTable binaryLocationsPerProject, BuildNotifier notifier) throws CoreException {
this.isIncrementalBuild = false;
+ this.notifier = notifier;
computeClasspathLocations(root, javaProject, binaryLocationsPerProject);
setNames(null, null);
}
@@ -84,11 +86,11 @@
int severity = JavaCore.ERROR.equals(javaProject.getOption(JavaCore.CORE_CIRCULAR_CLASSPATH, true))
? IMarker.SEVERITY_ERROR
: IMarker.SEVERITY_WARNING;
- if (severity != ((Integer) cycleMarker.getAttribute(IMarker.SEVERITY)).intValue())
+ if (severity != cycleMarker.getAttribute(IMarker.SEVERITY, severity))
cycleMarker.setAttribute(IMarker.SEVERITY, severity);
}
- IClasspathEntry[] classpathEntries = javaProject.getExpandedClasspath(true/*ignore unresolved variable*/, false/*don't create markers*/, null/*preferred cp*/, null/*preferred output*/);
+ IClasspathEntry[] classpathEntries = javaProject.getExpandedClasspath();
ArrayList sLocations = new ArrayList(classpathEntries.length);
ArrayList bLocations = new ArrayList(classpathEntries.length);
nextEntry : for (int i = 0, l = classpathEntries.length; i < l; i++) {
@@ -109,7 +111,7 @@
} else {
outputFolder = root.getFolder(outputPath);
if (!outputFolder.exists())
- createFolder(outputFolder);
+ createOutputFolder(outputFolder);
}
sLocations.add(
ClasspathLocation.forSourceFolder((IContainer) target, outputFolder, entry.fullInclusionPatternChars(), entry.fullExclusionPatternChars()));
@@ -136,11 +138,7 @@
: (IContainer) root.getFolder(prereqOutputPath);
if (binaryFolder.exists() && !seen.contains(binaryFolder)) {
seen.add(binaryFolder);
- ClasspathLocation bLocation =
- ClasspathLocation.forBinaryFolder(
- binaryFolder,
- true,
- entry.getAccessRuleSet());
+ ClasspathLocation bLocation = ClasspathLocation.forBinaryFolder(binaryFolder, true, entry.getAccessRuleSet());
bLocations.add(bLocation);
if (binaryLocationsPerProject != null) { // normal builder mode
ClasspathLocation[] existingLocations = (ClasspathLocation[]) binaryLocationsPerProject.get(prereqProject);
@@ -250,45 +248,36 @@
binaryLocations[i].cleanup();
}
-private void createFolder(IContainer folder) throws CoreException {
- if (!folder.exists()) {
- createFolder(folder.getParent());
- ((IFolder) folder).create(true, true, null);
+private void createOutputFolder(IContainer outputFolder) throws CoreException {
+ createParentFolder(outputFolder.getParent());
+ ((IFolder) outputFolder).create(IResource.FORCE | IResource.DERIVED, true, null);
+}
+
+private void createParentFolder(IContainer parent) throws CoreException {
+ if (!parent.exists()) {
+ createParentFolder(parent.getParent());
+ ((IFolder) parent).create(true, true, null);
}
}
private NameEnvironmentAnswer findClass(String qualifiedTypeName, char[] typeName) {
- if (initialTypeNames != null) {
- // TODO (kent) should use a hash set to avoid linear search once massive source set is being processed
- for (int i = 0, l = initialTypeNames.length; i < l; i++) {
- if (qualifiedTypeName.equals(initialTypeNames[i])) {
- if (isIncrementalBuild)
- // catch the case that a type inside a source file has been renamed but other class files are looking for it
- throw new AbortCompilation(true, new AbortIncrementalBuildException(qualifiedTypeName));
- return null; // looking for a file which we know was provided at the beginning of the compilation
- }
- }
+ if (this.notifier != null)
+ this.notifier.checkCancelWithinCompiler();
+
+ if (this.initialTypeNames != null && this.initialTypeNames.includes(qualifiedTypeName)) {
+ if (isIncrementalBuild)
+ // catch the case that a type inside a source file has been renamed but other class files are looking for it
+ throw new AbortCompilation(true, new AbortIncrementalBuildException(qualifiedTypeName));
+ return null; // looking for a file which we know was provided at the beginning of the compilation
}
- if (additionalUnits != null && sourceLocations.length > 0) {
+ if (this.additionalUnits != null && this.sourceLocations.length > 0) {
// if an additional source file is waiting to be compiled, answer it BUT not if this is a secondary type search
// if we answer X.java & it no longer defines Y then the binary type looking for Y will think the class path is wrong
// let the recompile loop fix up dependents when the secondary type Y has been deleted from X.java
- IPath qSourceFilePath = new Path(qualifiedTypeName); // doesn't have file extension
- int qSegmentCount = qSourceFilePath.segmentCount();
- next : for (int i = 0, l = additionalUnits.length; i < l; i++) {
- SourceFile additionalUnit = additionalUnits[i];
- IPath fullPath = additionalUnit.resource.getFullPath();
- int prefixCount = additionalUnit.sourceLocation.sourceFolder.getFullPath().segmentCount();
- if (qSegmentCount == fullPath.segmentCount() - prefixCount) {
- for (int j = 0; j < qSegmentCount - 1; j++)
- if (!qSourceFilePath.segment(j).equals(fullPath.segment(j + prefixCount)))
- continue next;
- if (!Util.equalsIgnoreJavaLikeExtension(fullPath.segment(qSegmentCount-1 + prefixCount), qSourceFilePath.segment(qSegmentCount-1)))
- continue next;
- return new NameEnvironmentAnswer(additionalUnit, null /*no access restriction*/);
- }
- }
+ SourceFile unit = (SourceFile) this.additionalUnits.get(qualifiedTypeName); // doesn't have file extension
+ if (unit != null)
+ return new NameEnvironmentAnswer(unit, null /*no access restriction*/);
}
String qBinaryFileName = qualifiedTypeName + SUFFIX_STRING_class;
@@ -301,10 +290,21 @@
}
// NOTE: the output folders are added at the beginning of the binaryLocations
+ NameEnvironmentAnswer suggestedAnswer = null;
for (int i = 0, l = binaryLocations.length; i < l; i++) {
NameEnvironmentAnswer answer = binaryLocations[i].findClass(binaryFileName, qPackageName, qBinaryFileName);
- if (answer != null) return answer;
+ if (answer != null) {
+ if (!answer.ignoreIfBetter()) {
+ if (answer.isBetter(suggestedAnswer))
+ return answer;
+ } else if (answer.isBetter(suggestedAnswer))
+ // remember suggestion and keep looking
+ suggestedAnswer = answer;
+ }
}
+ if (suggestedAnswer != null)
+ // no better answer was found
+ return suggestedAnswer;
return null;
}
@@ -336,9 +336,27 @@
return false;
}
-void setNames(String[] initialTypeNames, SourceFile[] additionalUnits) {
- this.initialTypeNames = initialTypeNames;
- this.additionalUnits = additionalUnits;
+void setNames(String[] typeNames, SourceFile[] additionalFiles) {
+ // convert the initial typeNames to a set
+ if (typeNames == null) {
+ this.initialTypeNames = null;
+ } else {
+ this.initialTypeNames = new SimpleSet(typeNames.length);
+ for (int i = 0, l = typeNames.length; i < l; i++)
+ this.initialTypeNames.add(typeNames[i]);
+ }
+ // map the additional source files by qualified type name
+ if (additionalFiles == null) {
+ this.additionalUnits = null;
+ } else {
+ this.additionalUnits = new SimpleLookupTable(additionalFiles.length);
+ for (int i = 0, l = additionalFiles.length; i < l; i++) {
+ SourceFile additionalUnit = additionalFiles[i];
+ if (additionalUnit != null)
+ this.additionalUnits.put(additionalUnit.initialTypeName, additionalFiles[i]);
+ }
+ }
+
for (int i = 0, l = sourceLocations.length; i < l; i++)
sourceLocations[i].reset();
for (int i = 0, l = binaryLocations.length; i < l; i++)
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameSet.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameSet.java
index 590df26..bcc19d6 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameSet.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameSet.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ProblemFactory.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ProblemFactory.java
index 6f81509..da2281c 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ProblemFactory.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ProblemFactory.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/QualifiedNameSet.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/QualifiedNameSet.java
index 4ba3cf3..e7354be 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/QualifiedNameSet.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/QualifiedNameSet.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ReferenceCollection.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ReferenceCollection.java
index 3521aec..22e01e5 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ReferenceCollection.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ReferenceCollection.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Tim Hanson <thanson@bea.com> - fix for https://bugs.eclipse.org/bugs/show_bug.cgi?id=137634
*******************************************************************************/
package org.eclipse.jdt.internal.core.builder;
@@ -23,6 +24,36 @@
this.simpleNameReferences = internSimpleNames(simpleNameReferences, true);
}
+void addDependencies(String[] typeNameDependencies) {
+ // if each qualified type name is already known then all of its subNames can be skipped
+ // and its expected that very few qualified names in typeNameDependencies need to be added
+ // but could always take 'p1.p2.p3.X' and make all qualified names 'p1' 'p1.p2' 'p1.p2.p3' 'p1.p2.p3.X', then intern
+ char[][][] qNames = new char[typeNameDependencies.length][][];
+ for (int i = typeNameDependencies.length; --i >= 0;)
+ qNames[i] = CharOperation.splitOn('.', typeNameDependencies[i].toCharArray());
+ qNames = internQualifiedNames(qNames);
+
+ next : for (int i = qNames.length; --i >= 0;) {
+ char[][] qualifiedTypeName = qNames[i];
+ while (!includes(qualifiedTypeName)) {
+ if (!includes(qualifiedTypeName[qualifiedTypeName.length - 1])) {
+ int length = this.simpleNameReferences.length;
+ System.arraycopy(this.simpleNameReferences, 0, this.simpleNameReferences = new char[length + 1][], 0, length);
+ this.simpleNameReferences[length] = qualifiedTypeName[qualifiedTypeName.length - 1];
+ }
+ int length = this.qualifiedNameReferences.length;
+ System.arraycopy(this.qualifiedNameReferences, 0, this.qualifiedNameReferences = new char[length + 1][][], 0, length);
+ this.qualifiedNameReferences[length] = qualifiedTypeName;
+
+ qualifiedTypeName = CharOperation.subarray(qualifiedTypeName, 0, qualifiedTypeName.length - 1);
+ char[][][] temp = internQualifiedNames(new char[][][] {qualifiedTypeName});
+ if (temp == EmptyQualifiedNames)
+ continue next; // qualifiedTypeName is a well known name
+ qualifiedTypeName = temp[0];
+ }
+ }
+}
+
boolean includes(char[] simpleName) {
for (int i = 0, l = simpleNameReferences.length; i < l; i++)
if (simpleName == simpleNameReferences[i]) return true;
@@ -157,7 +188,7 @@
keepers[index++] = internedNames.add(qualifiedName);
}
if (length > index) {
- if (length == 0) return EmptyQualifiedNames;
+ if (index == 0) return EmptyQualifiedNames;
System.arraycopy(keepers, 0, keepers = new char[index][][], 0, index);
}
return keepers;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/SourceFile.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/SourceFile.java
index 61c27f8..f55e29d 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/SourceFile.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/SourceFile.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -21,7 +21,7 @@
public class SourceFile implements ICompilationUnit {
-IFile resource;
+public IFile resource;
ClasspathMultiDirectory sourceLocation;
String initialTypeName;
boolean updateClassFile;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java
index f3230c9..c5d7e48 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -18,6 +18,7 @@
import org.eclipse.jdt.internal.compiler.env.AccessRule;
import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
import org.eclipse.jdt.internal.core.ClasspathAccessRule;
+import org.eclipse.jdt.internal.core.JavaModelManager;
import java.io.*;
import java.util.*;
@@ -31,7 +32,7 @@
// keyed by the project relative path of the type (ie. "src1/p1/p2/A.java"), value is a ReferenceCollection or an AdditionalTypeCollection
SimpleLookupTable references;
// keyed by qualified type name "p1/p2/A", value is the project relative path which defines this type "src1/p1/p2/A.java"
-SimpleLookupTable typeLocators;
+public SimpleLookupTable typeLocators;
int buildNumber;
long lastStructuralBuildTime;
@@ -43,7 +44,7 @@
private StringSet structurallyChangedTypes;
public static int MaxStructurallyChangedTypes = 100; // keep track of ? structurally changed types, otherwise consider all to be changed
-public static final byte VERSION = 0x0013; // added timestamps to external jars
+public static final byte VERSION = 0x0015; // changed access rule presentation
static final byte SOURCE_FOLDER = 1;
static final byte BINARY_FOLDER = 2;
@@ -65,10 +66,17 @@
this.typeLocators = new SimpleLookupTable(7);
this.buildNumber = 0; // indicates a full build
- this.lastStructuralBuildTime = System.currentTimeMillis();
+ this.lastStructuralBuildTime = computeStructuralBuildTime(javaBuilder.lastState == null ? 0 : javaBuilder.lastState.lastStructuralBuildTime);
this.structuralBuildTimes = new SimpleLookupTable(3);
}
+long computeStructuralBuildTime(long previousTime) {
+ long newTime = System.currentTimeMillis();
+ if (newTime <= previousTime)
+ newTime = previousTime + 1;
+ return newTime;
+}
+
void copyFrom(State lastState) {
this.knownPackageNames = null;
this.previousStructuralBuildTime = lastState.previousStructuralBuildTime;
@@ -96,8 +104,7 @@
this.typeLocators.put(keyTable[i], valueTable[i]);
}
}
-
-char[][] getDefinedTypeNamesFor(String typeLocator) {
+public char[][] getDefinedTypeNamesFor(String typeLocator) {
Object c = references.get(typeLocator);
if (c instanceof AdditionalTypeCollection)
return ((AdditionalTypeCollection) c).definedTypeNames;
@@ -144,9 +151,13 @@
return false;
}
+boolean isKnownType(String qualifiedTypeName) {
+ return typeLocators.containsKey(qualifiedTypeName);
+}
+
void record(String typeLocator, char[][][] qualifiedRefs, char[][] simpleRefs, char[] mainTypeName, ArrayList typeNames) {
if (typeNames.size() == 1 && CharOperation.equals(mainTypeName, (char[]) typeNames.get(0))) {
- references.put(typeLocator, new ReferenceCollection(qualifiedRefs, simpleRefs));
+ references.put(typeLocator, new ReferenceCollection(qualifiedRefs, simpleRefs));
} else {
char[][] definedTypeNames = new char[typeNames.size()][]; // can be empty when no types are defined
typeNames.toArray(definedTypeNames);
@@ -316,7 +327,7 @@
private static char[][] readNames(DataInputStream in) throws IOException {
int length = in.readInt();
char[][] names = new char[length][];
- for (int i = 0; i < length; i++)
+ for (int i = 0; i < length; i++)
names[i] = readName(in);
return names;
}
@@ -330,9 +341,12 @@
int problemId = in.readInt();
accessRules[i] = new ClasspathAccessRule(pattern, problemId);
}
- String messageTemplate = in.readUTF();
- AccessRuleSet accessRuleSet = new AccessRuleSet(accessRules);
- accessRuleSet.messageTemplate = messageTemplate;
+ JavaModelManager manager = JavaModelManager.getJavaModelManager();
+ String[] messageTemplates = new String[AccessRuleSet.MESSAGE_TEMPLATES_LENGTH];
+ for (int i = 0; i < AccessRuleSet.MESSAGE_TEMPLATES_LENGTH; i++) {
+ messageTemplates[i] = manager.intern(in.readUTF());
+ }
+ AccessRuleSet accessRuleSet = new AccessRuleSet(accessRules, messageTemplates);
return accessRuleSet;
}
@@ -347,7 +361,7 @@
void tagAsStructurallyChanged() {
this.previousStructuralBuildTime = this.lastStructuralBuildTime;
this.structurallyChangedTypes = new StringSet(7);
- this.lastStructuralBuildTime = System.currentTimeMillis();
+ this.lastStructuralBuildTime = computeStructuralBuildTime(this.previousStructuralBuildTime);
}
boolean wasStructurallyChanged(IProject prereqProject, State prereqState) {
@@ -374,10 +388,10 @@
Object[] valueTable;
/*
- * byte VERSION
+ * byte VERSION
* String project name
- * int build number
- * int last structural build number
+ * int build number
+ * int last structural build number
*/
out.writeByte(VERSION);
out.writeUTF(javaProjectName);
@@ -386,7 +400,7 @@
/*
* ClasspathMultiDirectory[]
- * int id
+ * int id
* String path(s)
*/
out.writeInt(length = sourceLocations.length);
@@ -401,7 +415,7 @@
/*
* ClasspathLocation[]
- * int id
+ * int id
* String path(s)
*/
out.writeInt(length = binaryLocations.length);
@@ -438,7 +452,7 @@
/*
* Structural build numbers table
* String prereq project name
- * int last structural build number
+ * int last structural build number
*/
out.writeInt(length = structuralBuildTimes.elementSize);
if (length > 0) {
@@ -456,10 +470,10 @@
}
/*
- * String[] Interned type locators
+ * String[] Interned type locators
*/
out.writeInt(length = references.elementSize);
- ArrayList internedTypeLocators = new ArrayList(length);
+ SimpleLookupTable internedTypeLocators = new SimpleLookupTable(length);
if (length > 0) {
keyTable = references.keyTable;
for (int i = 0, l = keyTable.length; i < l; i++) {
@@ -467,7 +481,7 @@
length--;
String key = (String) keyTable[i];
out.writeUTF(key);
- internedTypeLocators.add(key);
+ internedTypeLocators.put(key, new Integer(internedTypeLocators.elementSize));
}
}
if (JavaBuilder.DEBUG && length != 0)
@@ -477,7 +491,7 @@
/*
* Type locators table
* String type name
- * int interned locator id
+ * int interned locator id
*/
out.writeInt(length = typeLocators.elementSize);
if (length > 0) {
@@ -487,7 +501,8 @@
if (keyTable[i] != null) {
length--;
out.writeUTF((String) keyTable[i]);
- out.writeInt(internedTypeLocators.indexOf(valueTable[i]));
+ Integer index = (Integer) internedTypeLocators.get(valueTable[i]);
+ out.writeInt(index.intValue());
}
}
if (JavaBuilder.DEBUG && length != 0)
@@ -496,10 +511,10 @@
/*
* char[][][] Interned qualified names
- * char[][] Interned simple names
+ * char[][] Interned simple names
*/
- ArrayList internedQualifiedNames = new ArrayList(31);
- ArrayList internedSimpleNames = new ArrayList(31);
+ SimpleLookupTable internedQualifiedNames = new SimpleLookupTable(31);
+ SimpleLookupTable internedSimpleNames = new SimpleLookupTable(31);
valueTable = references.valueTable;
for (int i = 0, l = valueTable.length; i < l; i++) {
if (valueTable[i] != null) {
@@ -507,39 +522,57 @@
char[][][] qNames = collection.qualifiedNameReferences;
for (int j = 0, m = qNames.length; j < m; j++) {
char[][] qName = qNames[j];
- if (!internedQualifiedNames.contains(qName)) { // remember the names have been interned
- internedQualifiedNames.add(qName);
+ if (!internedQualifiedNames.containsKey(qName)) { // remember the names have been interned
+ internedQualifiedNames.put(qName, new Integer(internedQualifiedNames.elementSize));
for (int k = 0, n = qName.length; k < n; k++) {
char[] sName = qName[k];
- if (!internedSimpleNames.contains(sName)) // remember the names have been interned
- internedSimpleNames.add(sName);
+ if (!internedSimpleNames.containsKey(sName)) // remember the names have been interned
+ internedSimpleNames.put(sName, new Integer(internedSimpleNames.elementSize));
}
}
}
char[][] sNames = collection.simpleNameReferences;
for (int j = 0, m = sNames.length; j < m; j++) {
char[] sName = sNames[j];
- if (!internedSimpleNames.contains(sName)) // remember the names have been interned
- internedSimpleNames.add(sName);
+ if (!internedSimpleNames.containsKey(sName)) // remember the names have been interned
+ internedSimpleNames.put(sName, new Integer(internedSimpleNames.elementSize));
}
}
}
- char[][] internedArray = new char[internedSimpleNames.size()][];
- internedSimpleNames.toArray(internedArray);
+ char[][] internedArray = new char[internedSimpleNames.elementSize][];
+ Object[] simpleNames = internedSimpleNames.keyTable;
+ Object[] positions = internedSimpleNames.valueTable;
+ for (int i = positions.length; --i >= 0; ) {
+ if (positions[i] != null) {
+ int index = ((Integer) positions[i]).intValue();
+ internedArray[index] = (char[]) simpleNames[i];
+ }
+ }
writeNames(internedArray, out);
// now write the interned qualified names as arrays of interned simple names
- out.writeInt(length = internedQualifiedNames.size());
+ char[][][] internedQArray = new char[internedQualifiedNames.elementSize][][];
+ Object[] qualifiedNames = internedQualifiedNames.keyTable;
+ positions = internedQualifiedNames.valueTable;
+ for (int i = positions.length; --i >= 0; ) {
+ if (positions[i] != null) {
+ int index = ((Integer) positions[i]).intValue();
+ internedQArray[index] = (char[][]) qualifiedNames[i];
+ }
+ }
+ out.writeInt(length = internedQArray.length);
for (int i = 0; i < length; i++) {
- char[][] qName = (char[][]) internedQualifiedNames.get(i);
+ char[][] qName = internedQArray[i];
int qLength = qName.length;
out.writeInt(qLength);
- for (int j = 0; j < qLength; j++)
- out.writeInt(internedSimpleNames.indexOf(qName[j]));
+ for (int j = 0; j < qLength; j++) {
+ Integer index = (Integer) internedSimpleNames.get(qName[j]);
+ out.writeInt(index.intValue());
+ }
}
/*
* References table
- * int interned locator id
+ * int interned locator id
* ReferenceCollection
*/
out.writeInt(length = references.elementSize);
@@ -548,7 +581,8 @@
for (int i = 0, l = keyTable.length; i < l; i++) {
if (keyTable[i] != null) {
length--;
- out.writeInt(internedTypeLocators.indexOf(keyTable[i]));
+ Integer index = (Integer) internedTypeLocators.get(keyTable[i]);
+ out.writeInt(index.intValue());
ReferenceCollection collection = (ReferenceCollection) valueTable[i];
if (collection instanceof AdditionalTypeCollection) {
out.writeByte(1);
@@ -560,13 +594,17 @@
char[][][] qNames = collection.qualifiedNameReferences;
int qLength = qNames.length;
out.writeInt(qLength);
- for (int j = 0; j < qLength; j++)
- out.writeInt(internedQualifiedNames.indexOf(qNames[j]));
+ for (int j = 0; j < qLength; j++) {
+ index = (Integer) internedQualifiedNames.get(qNames[j]);
+ out.writeInt(index.intValue());
+ }
char[][] sNames = collection.simpleNameReferences;
int sLength = sNames.length;
out.writeInt(sLength);
- for (int j = 0; j < sLength; j++)
- out.writeInt(internedSimpleNames.indexOf(sNames[j]));
+ for (int j = 0; j < sLength; j++) {
+ index = (Integer) internedSimpleNames.get(sNames[j]);
+ out.writeInt(index.intValue());
+ }
}
}
if (JavaBuilder.DEBUG && length != 0)
@@ -595,13 +633,14 @@
AccessRule[] accessRules = accessRuleSet.getAccessRules();
int length = accessRules.length;
out.writeInt(length);
- if (length != 0) {
+ if (length != 0) {
for (int i = 0; i < length; i++) {
AccessRule accessRule = accessRules[i];
writeName(accessRule.pattern, out);
out.writeInt(accessRule.problemId);
}
- out.writeUTF(accessRuleSet.messageTemplate);
+ for (int i = 0; i < AccessRuleSet.MESSAGE_TEMPLATES_LENGTH; i++)
+ out.writeUTF(accessRuleSet.messageTemplates[i]);
}
}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/StringSet.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/StringSet.java
index a5e0b70..0b70452 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/StringSet.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/StringSet.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/WorkQueue.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/WorkQueue.java
index 03427d9..f7897f3 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/WorkQueue.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/WorkQueue.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,7 +10,7 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core.builder;
-import org.eclipse.jdt.internal.core.util.SimpleSet;
+import org.eclipse.jdt.internal.compiler.util.SimpleSet;
public class WorkQueue {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/eval/EvaluationContextWrapper.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/eval/EvaluationContextWrapper.java
index f0656bf..f533a79 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/eval/EvaluationContextWrapper.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/eval/EvaluationContextWrapper.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -13,15 +13,11 @@
import java.util.Locale;
import java.util.Map;
-import org.eclipse.core.resources.IMarker;
-import org.eclipse.core.resources.ResourcesPlugin;
-import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.*;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IImportDeclaration;
import org.eclipse.jdt.core.IJavaElement;
-import org.eclipse.jdt.core.IJavaModelMarker;
import org.eclipse.jdt.core.IJavaModelStatusConstants;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IType;
@@ -276,6 +272,9 @@
protected INameEnvironment getBuildNameEnvironment() {
return new NameEnvironment(getProject());
}
+public char[] getVarClassName() {
+ return this.context.getVarClassName();
+}
/**
* @see org.eclipse.jdt.core.eval.IEvaluationContext#getImports()
@@ -392,21 +391,9 @@
requestor.acceptClass(packageName, className, completionName, modifiers, completionStart, completionEnd);
}
public void acceptError(IProblem error) {
- if (true) return; // was disabled in 1.0
-
- try {
- IMarker marker = ResourcesPlugin.getWorkspace().getRoot().createMarker(IJavaModelMarker.TRANSIENT_PROBLEM);
- marker.setAttribute(IJavaModelMarker.ID, error.getID());
- marker.setAttribute(IMarker.CHAR_START, error.getSourceStart());
- marker.setAttribute(IMarker.CHAR_END, error.getSourceEnd() + 1);
- marker.setAttribute(IMarker.LINE_NUMBER, error.getSourceLineNumber());
- marker.setAttribute(IMarker.MESSAGE, error.getMessage());
- marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
- requestor.acceptError(marker);
- } catch(CoreException e){
- // ignore
- }
+ // was disabled in 1.0
}
+
public void acceptField(char[] declaringTypePackageName, char[] declaringTypeName, char[] name, char[] typePackageName, char[] typeName, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) {
requestor.acceptField(declaringTypePackageName, declaringTypeName, name, typePackageName, typeName, completionName, modifiers, completionStart, completionEnd);
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/eval/GlobalVariableWrapper.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/eval/GlobalVariableWrapper.java
index 39c5bff..939d078 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/eval/GlobalVariableWrapper.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/eval/GlobalVariableWrapper.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/eval/RequestorWrapper.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/eval/RequestorWrapper.java
index bcdee8d..77f26d4 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/eval/RequestorWrapper.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/eval/RequestorWrapper.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -14,13 +14,16 @@
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.IJavaModelMarker;
-import org.eclipse.jdt.core.compiler.IProblem;
+import org.eclipse.jdt.core.compiler.CategorizedProblem;
import org.eclipse.jdt.core.eval.ICodeSnippetRequestor;
import org.eclipse.jdt.internal.compiler.ClassFile;
+import org.eclipse.jdt.internal.core.builder.JavaBuilder;
import org.eclipse.jdt.internal.eval.IRequestor;
public class RequestorWrapper implements IRequestor {
+
ICodeSnippetRequestor requestor;
+
public RequestorWrapper(ICodeSnippetRequestor requestor) {
this.requestor = requestor;
}
@@ -47,7 +50,7 @@
/**
* @see ICodeSnippetRequestor
*/
-public void acceptProblem(IProblem problem, char[] fragmentSource, int fragmentKind) {
+public void acceptProblem(CategorizedProblem problem, char[] fragmentSource, int fragmentKind) {
try {
IMarker marker = ResourcesPlugin.getWorkspace().getRoot().createMarker(IJavaModelMarker.TRANSIENT_PROBLEM);
marker.setAttribute(IJavaModelMarker.ID, problem.getID());
@@ -57,6 +60,7 @@
//marker.setAttribute(IMarker.LOCATION, "#" + problem.getSourceLineNumber());
marker.setAttribute(IMarker.MESSAGE, problem.getMessage());
marker.setAttribute(IMarker.SEVERITY, (problem.isWarning() ? IMarker.SEVERITY_WARNING : IMarker.SEVERITY_ERROR));
+ marker.setAttribute(IMarker.SOURCE_ID, JavaBuilder.SOURCE_ID);
this.requestor.acceptProblem(marker, new String(fragmentSource), fragmentKind);
} catch (CoreException e) {
e.printStackTrace();
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/ChangeCollector.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/ChangeCollector.java
index c960f20..20786c0 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/ChangeCollector.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/ChangeCollector.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBinaryType.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBinaryType.java
index 4bb296e..7b61e06 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBinaryType.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBinaryType.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -12,17 +12,18 @@
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation;
import org.eclipse.jdt.internal.compiler.env.IBinaryField;
import org.eclipse.jdt.internal.compiler.env.IBinaryMethod;
import org.eclipse.jdt.internal.compiler.env.IBinaryNestedType;
import org.eclipse.jdt.internal.compiler.env.IBinaryType;
-import org.eclipse.jdt.internal.compiler.env.IConstants;
-import org.eclipse.jdt.internal.compiler.env.IGenericType;
import org.eclipse.jdt.internal.core.search.indexing.IIndexConstants;
public class HierarchyBinaryType implements IBinaryType {
private int modifiers;
- private int kind;
+ private char[] sourceName;
private char[] name;
private char[] enclosingTypeName;
private char[] superclass;
@@ -30,27 +31,14 @@
private char[][] typeParameterSignatures;
private char[] genericSignature;
-public HierarchyBinaryType(int modifiers, char[] qualification, char[] typeName, char[] enclosingTypeName, char[][] typeParameterSignatures, char typeSuffix){
+public HierarchyBinaryType(int modifiers, char[] qualification, char[] sourceName, char[] enclosingTypeName, char[][] typeParameterSignatures, char typeSuffix){
this.modifiers = modifiers;
- switch(typeSuffix) {
- case IIndexConstants.CLASS_SUFFIX :
- this.kind = IGenericType.CLASS_DECL;
- break;
- case IIndexConstants.INTERFACE_SUFFIX :
- this.kind = IGenericType.INTERFACE_DECL;
- break;
- case IIndexConstants.ENUM_SUFFIX :
- this.kind = IGenericType.ENUM_DECL;
- break;
- case IIndexConstants.ANNOTATION_TYPE_SUFFIX :
- this.kind = IGenericType.ANNOTATION_TYPE_DECL;
- break;
- }
+ this.sourceName = sourceName;
if (enclosingTypeName == null){
- this.name = CharOperation.concat(qualification, typeName, '/');
+ this.name = CharOperation.concat(qualification, sourceName, '/');
} else {
- this.name = CharOperation.concat(qualification, '/', enclosingTypeName, '$', typeName); //rebuild A$B name
+ this.name = CharOperation.concat(qualification, '/', enclosingTypeName, '$', sourceName); //rebuild A$B name
this.enclosingTypeName = CharOperation.concat(qualification, enclosingTypeName,'/');
CharOperation.replace(this.enclosingTypeName, '.', '/');
}
@@ -100,12 +88,6 @@
return this.genericSignature;
}
/**
- * @see org.eclipse.jdt.internal.compiler.env.IGenericType#getKind()
- */
-public int getKind() {
- return this.kind;
-}
-/**
* Answer the resolved names of the receiver's interfaces in the
* class file format as specified in section 4.2 of the Java 2 VM spec
* or null if the array is empty.
@@ -146,6 +128,11 @@
public char[] getName() {
return this.name;
}
+
+public char[] getSourceName() {
+ return this.sourceName;
+}
+
/**
* Answer the resolved name of the receiver's superclass in the
* class file format as specified in section 4.2 of the Java 2 VM spec
@@ -189,7 +176,7 @@
if (superClassOrInterface == IIndexConstants.CLASS_SUFFIX){
// interfaces are indexed as having superclass references to Object by default,
// this is an artifact used for being able to query them only.
- if (this.kind == IGenericType.INTERFACE_DECL) return;
+ if (TypeDeclaration.kind(this.modifiers) == TypeDeclaration.INTERFACE_DECL) return;
char[] encodedName = CharOperation.concat(superQualification, superTypeName, '/');
CharOperation.replace(encodedName, '.', '/');
this.superclass = encodedName;
@@ -207,17 +194,17 @@
}
public String toString() {
StringBuffer buffer = new StringBuffer();
- if (this.modifiers == IConstants.AccPublic) {
+ if (this.modifiers == ClassFileConstants.AccPublic) {
buffer.append("public "); //$NON-NLS-1$
}
- switch (this.kind) {
- case IGenericType.CLASS_DECL :
+ switch (TypeDeclaration.kind(this.modifiers)) {
+ case TypeDeclaration.CLASS_DECL :
buffer.append("class "); //$NON-NLS-1$
break;
- case IGenericType.INTERFACE_DECL :
+ case TypeDeclaration.INTERFACE_DECL :
buffer.append("interface "); //$NON-NLS-1$
break;
- case IGenericType.ENUM_DECL :
+ case TypeDeclaration.ENUM_DECL :
buffer.append("enum "); //$NON-NLS-1$
break;
}
@@ -244,6 +231,13 @@
/**
* @see org.eclipse.jdt.internal.compiler.env.IBinaryType
*/
+public IBinaryAnnotation[] getAnnotations() {
+ return null;
+}
+
+/**
+ * @see org.eclipse.jdt.internal.compiler.env.IBinaryType
+ */
public char[] sourceFileName() {
return null;
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBuilder.java
index 90bf5d0..6902412 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBuilder.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -13,27 +13,21 @@
import java.util.HashMap;
import java.util.Map;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.env.IBinaryType;
import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
import org.eclipse.jdt.internal.compiler.env.IGenericType;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
import org.eclipse.jdt.internal.core.*;
-import org.eclipse.jdt.internal.core.BasicCompilationUnit;
-import org.eclipse.jdt.internal.core.ClassFile;
-import org.eclipse.jdt.internal.core.JarPackageFragmentRoot;
-import org.eclipse.jdt.internal.core.JavaElement;
-import org.eclipse.jdt.internal.core.JavaModelManager;
-import org.eclipse.jdt.internal.core.JavaProject;
-import org.eclipse.jdt.internal.core.NameLookup;
-import org.eclipse.jdt.internal.core.Openable;
-import org.eclipse.jdt.internal.core.SearchableEnvironment;
-import org.eclipse.jdt.internal.core.SourceTypeElementInfo;
+import org.eclipse.jdt.internal.core.util.ResourceCompilationUnit;
import org.eclipse.jdt.internal.core.util.Util;
public abstract class HierarchyBuilder {
@@ -83,14 +77,16 @@
} else {
unitsToLookInside = workingCopies;
}
- SearchableEnvironment searchableEnvironment = project.newSearchableNameEnvironment(unitsToLookInside);
- this.nameLookup = searchableEnvironment.nameLookup;
- this.hierarchyResolver =
- new HierarchyResolver(
- searchableEnvironment,
- project.getOptions(true),
- this,
- new DefaultProblemFactory());
+ if (project != null) {
+ SearchableEnvironment searchableEnvironment = project.newSearchableNameEnvironment(unitsToLookInside);
+ this.nameLookup = searchableEnvironment.nameLookup;
+ this.hierarchyResolver =
+ new HierarchyResolver(
+ searchableEnvironment,
+ project.getOptions(true),
+ this,
+ new DefaultProblemFactory());
+ }
this.infoToHandle = new HashMap(5);
this.focusQualifiedName = focusType == null ? null : focusType.getFullyQualifiedName();
}
@@ -160,17 +156,17 @@
}
}
// now do the caching
- switch (type.getKind()) {
- case IGenericType.CLASS_DECL :
- case IGenericType.ENUM_DECL :
+ switch (TypeDeclaration.kind(type.getModifiers())) {
+ case TypeDeclaration.CLASS_DECL :
+ case TypeDeclaration.ENUM_DECL :
if (superclassHandle == null) {
this.hierarchy.addRootClass(typeHandle);
} else {
this.hierarchy.cacheSuperclass(typeHandle, superclassHandle);
}
break;
- case IGenericType.INTERFACE_DECL :
- case IGenericType.ANNOTATION_TYPE_DECL :
+ case TypeDeclaration.INTERFACE_DECL :
+ case TypeDeclaration.ANNOTATION_TYPE_DECL :
this.hierarchy.addInterface(typeHandle);
break;
}
@@ -224,14 +220,14 @@
protected IType lookupBinaryHandle(IBinaryType typeInfo) {
int flag;
String qualifiedName;
- switch (typeInfo.getKind()) {
- case IGenericType.CLASS_DECL :
+ switch (TypeDeclaration.kind(typeInfo.getModifiers())) {
+ case TypeDeclaration.CLASS_DECL :
flag = NameLookup.ACCEPT_CLASSES;
break;
- case IGenericType.INTERFACE_DECL :
+ case TypeDeclaration.INTERFACE_DECL :
flag = NameLookup.ACCEPT_INTERFACES;
break;
- case IGenericType.ENUM_DECL :
+ case TypeDeclaration.ENUM_DECL :
flag = NameLookup.ACCEPT_ENUMS;
break;
default:
@@ -242,7 +238,15 @@
char[] bName = typeInfo.getName();
qualifiedName = new String(ClassFile.translatedName(bName));
if (qualifiedName.equals(this.focusQualifiedName)) return getType();
- return this.nameLookup.findType(qualifiedName, false, flag);
+ NameLookup.Answer answer = this.nameLookup.findType(qualifiedName,
+ false,
+ flag,
+ true/* consider secondary types */,
+ false/* do NOT wait for indexes */,
+ false/*don't check restrictions*/,
+ null);
+ return answer == null || answer.type == null || !answer.type.isBinary() ? null : answer.type;
+
}
protected void worked(IProgressMonitor monitor, int work) {
if (monitor != null) {
@@ -256,9 +260,9 @@
/**
* Create an ICompilationUnit info from the given compilation unit on disk.
*/
-protected ICompilationUnit createCompilationUnitFromPath(Openable handle, String osPath) {
+protected ICompilationUnit createCompilationUnitFromPath(Openable handle, IFile file) {
final char[] elementName = handle.getElementName().toCharArray();
- return new BasicCompilationUnit(null/* no source*/, null/* no package */, osPath, handle) {
+ return new ResourceCompilationUnit(file, file.getLocationURI()) {
public char[] getFileName() {
return elementName;
}
@@ -268,10 +272,10 @@
* Creates the type info from the given class file on disk and
* adds it to the given list of infos.
*/
-protected IBinaryType createInfoFromClassFile(Openable handle, String osPath) {
+protected IBinaryType createInfoFromClassFile(Openable handle, IResource file) {
IBinaryType info = null;
try {
- info = org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader.read(osPath);
+ info = Util.newClassFileReader(file);
} catch (org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException e) {
if (TypeHierarchy.DEBUG) {
e.printStackTrace();
@@ -282,6 +286,11 @@
e.printStackTrace();
}
return null;
+ } catch (CoreException e) {
+ if (TypeHierarchy.DEBUG) {
+ e.printStackTrace();
+ }
+ return null;
}
this.infoToHandle.put(info, handle);
return info;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java
index da7f0c4..b79754b 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -27,6 +27,7 @@
import java.util.HashSet;
import java.util.Map;
+import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
@@ -40,9 +41,6 @@
import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy;
import org.eclipse.jdt.internal.compiler.IProblemFactory;
import org.eclipse.jdt.internal.compiler.ast.*;
-import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
import org.eclipse.jdt.internal.compiler.env.IBinaryType;
import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
@@ -52,18 +50,12 @@
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.impl.ITypeRequestor;
import org.eclipse.jdt.internal.compiler.lookup.*;
-import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding;
-import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
-import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
-import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
-import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
import org.eclipse.jdt.internal.compiler.parser.Parser;
import org.eclipse.jdt.internal.compiler.parser.SourceTypeConverter;
import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
import org.eclipse.jdt.internal.compiler.util.Messages;
import org.eclipse.jdt.internal.core.*;
-import org.eclipse.jdt.internal.core.Member;
import org.eclipse.jdt.internal.core.util.ASTNodeFinder;
import org.eclipse.jdt.internal.core.util.HandleFactory;
@@ -100,6 +92,10 @@
* @param packageBinding
*/
public void accept(IBinaryType binaryType, PackageBinding packageBinding, AccessRestriction accessRestriction) {
+ IProgressMonitor progressMonitor = this.builder.hierarchy.progressMonitor;
+ if (progressMonitor != null && progressMonitor.isCanceled())
+ throw new OperationCanceledException();
+
BinaryTypeBinding typeBinding = this.lookupEnvironment.createBinaryTypeFrom(binaryType, packageBinding, accessRestriction);
try {
this.remember(binaryType, typeBinding);
@@ -126,6 +122,10 @@
* @param packageBinding
*/
public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding, AccessRestriction accessRestriction) {
+ IProgressMonitor progressMonitor = this.builder.hierarchy.progressMonitor;
+ if (progressMonitor != null && progressMonitor.isCanceled())
+ throw new OperationCanceledException();
+
// find most enclosing type first (needed when explicit askForType(...) is done
// with a member type (e.g. p.A$B))
ISourceType sourceType = sourceTypes[0];
@@ -163,32 +163,39 @@
*/
private IType findSuperClass(IGenericType type, ReferenceBinding typeBinding) {
ReferenceBinding superBinding = typeBinding.superclass();
+
if (superBinding != null) {
superBinding = (ReferenceBinding) superBinding.erasure();
- if (superBinding.id == TypeIds.T_JavaLangObject && typeBinding.isHierarchyInconsistent()) {
- char[] superclassName;
- char separator;
- if (type instanceof IBinaryType) {
- superclassName = ((IBinaryType)type).getSuperclassName();
- separator = '/';
- } else if (type instanceof ISourceType) {
- superclassName = ((ISourceType)type).getSuperclassName();
- separator = '.';
- } else if (type instanceof HierarchyType) {
- superclassName = ((HierarchyType)type).superclassName;
- separator = '.';
- } else {
+ if (typeBinding.isHierarchyInconsistent()) {
+ if (superBinding.problemId() == ProblemReasons.NotFound) {
+ this.hasMissingSuperClass = true;
+ this.builder.hierarchy.missingTypes.add(new String(superBinding.sourceName)); // note: this could be Map$Entry
return null;
- }
-
- if (superclassName != null) { // check whether subclass of Object due to broken hierarchy (as opposed to explicitly extending it)
- int lastSeparator = CharOperation.lastIndexOf(separator, superclassName);
- char[] simpleName = lastSeparator == -1 ? superclassName : CharOperation.subarray(superclassName, lastSeparator+1, superclassName.length);
- if (!CharOperation.equals(simpleName, TypeConstants.OBJECT)) {
- this.hasMissingSuperClass = true;
- this.builder.hierarchy.missingTypes.add(new String(simpleName));
+ } else if ((superBinding.id == TypeIds.T_JavaLangObject)) {
+ char[] superclassName;
+ char separator;
+ if (type instanceof IBinaryType) {
+ superclassName = ((IBinaryType)type).getSuperclassName();
+ separator = '/';
+ } else if (type instanceof ISourceType) {
+ superclassName = ((ISourceType)type).getSuperclassName();
+ separator = '.';
+ } else if (type instanceof HierarchyType) {
+ superclassName = ((HierarchyType)type).superclassName;
+ separator = '.';
+ } else {
return null;
}
+
+ if (superclassName != null) { // check whether subclass of Object due to broken hierarchy (as opposed to explicitly extending it)
+ int lastSeparator = CharOperation.lastIndexOf(separator, superclassName);
+ char[] simpleName = lastSeparator == -1 ? superclassName : CharOperation.subarray(superclassName, lastSeparator+1, superclassName.length);
+ if (!CharOperation.equals(simpleName, TypeConstants.OBJECT)) {
+ this.hasMissingSuperClass = true;
+ this.builder.hierarchy.missingTypes.add(new String(simpleName));
+ return null;
+ }
+ }
}
}
for (int t = this.typeIndex; t >= 0; t--) {
@@ -218,7 +225,7 @@
superInterfaceNames = sourceType.getInterfaceNames();
}
} else {
- if (sourceType.getKind() == IGenericType.ANNOTATION_TYPE_DECL)
+ if (TypeDeclaration.kind(sourceType.getModifiers()) == TypeDeclaration.ANNOTATION_TYPE_DECL)
superInterfaceNames = new char[][] {TypeConstants.CharArray_JAVA_LANG_ANNOTATION_ANNOTATION};
else
superInterfaceNames = sourceType.getInterfaceNames();
@@ -240,7 +247,7 @@
return null;
}
- ReferenceBinding[] interfaceBindings = typeBinding.superInterfaces();
+ ReferenceBinding[] interfaceBindings = typeBinding.superInterfaces();
int bindingIndex = 0;
int bindingLength = interfaceBindings == null ? 0 : interfaceBindings.length;
int length = superInterfaceNames == null ? 0 : superInterfaceNames.length;
@@ -248,18 +255,20 @@
int index = 0;
next : for (int i = 0; i < length; i++) {
char[] superInterfaceName = superInterfaceNames[i];
- int lastSeparator = CharOperation.lastIndexOf(separator, superInterfaceName);
- int start = lastSeparator + 1;
int end = superInterfaceName.length;
+ // find the end of simple name
+ int genericStart = CharOperation.indexOf(Signature.C_GENERIC_START, superInterfaceName);
+ if (genericStart != -1) end = genericStart;
+
+ // find the start of simple name
+ int lastSeparator = CharOperation.lastIndexOf(separator, superInterfaceName, 0, end);
+ int start = lastSeparator + 1;
+
// case of binary inner type -> take the last part
int lastDollar = CharOperation.lastIndexOf('$', superInterfaceName, start);
if (lastDollar != -1) start = lastDollar + 1;
- // case of a parameterized type -> take the first part
- int genericStart = CharOperation.indexOf(Signature.C_GENERIC_START, superInterfaceName, start);
- if (genericStart != -1) end = genericStart;
-
char[] simpleName = CharOperation.subarray(superInterfaceName, start, end);
if (bindingIndex < bindingLength) {
@@ -282,6 +291,59 @@
System.arraycopy(superinterfaces, 0, superinterfaces = new IType[index], 0, index);
return superinterfaces;
}
+private void fixSupertypeBindings() {
+ for (int current = this.typeIndex; current >= 0; current--) {
+ ReferenceBinding typeBinding = this.typeBindings[current];
+
+
+ if (typeBinding instanceof SourceTypeBinding) {
+ ClassScope scope = ((SourceTypeBinding) typeBinding).scope;
+ if (scope != null) {
+ TypeDeclaration typeDeclaration = scope.referenceContext;
+ TypeReference superclassRef = typeDeclaration == null ? null : typeDeclaration.superclass;
+ TypeBinding superclass = superclassRef == null ? null : superclassRef.resolvedType;
+ if (superclass instanceof ProblemReferenceBinding) {
+ superclass = ((ProblemReferenceBinding) superclass).closestMatch();
+ }
+ if (superclass != null)
+ ((SourceTypeBinding) typeBinding).superclass = (ReferenceBinding) superclass;
+
+ TypeReference[] superInterfaces = typeDeclaration == null ? null : typeDeclaration.superInterfaces;
+ int length;
+ ReferenceBinding[] interfaceBindings = typeBinding.superInterfaces();
+ if (superInterfaces != null && (length = superInterfaces.length) > (interfaceBindings == null ? 0 : interfaceBindings.length)) { // check for interfaceBindings being null (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=139689)
+ interfaceBindings = new ReferenceBinding[length];
+ int index = 0;
+ for (int i = 0; i < length; i++) {
+ ReferenceBinding superInterface = (ReferenceBinding) superInterfaces[i].resolvedType;
+ if (superInterface instanceof ProblemReferenceBinding)
+ superInterface = superInterface.closestMatch();
+ if (superInterface != null)
+ interfaceBindings[index++] = superInterface;
+ }
+ if (index < length)
+ System.arraycopy(interfaceBindings, 0, interfaceBindings = new ReferenceBinding[index], 0 , index);
+ ((SourceTypeBinding) typeBinding).superInterfaces = interfaceBindings;
+ }
+ }
+ } else if (typeBinding instanceof BinaryTypeBinding) {
+ try {
+ typeBinding.superclass();
+ } catch (AbortCompilation e) {
+ // allow subsequent call to superclass() to succeed so that we don't have to catch AbortCompilation everywhere
+ ((BinaryTypeBinding) typeBinding).tagBits &= ~TagBits.HasUnresolvedSuperclass;
+ this.builder.hierarchy.missingTypes.add(new String(typeBinding.superclass().sourceName()));
+ this.hasMissingSuperClass = true;
+ }
+ try {
+ typeBinding.superInterfaces();
+ } catch (AbortCompilation e) {
+ // allow subsequent call to superInterfaces() to succeed so that we don't have to catch AbortCompilation everywhere
+ ((BinaryTypeBinding) typeBinding).tagBits &= ~TagBits.HasUnresolvedSuperinterfaces;
+ }
+ }
+ }
+}
private void remember(IGenericType suppliedType, ReferenceBinding typeBinding) {
if (typeBinding == null) return;
@@ -309,7 +371,7 @@
// simple super class name
char[] superclassName = null;
TypeReference superclass;
- if ((typeDeclaration.bits & ASTNode.IsAnonymousTypeMASK) != 0) {
+ if ((typeDeclaration.bits & ASTNode.IsAnonymousType) != 0) {
superclass = typeDeclaration.allocation.type;
} else {
superclass = typeDeclaration.superclass;
@@ -334,7 +396,6 @@
HierarchyType hierarchyType = new HierarchyType(
type,
- typeDeclaration.kind(),
typeDeclaration.name,
typeDeclaration.binding.modifiers,
superclassName,
@@ -408,6 +469,9 @@
}
}
+ // be resilient and fix super type bindings
+ fixSupertypeBindings();
+
int objectIndex = -1;
for (int current = this.typeIndex; current >= 0; current--) {
ReferenceBinding typeBinding = this.typeBindings[current];
@@ -459,7 +523,7 @@
public void resolve(IGenericType suppliedType) {
try {
if (suppliedType.isBinaryType()) {
- BinaryTypeBinding binaryTypeBinding = this.lookupEnvironment.cacheBinaryType((IBinaryType) suppliedType, null /*no access restriction*/);
+ BinaryTypeBinding binaryTypeBinding = this.lookupEnvironment.cacheBinaryType((IBinaryType) suppliedType, false/*don't need field and method (bug 125067)*/, null /*no access restriction*/);
remember(suppliedType, binaryTypeBinding);
// We still need to add superclasses and superinterfaces bindings (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=53095)
int startIndex = this.typeIndex;
@@ -570,9 +634,8 @@
if (containsLocalType) parsedUnit.bits |= ASTNode.HasAllMethodBodies;
} else {
// create parsed unit from file
- IResource file = cu.getResource();
- String osPath = file.getLocation().toOSString();
- ICompilationUnit sourceUnit = this.builder.createCompilationUnitFromPath(openable, osPath);
+ IFile file = (IFile) cu.getResource();
+ ICompilationUnit sourceUnit = this.builder.createCompilationUnitFromPath(openable, file);
CompilationResult unitResult = new CompilationResult(sourceUnit, i, openablesLength, this.options.maxProblemsPerUnit);
parsedUnit = parser.dietParse(sourceUnit, unitResult);
@@ -609,13 +672,12 @@
binaryType = this.builder.createInfoFromClassFileInJar(classFile);
} else {
IResource file = classFile.getResource();
- String osPath = file.getLocation().toOSString();
- binaryType = this.builder.createInfoFromClassFile(classFile, osPath);
+ binaryType = this.builder.createInfoFromClassFile(classFile, file);
}
}
if (binaryType != null) {
try {
- BinaryTypeBinding binaryTypeBinding = this.lookupEnvironment.cacheBinaryType(binaryType, null /*no access restriction*/);
+ BinaryTypeBinding binaryTypeBinding = this.lookupEnvironment.cacheBinaryType(binaryType, false/*don't need field and method (bug 125067)*/, null /*no access restriction*/);
remember(binaryType, binaryTypeBinding);
if (openable.equals(focusOpenable)) {
focusBinaryBinding = binaryTypeBinding;
@@ -650,7 +712,10 @@
if (containsLocalType) { // NB: no-op if method bodies have been already parsed
parser.getMethodBodies(parsedUnit);
}
- this.lookupEnvironment.completeTypeBindings(parsedUnit, true/*build constructor only*/);
+ // complete type bindings and build fields and methods only for local types
+ // (in this case the constructor is needed when resolving local types)
+ // (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=145333)
+ this.lookupEnvironment.completeTypeBindings(parsedUnit, containsLocalType);
} catch (AbortCompilation e) {
// classpath problem for this type: don't try to resolve (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=49809)
hasLocalType[i] = false;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyType.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyType.java
index 1ba6b06..11e668e 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyType.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyType.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -21,7 +21,6 @@
public class HierarchyType implements IGenericType {
public IType typeHandle;
- public int kind;
public char[] name;
public int modifiers;
public char[] superclassName;
@@ -29,14 +28,12 @@
public HierarchyType(
IType typeHandle,
- int kind,
char[] name,
int modifiers,
char[] superclassName,
char[][] superInterfaceNames) {
this.typeHandle = typeHandle;
- this.kind = kind;
this.name = name;
this.modifiers = modifiers;
this.superclassName = superclassName;
@@ -48,12 +45,7 @@
public char[] getFileName() {
return this.typeHandle.getCompilationUnit().getElementName().toCharArray();
}
-/**
- * @see org.eclipse.jdt.internal.compiler.env.IGenericType#getKind()
- */
-public int getKind() {
- return this.kind;
-}
+
/**
* Answer an int whose bits are set according the access constants
* defined by the VM spec.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/IndexBasedHierarchyBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/IndexBasedHierarchyBuilder.java
index 2fed303..7355ef1 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/IndexBasedHierarchyBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/IndexBasedHierarchyBuilder.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -12,8 +12,11 @@
import java.util.*;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jdt.core.*;
import org.eclipse.jdt.core.compiler.CharOperation;
@@ -23,6 +26,7 @@
import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
+import org.eclipse.jdt.internal.compiler.util.HashtableOfObjectToInt;
import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
import org.eclipse.jdt.internal.core.*;
import org.eclipse.jdt.internal.core.search.IndexQueryRequestor;
@@ -33,6 +37,7 @@
import org.eclipse.jdt.internal.core.search.matching.MatchLocator;
import org.eclipse.jdt.internal.core.search.matching.SuperTypeReferencePattern;
import org.eclipse.jdt.internal.core.util.HandleFactory;
+import org.eclipse.jdt.internal.core.util.Util;
public class IndexBasedHierarchyBuilder extends HierarchyBuilder implements SuffixConstants {
public static final int MAXTICKS = 800; // heuristic so that there still progress for deep hierachies
@@ -43,10 +48,6 @@
* the region).
*/
protected Map cuToHandle;
- /**
- * A map from compilation unit handles to working copies.
- */
- protected Map handleToWorkingCopy;
/**
* The scope this hierarchy builder should restrain results to.
@@ -61,7 +62,7 @@
/**
* Collection used to queue subtype index queries
*/
- private static class Queue {
+ static class Queue {
public char[][] names = new char[10][];
public int start = 0;
public int end = -1;
@@ -119,7 +120,7 @@
allPossibleSubtypes = this.determinePossibleSubTypes(localTypes, possibleSubtypesMonitor);
} else {
// local or anonymous type
- allPossibleSubtypes = new String[0];
+ allPossibleSubtypes = CharOperation.NO_STRINGS;
}
if (allPossibleSubtypes != null) {
IProgressMonitor buildMonitor =
@@ -138,13 +139,38 @@
}
}
private void buildForProject(JavaProject project, ArrayList potentialSubtypes, org.eclipse.jdt.core.ICompilationUnit[] workingCopies, HashSet localTypes, IProgressMonitor monitor) throws JavaModelException {
- // copy vectors into arrays
- int openablesLength = potentialSubtypes.size();
- Openable[] openables = new Openable[openablesLength];
- potentialSubtypes.toArray(openables);
-
// resolve
+ int openablesLength = potentialSubtypes.size();
if (openablesLength > 0) {
+ // copy vectors into arrays
+ Openable[] openables = new Openable[openablesLength];
+ potentialSubtypes.toArray(openables);
+
+ // sort in the order of roots and in reverse alphabetical order for .class file
+ // since requesting top level types in the process of caching an enclosing type is
+ // not supported by the lookup environment
+ IPackageFragmentRoot[] roots = project.getPackageFragmentRoots();
+ int rootsLength = roots.length;
+ final HashtableOfObjectToInt indexes = new HashtableOfObjectToInt(openablesLength);
+ for (int i = 0; i < openablesLength; i++) {
+ IJavaElement root = openables[i].getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
+ int index;
+ for (index = 0; index < rootsLength; index++) {
+ if (roots[index].equals(root))
+ break;
+ }
+ indexes.put(openables[i], index);
+ }
+ Arrays.sort(openables, new Comparator() {
+ public int compare(Object a, Object b) {
+ int aIndex = indexes.get(a);
+ int bIndex = indexes.get(b);
+ if (aIndex != bIndex)
+ return aIndex - bIndex;
+ return ((Openable) b).getElementName().compareTo(((Openable) a).getElementName());
+ }
+ });
+
IType focusType = this.getType();
boolean inProjectOfFocusType = focusType != null && focusType.getJavaProject().equals(project);
org.eclipse.jdt.core.ICompilationUnit[] unitsToLookInside = null;
@@ -175,10 +201,13 @@
Member declaringMember = ((Member)focusType).getOuterMostLocalContext();
if (declaringMember == null) {
// top level or member type
- char[] fullyQualifiedName = focusType.getFullyQualifiedName().toCharArray();
- if (!inProjectOfFocusType && searchableEnvironment.findType(CharOperation.splitOn('.', fullyQualifiedName)) == null) {
- // focus type is not visible in this project: no need to go further
- return;
+ if (!inProjectOfFocusType) {
+ char[] typeQualifiedName = focusType.getTypeQualifiedName('.').toCharArray();
+ String[] packageName = ((PackageFragment) focusType.getPackageFragment()).names;
+ if (searchableEnvironment.findType(typeQualifiedName, Util.toCharArrays(packageName)) == null) {
+ // focus type is not visible in this project: no need to go further
+ return;
+ }
}
} else {
// local or anonymous type
@@ -238,17 +267,12 @@
length++;
}
- // sort by projects
/*
- * NOTE: To workaround pb with hierarchy resolver that requests top
- * level types in the process of caching an enclosing type, this needs to
- * be sorted in reverse alphabetical order so that top level types are cached
- * before their inner types.
+ * Sort in alphabetical order so that potential subtypes are grouped per project
*/
- org.eclipse.jdt.internal.core.util.Util.sortReverseOrder(allPotentialSubTypes);
-
- ArrayList potentialSubtypes = new ArrayList();
+ Arrays.sort(allPotentialSubTypes);
+ ArrayList potentialSubtypes = new ArrayList();
try {
// create element infos for subtypes
HandleFactory factory = new HandleFactory();
@@ -330,19 +354,19 @@
if (monitor != null) monitor.done();
}
}
-protected ICompilationUnit createCompilationUnitFromPath(Openable handle, String osPath) {
- ICompilationUnit unit = super.createCompilationUnitFromPath(handle, osPath);
+protected ICompilationUnit createCompilationUnitFromPath(Openable handle, IFile file) {
+ ICompilationUnit unit = super.createCompilationUnitFromPath(handle, file);
this.cuToHandle.put(unit, handle);
return unit;
}
-protected IBinaryType createInfoFromClassFile(Openable classFile, String osPath) {
+protected IBinaryType createInfoFromClassFile(Openable classFile, IResource file) {
String documentPath = classFile.getPath().toString();
IBinaryType binaryType = (IBinaryType)this.binariesFromIndexMatches.get(documentPath);
if (binaryType != null) {
this.infoToHandle.put(binaryType, classFile);
return binaryType;
} else {
- return super.createInfoFromClassFile(classFile, osPath);
+ return super.createInfoFromClassFile(classFile, file);
}
}
protected IBinaryType createInfoFromClassFileInJar(Openable classFile) {
@@ -421,7 +445,7 @@
final Map binariesFromIndexMatches,
final IPathRequestor pathRequestor,
int waitingPolicy, // WaitUntilReadyToSearch | ForceImmediateSearch | CancelIfNotReadyToSearch
- IProgressMonitor progressMonitor) {
+ final IProgressMonitor progressMonitor) {
/* embed constructs inside arrays so as to pass them to (inner) collector */
final Queue queue = new Queue();
@@ -436,7 +460,7 @@
boolean isLocalOrAnonymous = record.enclosingTypeName == IIndexConstants.ONE_ZERO;
pathRequestor.acceptPath(documentPath, isLocalOrAnonymous);
char[] typeName = record.simpleName;
- int suffix = documentPath.toLowerCase().indexOf(SUFFIX_STRING_class);
+ int suffix = documentPath.toLowerCase().lastIndexOf(SUFFIX_STRING_class);
if (suffix != -1){
HierarchyBinaryType binaryType = (HierarchyBinaryType)binariesFromIndexMatches.get(documentPath);
if (binaryType == null){
@@ -468,8 +492,14 @@
}
};
+ int superRefKind;
+ try {
+ superRefKind = type.isClass() ? SuperTypeReferencePattern.ONLY_SUPER_CLASSES : SuperTypeReferencePattern.ALL_SUPER_TYPES;
+ } catch (JavaModelException e) {
+ superRefKind = SuperTypeReferencePattern.ALL_SUPER_TYPES;
+ }
SuperTypeReferencePattern pattern =
- new SuperTypeReferencePattern(null, null, false, SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE);
+ new SuperTypeReferencePattern(null, null, superRefKind, SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE);
MatchLocator.setFocus(pattern, type);
SubTypeSearchJob job = new SubTypeSearchJob(
pattern,
@@ -490,7 +520,16 @@
// search all index references to a given supertype
pattern.superSimpleName = currentTypeName;
- indexManager.performConcurrentJob(job, waitingPolicy, null); // no sub progress monitor since its too costly for deep hierarchies
+ indexManager.performConcurrentJob(job, waitingPolicy, progressMonitor == null ? null : new NullProgressMonitor() {
+ // don't report progress since this is too costly for deep hierarchies
+ // just handle isCanceled() (seehttps://bugs.eclipse.org/bugs/show_bug.cgi?id=179511)
+ public void setCanceled(boolean value) {
+ progressMonitor.setCanceled(value);
+ }
+ public boolean isCanceled() {
+ return progressMonitor.isCanceled();
+ }
+ });
if (progressMonitor != null && ++ticks <= MAXTICKS)
progressMonitor.worked(1);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/RegionBasedHierarchyBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/RegionBasedHierarchyBuilder.java
index b0ae80a..70c737b 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/RegionBasedHierarchyBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/RegionBasedHierarchyBuilder.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -13,6 +13,7 @@
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.Map;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;
@@ -27,6 +28,7 @@
import org.eclipse.jdt.internal.core.JavaModelManager;
import org.eclipse.jdt.internal.core.JavaProject;
import org.eclipse.jdt.internal.core.Openable;
+import org.eclipse.jdt.internal.core.SearchableEnvironment;
public class RegionBasedHierarchyBuilder extends HierarchyBuilder {
@@ -69,26 +71,29 @@
*/
private void createTypeHierarchyBasedOnRegion(HashMap allOpenablesInRegion, IProgressMonitor monitor) {
- int size = allOpenablesInRegion.size();
- if (size != 0) {
+ try {
+ int size = allOpenablesInRegion.size();
+ if (monitor != null) monitor.beginTask("", size * 2/* 1 for build binding, 1 for connect hierarchy*/); //$NON-NLS-1$
this.infoToHandle = new HashMap(size);
- }
+ Iterator javaProjects = allOpenablesInRegion.entrySet().iterator();
+ while (javaProjects.hasNext()) {
+ Map.Entry entry = (Map.Entry) javaProjects.next();
+ JavaProject project = (JavaProject) entry.getKey();
+ ArrayList allOpenables = (ArrayList) entry.getValue();
+ Openable[] openables = new Openable[allOpenables.size()];
+ allOpenables.toArray(openables);
- Iterator javaProjects = allOpenablesInRegion.keySet().iterator();
- while (javaProjects.hasNext()) {
- ArrayList allOpenables = (ArrayList) allOpenablesInRegion.get(javaProjects.next());
- Openable[] openables = new Openable[allOpenables.size()];
- allOpenables.toArray(openables);
-
- try {
- // resolve
- if (monitor != null) monitor.beginTask("", size * 2/* 1 for build binding, 1 for connect hierarchy*/); //$NON-NLS-1$
- if (size > 0) {
+ try {
+ // resolve
+ SearchableEnvironment searchableEnvironment = project.newSearchableNameEnvironment(this.hierarchy.workingCopies);
+ this.nameLookup = searchableEnvironment.nameLookup;
this.hierarchyResolver.resolve(openables, null, monitor);
- }
- } finally {
- if (monitor != null) monitor.done();
+ } catch (JavaModelException e) {
+ // project doesn't exit: ignore
+ }
}
+ } finally {
+ if (monitor != null) monitor.done();
}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/RegionBasedTypeHierarchy.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/RegionBasedTypeHierarchy.java
index f9ae011..4dd08ac 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/RegionBasedTypeHierarchy.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/RegionBasedTypeHierarchy.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -14,17 +14,11 @@
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.*;
-import org.eclipse.jdt.core.IJavaElement;
-import org.eclipse.jdt.core.IJavaElementDelta;
-import org.eclipse.jdt.core.IJavaProject;
-import org.eclipse.jdt.core.IOpenable;
-import org.eclipse.jdt.core.IRegion;
-import org.eclipse.jdt.core.IType;
-import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.internal.core.CompilationUnit;
import org.eclipse.jdt.internal.core.JavaElement;
import org.eclipse.jdt.internal.core.Openable;
+import org.eclipse.jdt.internal.core.Region;
import org.eclipse.jdt.internal.core.TypeVector;
public class RegionBasedTypeHierarchy extends TypeHierarchy {
@@ -42,8 +36,37 @@
*/
public RegionBasedTypeHierarchy(IRegion region, ICompilationUnit[] workingCopies, IType type, boolean computeSubtypes) {
super(type, workingCopies, (IJavaSearchScope)null, computeSubtypes);
- this.region = region;
+
+ Region newRegion = new Region() {
+ public void add(IJavaElement element) {
+ if (!contains(element)) {
+ //"new" element added to region
+ removeAllChildren(element);
+ fRootElements.add(element);
+ if (element.getElementType() == IJavaElement.JAVA_PROJECT) {
+ // add jar roots as well so that jars don't rely on their parent to know
+ // if they are contained in the region
+ // (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=146615)
+ try {
+ IPackageFragmentRoot[] roots = ((IJavaProject) element).getPackageFragmentRoots();
+ for (int i = 0, length = roots.length; i < length; i++) {
+ if (roots[i].isArchive() && !fRootElements.contains(roots[i]))
+ fRootElements.add(roots[i]);
+ }
+ } catch (JavaModelException e) {
+ // project doesn't exist
+ }
+ }
+ fRootElements.trimToSize();
+ }
+ }
+ };
IJavaElement[] elements = region.getElements();
+ for (int i = 0, length = elements.length; i < length; i++) {
+ newRegion.add(elements[i]);
+
+ }
+ this.region = newRegion;
if (elements.length > 0)
this.project = elements[0].getJavaProject();
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/TypeHierarchy.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/TypeHierarchy.java
index 8c8609b..7397703 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/TypeHierarchy.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/TypeHierarchy.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -25,31 +25,11 @@
import org.eclipse.core.runtime.ISafeRunnable;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
-import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.jdt.core.*;
-import org.eclipse.jdt.core.ElementChangedEvent;
-import org.eclipse.jdt.core.IClasspathEntry;
-import org.eclipse.jdt.core.IElementChangedListener;
-import org.eclipse.jdt.core.IJavaElement;
-import org.eclipse.jdt.core.IJavaElementDelta;
-import org.eclipse.jdt.core.IJavaProject;
-import org.eclipse.jdt.core.IPackageFragment;
-import org.eclipse.jdt.core.IPackageFragmentRoot;
-import org.eclipse.jdt.core.IType;
-import org.eclipse.jdt.core.ITypeHierarchy;
-import org.eclipse.jdt.core.ITypeHierarchyChangedListener;
-import org.eclipse.jdt.core.JavaCore;
-import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.internal.core.*;
-import org.eclipse.jdt.internal.core.CompilationUnit;
-import org.eclipse.jdt.internal.core.JavaElement;
-import org.eclipse.jdt.internal.core.JavaModelStatus;
-import org.eclipse.jdt.internal.core.JavaProject;
-import org.eclipse.jdt.internal.core.Openable;
-import org.eclipse.jdt.internal.core.Region;
-import org.eclipse.jdt.internal.core.TypeVector;
import org.eclipse.jdt.internal.core.util.Messages;
import org.eclipse.jdt.internal.core.util.Util;
@@ -170,7 +150,7 @@
* Creates a TypeHierarchy on the given type.
*/
public TypeHierarchy(IType type, ICompilationUnit[] workingCopies, IJavaSearchScope scope, boolean computeSubtypes) {
- this.focusType = type;
+ this.focusType = type == null ? null : (IType) ((JavaElement) type).unresolved(); // unsure the focus type is unresolved (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=92357)
this.workingCopies = workingCopies;
this.computeSubtypes = computeSubtypes;
this.scope = scope;
@@ -378,7 +358,7 @@
listeners = (ArrayList)listeners.clone();
for (int i= 0; i < listeners.size(); i++) {
final ITypeHierarchyChangedListener listener= (ITypeHierarchyChangedListener)listeners.get(i);
- Platform.run(new ISafeRunnable() {
+ SafeRunner.run(new ISafeRunnable() {
public void handleException(Throwable exception) {
Util.log(exception, "Exception occurred in listener of Type hierarchy change notification"); //$NON-NLS-1$
}
@@ -544,14 +524,15 @@
* @see #getExtendingInterfaces
*/
private IType[] getExtendingInterfaces0(IType extendedInterface) {
- Iterator iter = this.typeToSuperInterfaces.keySet().iterator();
+ Iterator iter = this.typeToSuperInterfaces.entrySet().iterator();
ArrayList interfaceList = new ArrayList();
while (iter.hasNext()) {
- IType type = (IType) iter.next();
+ Map.Entry entry = (Map.Entry) iter.next();
+ IType type = (IType) entry.getKey();
if (!this.isInterface(type)) {
continue;
}
- IType[] superInterfaces = (IType[]) this.typeToSuperInterfaces.get(type);
+ IType[] superInterfaces = (IType[]) entry.getValue();
if (superInterfaces != null) {
for (int i = 0; i < superInterfaces.length; i++) {
IType superInterface = superInterfaces[i];
@@ -580,14 +561,15 @@
*/
private IType[] getImplementingClasses0(IType interfce) {
- Iterator iter = this.typeToSuperInterfaces.keySet().iterator();
+ Iterator iter = this.typeToSuperInterfaces.entrySet().iterator();
ArrayList iMenters = new ArrayList();
while (iter.hasNext()) {
- IType type = (IType) iter.next();
+ Map.Entry entry = (Map.Entry) iter.next();
+ IType type = (IType) entry.getKey();
if (this.isInterface(type)) {
continue;
}
- IType[] types = (IType[]) this.typeToSuperInterfaces.get(type);
+ IType[] types = (IType[]) entry.getValue();
for (int i = 0; i < types.length; i++) {
IType iFace = types[i];
if (iFace.equals(interfce)) {
@@ -769,7 +751,7 @@
String superclassName = type.getSuperclassName();
if (superclassName != null) {
int lastSeparator = superclassName.lastIndexOf('.');
- String simpleName = (lastSeparator > -1) ? superclassName.substring(lastSeparator) : superclassName;
+ String simpleName = superclassName.substring(lastSeparator+1);
if (hasTypeNamed(simpleName)) return true;
}
@@ -779,7 +761,7 @@
for (int i = 0, length = superinterfaceNames.length; i < length; i++) {
String superinterfaceName = superinterfaceNames[i];
int lastSeparator = superinterfaceName.lastIndexOf('.');
- String simpleName = (lastSeparator > -1) ? superinterfaceName.substring(lastSeparator) : superinterfaceName;
+ String simpleName = superinterfaceName.substring(lastSeparator+1);
if (hasTypeNamed(simpleName)) return true;
}
}
@@ -873,7 +855,7 @@
case IJavaElementDelta.ADDED :
try {
// if the added project is on the classpath, then the hierarchy has changed
- IClasspathEntry[] classpath = ((JavaProject)this.javaProject()).getExpandedClasspath(true);
+ IClasspathEntry[] classpath = ((JavaProject)this.javaProject()).getExpandedClasspath();
for (int i = 0; i < classpath.length; i++) {
if (classpath[i].getEntryKind() == IClasspathEntry.CPE_PROJECT
&& classpath[i].getPath().equals(element.getPath())) {
@@ -882,7 +864,7 @@
}
if (this.focusType != null) {
// if the hierarchy's project is on the added project classpath, then the hierarchy has changed
- classpath = ((JavaProject)element).getExpandedClasspath(true);
+ classpath = ((JavaProject)element).getExpandedClasspath();
IPath hierarchyProject = javaProject().getPath();
for (int i = 0; i < classpath.length; i++) {
if (classpath[i].getEntryKind() == IClasspathEntry.CPE_PROJECT
@@ -948,12 +930,9 @@
for (int i = 0; i < elements.length; i++) {
JavaProject javaProject = (JavaProject)elements[i];
try {
- IClasspathEntry[] classpath = javaProject.getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/);
- for (int j = 0; j < classpath.length; j++) {
- IClasspathEntry entry = classpath[j];
- if (entry.getPath().equals(rootPath)) {
- return true;
- }
+ IClasspathEntry entry = javaProject.getClasspathEntryFor(rootPath);
+ if (entry != null) {
+ return true;
}
} catch (JavaModelException e) {
// igmore this project
@@ -1233,11 +1212,11 @@
try {
this.progressMonitor = monitor;
if (monitor != null) {
- if (this.focusType != null) {
- monitor.beginTask(Messages.bind(Messages.hierarchy_creatingOnType, this.focusType.getFullyQualifiedName()), 100);
- } else {
- monitor.beginTask(Messages.hierarchy_creating, 100);
- }
+ monitor.beginTask(
+ this.focusType != null ?
+ Messages.bind(Messages.hierarchy_creatingOnType, this.focusType.getFullyQualifiedName()) :
+ Messages.hierarchy_creating,
+ 100);
}
long start = -1;
if (DEBUG) {
@@ -1307,30 +1286,32 @@
hashtable.put(this.focusType, index);
hashtable2.put(index, this.focusType);
}
- Object[] types = this.classToSuperclass.keySet().toArray();
+ Object[] types = this.classToSuperclass.entrySet().toArray();
for (int i = 0; i < types.length; i++) {
- Object t = types[i];
+ Map.Entry entry = (Map.Entry) types[i];
+ Object t = entry.getKey();
if(hashtable.get(t) == null) {
Integer index = new Integer(count++);
hashtable.put(t, index);
hashtable2.put(index, t);
}
- Object superClass = this.classToSuperclass.get(t);
+ Object superClass = entry.getValue();
if(superClass != null && hashtable.get(superClass) == null) {
Integer index = new Integer(count++);
hashtable.put(superClass, index);
hashtable2.put(index, superClass);
}
}
- types = this.typeToSuperInterfaces.keySet().toArray();
+ types = this.typeToSuperInterfaces.entrySet().toArray();
for (int i = 0; i < types.length; i++) {
- Object t = types[i];
+ Map.Entry entry = (Map.Entry) types[i];
+ Object t = entry.getKey();
if(hashtable.get(t) == null) {
Integer index = new Integer(count++);
hashtable.put(t, index);
hashtable2.put(index, t);
}
- Object[] sp = (Object[])this.typeToSuperInterfaces.get(t);
+ Object[] sp = (Object[]) entry.getValue();
if(sp != null) {
for (int j = 0; j < sp.length; j++) {
Object superInterface = sp[j];
@@ -1392,10 +1373,11 @@
output.write(SEPARATOR1);
// save superclasses
- types = this.classToSuperclass.keySet().toArray();
+ types = this.classToSuperclass.entrySet().toArray();
for (int i = 0; i < types.length; i++) {
- IJavaElement key = (IJavaElement)types[i];
- IJavaElement value = (IJavaElement)this.classToSuperclass.get(key);
+ Map.Entry entry = (Map.Entry) types[i];
+ IJavaElement key = (IJavaElement) entry.getKey();
+ IJavaElement value = (IJavaElement) entry.getValue();
output.write(((Integer)hashtable.get(key)).toString().getBytes());
output.write('>');
@@ -1405,10 +1387,11 @@
output.write(SEPARATOR1);
// save superinterfaces
- types = this.typeToSuperInterfaces.keySet().toArray();
+ types = this.typeToSuperInterfaces.entrySet().toArray();
for (int i = 0; i < types.length; i++) {
- IJavaElement key = (IJavaElement)types[i];
- IJavaElement[] values = (IJavaElement[])this.typeToSuperInterfaces.get(key);
+ Map.Entry entry = (Map.Entry) types[i];
+ IJavaElement key = (IJavaElement) entry.getKey();
+ IJavaElement[] values = (IJavaElement[]) entry.getValue();
if(values.length > 0) {
output.write(((Integer)hashtable.get(key)).toString().getBytes());
@@ -1491,17 +1474,16 @@
toString(buffer, this.focusType, 1, false);
} else {
buffer.append("Sub types of root classes:\n"); //$NON-NLS-1$
- IType[] roots= getRootClasses();
+ IJavaElement[] roots = Util.sortCopy(getRootClasses());
for (int i= 0; i < roots.length; i++) {
- toString(buffer, roots[i], 1, false);
+ toString(buffer, (IType) roots[i], 1, false);
}
}
if (this.rootClasses.size > 1) {
buffer.append("Root classes:\n"); //$NON-NLS-1$
- IType[] roots = this.getRootClasses();
+ IJavaElement[] roots = Util.sortCopy(getRootClasses());
for (int i = 0, length = roots.length; i < length; i++) {
- IType type = roots[i];
- toString(buffer, type, 1, false);
+ toString(buffer, (IType) roots[i], 1, false);
}
} else if (this.rootClasses.size == 0) {
// see http://bugs.eclipse.org/bugs/show_bug.cgi?id=24691
@@ -1519,11 +1501,12 @@
*/
private void toString(StringBuffer buffer, IType type, int indent, boolean ascendant) {
IType[] types= ascendant ? getSupertypes(type) : getSubtypes(type);
- for (int i= 0; i < types.length; i++) {
+ IJavaElement[] sortedTypes = Util.sortCopy(types);
+ for (int i= 0; i < sortedTypes.length; i++) {
for (int j= 0; j < indent; j++) {
buffer.append(" "); //$NON-NLS-1$
}
- JavaElement element = (JavaElement)types[i];
+ JavaElement element = (JavaElement)sortedTypes[i];
buffer.append(element.toStringWithAncestors(false/*don't show key*/));
buffer.append('\n');
toString(buffer, types[i], indent + 1, ascendant);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/AbstractDOMBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/AbstractDOMBuilder.java
index 3702006..7c67a47 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/AbstractDOMBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/AbstractDOMBuilder.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/CompilationUnit.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/CompilationUnit.java
index db3c55b..8e75cee 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/CompilationUnit.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/CompilationUnit.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMBuilder.java
index 914af5c..3e68d04 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMBuilder.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -14,8 +14,8 @@
import java.util.Map;
import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.compiler.CategorizedProblem;
import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.core.jdom.*;
import org.eclipse.jdt.internal.compiler.DocumentElementParser;
import org.eclipse.jdt.internal.compiler.IDocumentElementRequestor;
@@ -121,7 +121,7 @@
*
* @see IDocumentElementRequestor
*/
-public void acceptProblem(IProblem problem){
+public void acceptProblem(CategorizedProblem problem){
if (fBuildingSingleMember && fFinishedSingleMember) {
return;
}
@@ -268,7 +268,10 @@
return null;
}
if (fNode != null) fNode.normalize(this);
- return (IDOMType)fNode;
+ if (fNode instanceof IDOMType) {
+ return (IDOMType) fNode;
+ }
+ return null;
}
/**
* Creates a new DOMMethod and inizializes.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMCompilationUnit.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMCompilationUnit.java
index e06d1bb..d150c83 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMCompilationUnit.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMCompilationUnit.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMField.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMField.java
index eba8825..3994126 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMField.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMField.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMImport.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMImport.java
index 1a99239..8c40c0a 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMImport.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMImport.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMInitializer.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMInitializer.java
index cba8276..74aaf01 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMInitializer.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMInitializer.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMMember.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMMember.java
index f5555f2..19c1242 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMMember.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMMember.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -13,7 +13,7 @@
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.jdom.*;
-import org.eclipse.jdt.internal.compiler.env.IConstants;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.core.util.CharArrayBuffer;
/**
* DOMMember provides an implementation of IDOMMember.
@@ -283,10 +283,10 @@
setHasComment(comment != null);
/* see 1FVIJAH */
if (comment != null && comment.indexOf("@deprecated") >= 0) { //$NON-NLS-1$
- fFlags= fFlags | IConstants.AccDeprecated;
+ fFlags= fFlags | ClassFileConstants.AccDeprecated;
return;
}
- fFlags= fFlags & (~IConstants.AccDeprecated);
+ fFlags= fFlags & (~ClassFileConstants.AccDeprecated);
}
/**
* @see IDOMMember#setFlags(int)
@@ -294,9 +294,9 @@
public void setFlags(int flags) {
becomeDetailed();
if (Flags.isDeprecated(fFlags)) {
- fFlags= flags | IConstants.AccDeprecated;
+ fFlags= flags | ClassFileConstants.AccDeprecated;
} else {
- fFlags= flags & (~IConstants.AccDeprecated);
+ fFlags= flags & (~ClassFileConstants.AccDeprecated);
}
fragment();
fModifiers= generateFlags();
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMMethod.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMMethod.java
index c83d0eb..db80cfc 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMMethod.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMMethod.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -118,7 +118,7 @@
* The formal type parameters.
* @since 3.0
*/
- protected String[] fTypeParameters = new String[0];
+ protected String[] fTypeParameters = CharOperation.NO_STRINGS;
/**
* Default value for this attotation type member (only),
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMNode.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMNode.java
index b9d4291..8da9dbf 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMNode.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMNode.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMPackage.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMPackage.java
index 3bc7454..4280885 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMPackage.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMPackage.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMType.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMType.java
index f3a708d..faff058 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMType.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMType.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -15,6 +15,7 @@
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.compiler.InvalidInputException;
import org.eclipse.jdt.core.jdom.*;
import org.eclipse.jdt.internal.compiler.parser.Scanner;
@@ -32,8 +33,6 @@
*/
// TODO (jerome) - add implementation support for 1.5 features
/* package */ class DOMType extends DOMMember implements IDOMType {
-
- private static final String[] EMPTY_SUPERINTERFACES = new String[] {};
/**
* The 'class' or 'interface' keyword if altered
* from the documents contents, otherwise <code>null</code>.
@@ -114,13 +113,13 @@
* <code>null</code> when this type does not extend
* or implement any interfaces.
*/
- protected String[] fSuperInterfaces= new String[0];
+ protected String[] fSuperInterfaces= CharOperation.NO_STRINGS;
/**
* The formal type parameters.
* @since 3.0
*/
- protected String[] fTypeParameters = new String[0];
+ protected String[] fTypeParameters = CharOperation.NO_STRINGS;
/**
* Indicates this type is an enum class.
@@ -325,6 +324,9 @@
} else {
if (fSuperclassRange[0] < 0) {
buffer.append(' ');
+ } else if (fImplementsRange[0] > 0) {
+ buffer.append(fDocument, fSuperclassRange[1] + 1, fImplementsRange[0] - fSuperclassRange[1] - 1);
+ buffer.append(fDocument, fInterfacesRange[1] + 1, fOpenBodyRange[0] - fInterfacesRange[1] - 1);
} else {
buffer.append(fDocument, fSuperclassRange[1] + 1, fOpenBodyRange[0] - fSuperclassRange[1] - 1);
}
@@ -693,7 +695,7 @@
fSuperInterfaces= names;
if (names.length == 0) {
fInterfaces= null;
- fSuperInterfaces= EMPTY_SUPERINTERFACES;
+ fSuperInterfaces= CharOperation.NO_STRINGS;
setMask(MASK_TYPE_HAS_INTERFACES, false);
} else {
setMask(MASK_TYPE_HAS_INTERFACES, true);
@@ -785,7 +787,7 @@
// annotation types are always interface with no superclass or superinterfaces
setClass(false);
setSuperclass(null);
- setSuperInterfaces(new String[0]);
+ setSuperInterfaces(CharOperation.NO_STRINGS);
}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/ILineStartFinder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/ILineStartFinder.java
index f53b02c..db9bcba 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/ILineStartFinder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/ILineStartFinder.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/SiblingEnumeration.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/SiblingEnumeration.java
index e9b126e..ff5b800 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/SiblingEnumeration.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/SiblingEnumeration.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/SimpleDOMBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/SimpleDOMBuilder.java
index 6442feb..b90c530 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/SimpleDOMBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/SimpleDOMBuilder.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -13,13 +13,13 @@
import java.util.Map;
import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.compiler.CategorizedProblem;
import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.core.jdom.*;
import org.eclipse.jdt.internal.compiler.ISourceElementRequestor;
import org.eclipse.jdt.internal.compiler.SourceElementParser;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
-import org.eclipse.jdt.internal.compiler.env.IGenericType;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
/**
@@ -33,13 +33,13 @@
/**
* Does nothing.
*/
-public void acceptProblem(IProblem problem) {
+public void acceptProblem(CategorizedProblem problem) {
// nothing to do
}
-public void acceptImport(int declarationStart, int declarationEnd, char[] name, boolean onDemand, int modifiers) {
+public void acceptImport(int declarationStart, int declarationEnd, char[][] tokens, boolean onDemand, int modifiers) {
int[] sourceRange = {declarationStart, declarationEnd};
- String importName = new String(name);
+ String importName = new String(CharOperation.concatWith(tokens, '.'));
/** name is set to contain the '*' */
if (onDemand) {
importName+=".*"; //$NON-NLS-1$
@@ -130,7 +130,7 @@
int[] sourceRange = {typeInfo.declarationStart, -1}; // will be fixed in the exit
int[] nameRange = new int[] {typeInfo.nameSourceStart, typeInfo.nameSourceEnd};
fNode = new DOMType(fDocument, sourceRange, new String(typeInfo.name), nameRange,
- typeInfo.modifiers, CharOperation.charArrayToStringArray(typeInfo.superinterfaces), typeInfo.kind == IGenericType.CLASS_DECL); // TODO (jerome) should pass in kind
+ typeInfo.modifiers, CharOperation.charArrayToStringArray(typeInfo.superinterfaces), TypeDeclaration.kind(typeInfo.modifiers) == TypeDeclaration.CLASS_DECL); // TODO (jerome) should pass in kind
addChild(fNode);
fStack.push(fNode);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ASTNodeFinder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ASTNodeFinder.java
index f0d7e6f..e4364ba 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ASTNodeFinder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ASTNodeFinder.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -121,7 +121,7 @@
int count = 0;
public boolean visit(TypeDeclaration typeDeclaration, BlockScope scope) {
if (result != null) return false;
- if ((typeDeclaration.bits & ASTNode.IsAnonymousTypeMASK) != 0) {
+ if ((typeDeclaration.bits & ASTNode.IsAnonymousType) != 0) {
if (findAnonymous && ++count == occurenceCount) {
result = typeDeclaration;
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Annotation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Annotation.java
index 3a2343d..475021f 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Annotation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Annotation.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004 IBM Corporation and others.
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/AnnotationComponent.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/AnnotationComponent.java
index 93e194b..30ed3c5 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/AnnotationComponent.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/AnnotationComponent.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004 IBM Corporation and others.
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/AnnotationDefaultAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/AnnotationDefaultAttribute.java
index 4f7e49c..ad4cd78 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/AnnotationDefaultAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/AnnotationDefaultAttribute.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/BindingKeyParser.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/BindingKeyParser.java
index 81b4fe7..d0248ce 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/BindingKeyParser.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/BindingKeyParser.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005 IBM Corporation and others.
+ * Copyright (c) 2005, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -17,7 +17,9 @@
int keyStart;
- class Scanner {
+ static final char C_THROWN = '|';
+
+ static class Scanner {
static final int PACKAGE = 0;
static final int TYPE = 1;
static final int FIELD = 2;
@@ -116,10 +118,10 @@
return this.index < this.source.length && "LIZVCDBFJS[!".indexOf(this.source[this.index]) != -1; //$NON-NLS-1$
}
- boolean isAtFlagsStart() {
+ boolean isAtThrownStart() {
return
this.index < this.source.length
- && this.source[this.index] == '^';
+ && this.source[this.index] == C_THROWN;
}
boolean isAtTypeVariableStart() {
@@ -161,7 +163,8 @@
break;
case 'L':
case 'T':
- if (this.index == previousTokenEnd) {
+ if (this.index == previousTokenEnd
+ && (this.index == 0 || this.source[this.index-1] != '.')) { // case of field or method starting with one of the character above
this.start = this.index+1;
}
break;
@@ -174,28 +177,6 @@
return this.token;
}
break;
- case '^':
- if (this.index == previousTokenEnd) {
- this.index++;
- this.start = this.index;
- while (this.index < length && Character.isDigit(this.source[this.index]))
- this.index++;
- this.token = FLAGS;
- return this.token;
- } else {
- switch (this.token) {
- case METHOD:
- case LOCAL_VAR:
- this.token = LOCAL_VAR;
- break;
- case TYPE:
- case BASE_TYPE:
- if (this.index > this.start && this.source[this.start-1] == '.')
- this.token = FIELD;
- break;
- }
- return this.token;
- }
case '$':
case '~':
if (this.index == previousTokenEnd) {
@@ -306,7 +287,7 @@
switch (this.source[this.index]) {
case '#':
case '%':
- case '^':
+ case C_THROWN:
return;
case ':':
if (braket == 0)
@@ -325,6 +306,11 @@
}
}
+ void skipThrownStart() {
+ while (this.index < this.source.length && this.source[this.index] == C_THROWN)
+ this.index++;
+ }
+
void skipParametersStart() {
while (this.index < this.source.length && (this.source[this.index] == '<' || this.source[this.index] == '%'))
this.index++;
@@ -429,6 +415,10 @@
// default is to do nothing
}
+ public void consumeException() {
+ // default is to do nothing
+ }
+
public void consumeField(char[] fieldName) {
// default is to do nothing
}
@@ -541,72 +531,75 @@
}
public void parse(boolean pauseAfterFullyQualifiedName) {
- if (!this.parsingPaused) {
- // fully qualified name
- parseFullyQualifiedName();
- if (pauseAfterFullyQualifiedName) {
- this.parsingPaused = true;
+ try {
+ if (!this.parsingPaused) {
+ // fully qualified name
+ parseFullyQualifiedName();
+ parseSecondaryType();
+ if (pauseAfterFullyQualifiedName) {
+ this.parsingPaused = true;
+ return;
+ }
+ }
+ if (!hasTypeName()) {
+ consumeKey();
return;
}
- }
- if (!hasTypeName()) {
- consumeKey();
- return;
- }
- consumeTopLevelType();
- parseSecondaryType();
- parseInnerType();
-
- if (this.scanner.isAtParametersStart()) {
- this.scanner.skipParametersStart();
- if (this.scanner.isAtTypeParameterStart()) {
- // generic type
- parseGenericType();
- // skip ";>"
- this.scanner.skipParametersEnd();
- // local type in generic type
- parseInnerType();
- } else if (this.scanner.isAtTypeArgumentStart())
- // parameterized type
- parseParameterizedType(null/*top level type or member type with raw enclosing type*/, false/*no raw*/);
- else if (this.scanner.isAtRawTypeEnd())
- // raw type
- parseRawType();
- } else {
- // non-generic type
- consumeNonGenericType();
- }
-
- consumeType();
- this.scanner.skipTypeEnd();
- parseFlags();
-
- if (this.scanner.isAtFieldOrMethodStart()) {
- switch (this.scanner.nextToken()) {
- case Scanner.FIELD:
- parseField();
- return;
- case Scanner.METHOD:
- parseMethod();
- if (this.scanner.isAtLocalVariableStart()) {
- parseLocalVariable();
- } else if (this.scanner.isAtTypeVariableStart()) {
- parseTypeVariable();
- }
- break;
- default:
- malformedKey();
- return;
+ consumeTopLevelType();
+ parseInnerType();
+
+ if (this.scanner.isAtParametersStart()) {
+ this.scanner.skipParametersStart();
+ if (this.scanner.isAtTypeParameterStart()) {
+ // generic type
+ parseGenericType();
+ // skip ";>"
+ this.scanner.skipParametersEnd();
+ // local type in generic type
+ parseInnerType();
+ } else if (this.scanner.isAtTypeArgumentStart())
+ // parameterized type
+ parseParameterizedType(null/*top level type or member type with raw enclosing type*/, false/*no raw*/);
+ else if (this.scanner.isAtRawTypeEnd())
+ // raw type
+ parseRawType();
+ } else {
+ // non-generic type
+ consumeNonGenericType();
}
- } else if (this.scanner.isAtTypeVariableStart()) {
- parseTypeVariable();
- } else if (this.scanner.isAtWildcardStart()) {
- parseWildcard();
- } else if (this.scanner.isAtTypeWithCaptureStart()) {
- parseTypeWithCapture();
+
+ consumeType();
+ this.scanner.skipTypeEnd();
+
+ if (this.scanner.isAtFieldOrMethodStart()) {
+ switch (this.scanner.nextToken()) {
+ case Scanner.FIELD:
+ parseField();
+ return;
+ case Scanner.METHOD:
+ parseMethod();
+ if (this.scanner.isAtLocalVariableStart()) {
+ parseLocalVariable();
+ } else if (this.scanner.isAtTypeVariableStart()) {
+ parseTypeVariable();
+ }
+ break;
+ default:
+ malformedKey();
+ return;
+ }
+ } else if (this.scanner.isAtTypeVariableStart()) {
+ parseTypeVariable();
+ } else if (this.scanner.isAtWildcardStart()) {
+ parseWildcard();
+ } else if (this.scanner.isAtTypeWithCaptureStart()) {
+ parseTypeWithCapture();
+ }
+
+ consumeKey();
+ } catch (IllegalArgumentException e) {
+ // the given key was illegal
}
-
- consumeKey();
}
private void parseFullyQualifiedName() {
@@ -704,7 +697,6 @@
parseLocalVariable();
} else {
consumeLocalVar(varName);
- parseFlags();
}
}
@@ -713,7 +705,9 @@
this.scanner.skipMethodSignature();
char[] signature = this.scanner.getTokenSource();
consumeMethod(selector, signature);
- parseFlags();
+ if (this.scanner.isAtThrownStart()) {
+ parseThrownExceptions();
+ }
if (this.scanner.isAtParametersStart())
parseParameterizedMethod();
}
@@ -743,9 +737,14 @@
consumeField(fieldName);
}
- private void parseFlags() {
- if (!this.scanner.isAtFlagsStart() || this.scanner.nextToken() != Scanner.FLAGS) return;
- consumeModifiers(this.scanner.getTokenSource());
+ private void parseThrownExceptions() {
+ while (this.scanner.isAtThrownStart()) {
+ this.scanner.skipThrownStart();
+ BindingKeyParser parser = newParser();
+ parser.parse();
+ consumeParser(parser);
+ consumeException();
+ }
}
private void parseParameterizedType(char[] typeName, boolean isRaw) {
@@ -758,7 +757,6 @@
this.scanner.skipParametersEnd();
consumeParameterizedType(typeName, isRaw);
this.scanner.skipTypeEnd();
- parseFlags();
if (this.scanner.isAtMemberTypeStart() && this.scanner.nextToken() == Scanner.TYPE) {
typeName = this.scanner.getTokenSource();
if (this.scanner.isAtParametersStart()) {
@@ -772,6 +770,15 @@
private void parseRawType() {
this.scanner.skipParametersEnd();
consumeRawType();
+ this.scanner.skipTypeEnd();
+ if (this.scanner.isAtMemberTypeStart() && this.scanner.nextToken() == Scanner.TYPE) {
+ char[] typeName = this.scanner.getTokenSource();
+ if (this.scanner.isAtParametersStart()) {
+ this.scanner.skipParametersStart();
+ parseParameterizedType(typeName, this.scanner.isAtRawTypeEnd());
+ } else
+ consumeParameterizedType(typeName, true/*raw*/);
+ }
}
private void parseReturnType() {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/BindingKeyResolver.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/BindingKeyResolver.java
index 27c74f2..32e16ba 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/BindingKeyResolver.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/BindingKeyResolver.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005 IBM Corporation and others.
+ * Copyright (c) 2005, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -27,7 +27,6 @@
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Wildcard;
import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
-import org.eclipse.jdt.internal.compiler.lookup.BaseTypes;
import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
@@ -38,7 +37,6 @@
import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
-import org.eclipse.jdt.internal.compiler.lookup.ParameterizedGenericMethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.RawTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
@@ -57,6 +55,7 @@
ReferenceBinding genericType;
MethodBinding methodBinding;
+ char[] secondarySimpleName;
CompilationUnitDeclaration parsedUnit;
BlockScope scope;
TypeBinding typeBinding;
@@ -188,8 +187,12 @@
this.typeBinding = captureFinder.capture;
}
+ public void consumeException() {
+ this.types = new ArrayList();
+ }
+
public void consumeField(char[] fieldName) {
- FieldBinding[] fields = ((ReferenceBinding) this.typeBinding).fields();
+ FieldBinding[] fields = ((ReferenceBinding) this.typeBinding).availableFields(); // resilience
for (int i = 0, length = fields.length; i < length; i++) {
FieldBinding field = fields[i];
if (CharOperation.equals(fieldName, field.name)) {
@@ -205,9 +208,9 @@
return;
TypeBinding[] arguments = getTypeBindingArguments();
if (arguments.length != this.methodBinding.typeVariables().length)
- this.methodBinding = new ParameterizedGenericMethodBinding(this.methodBinding, (RawTypeBinding) null, this.environment);
+ this.methodBinding = this.environment.createParameterizedGenericMethod(this.methodBinding, (RawTypeBinding) null);
else
- this.methodBinding = new ParameterizedGenericMethodBinding(this.methodBinding, arguments, this.environment);
+ this.methodBinding = this.environment.createParameterizedGenericMethod(this.methodBinding, arguments);
this.compilerBinding = this.methodBinding;
}
@@ -235,7 +238,7 @@
}
public void consumeMethod(char[] selector, char[] signature) {
- MethodBinding[] methods = ((ReferenceBinding) this.typeBinding).methods();
+ MethodBinding[] methods = ((ReferenceBinding) this.typeBinding).availableMethods(); // resilience
for (int i = 0, methodLength = methods.length; i < methodLength; i++) {
MethodBinding method = methods[i];
if (CharOperation.equals(selector, method.selector) || (selector.length == 0 && method.isConstructor())) {
@@ -264,8 +267,13 @@
public void consumeParameterizedType(char[] simpleTypeName, boolean isRaw) {
TypeBinding[] arguments = getTypeBindingArguments();
if (simpleTypeName != null) {
- // parameterized member type with parameterized enclosing type
- this.genericType = this.genericType.getMemberType(simpleTypeName);
+ if (this.genericType == null) {
+ // parameterized member type with raw enclosing type
+ this.genericType = ((ReferenceBinding) this.typeBinding).getMemberType(simpleTypeName);
+ } else {
+ // parameterized member type with parameterized enclosing type
+ this.genericType = this.genericType.getMemberType(simpleTypeName);
+ }
if (!isRaw)
this.typeBinding = this.environment.createParameterizedType(this.genericType, arguments, (ReferenceBinding) this.typeBinding);
else
@@ -298,12 +306,10 @@
public void consumeRawType() {
if (this.typeBinding == null) return;
- this.typeBinding = this.environment.createRawType((ReferenceBinding) this.typeBinding, this.typeBinding.enclosingType());
+ this.typeBinding = this.environment.convertToRawType(this.typeBinding);
}
public void consumeSecondaryType(char[] simpleTypeName) {
- if (this.parsedUnit == null) return;
- this.typeDeclaration = null; // start from the parsed unit
- this.typeBinding = getTypeBinding(simpleTypeName);
+ this.secondarySimpleName = simpleTypeName;
}
public void consumeFullyQualifiedName(char[] fullyQualifiedName) {
@@ -318,7 +324,7 @@
if (this.parsedUnit == null) {
this.typeBinding = getBinaryBinding();
} else {
- char[] typeName = this.compoundName[this.compoundName.length-1];
+ char[] typeName = this.secondarySimpleName == null ? this.compoundName[this.compoundName.length-1] : this.secondarySimpleName;
this.typeBinding = getTypeBinding(typeName);
}
}
@@ -333,7 +339,7 @@
public void consumeTypeVariable(char[] position, char[] typeVariableName) {
if (position.length > 0) {
int pos = Integer.parseInt(new String(position));
- MethodBinding[] methods = ((ReferenceBinding) this.typeBinding).methods();
+ MethodBinding[] methods = ((ReferenceBinding) this.typeBinding).availableMethods(); // resilience
if (methods != null && pos < methods.length) {
this.methodBinding = methods[pos];
}
@@ -380,25 +386,25 @@
private TypeBinding getBaseTypeBinding(char[] signature) {
switch (signature[0]) {
case 'I' :
- return BaseTypes.IntBinding;
+ return TypeBinding.INT;
case 'Z' :
- return BaseTypes.BooleanBinding;
+ return TypeBinding.BOOLEAN;
case 'V' :
- return BaseTypes.VoidBinding;
+ return TypeBinding.VOID;
case 'C' :
- return BaseTypes.CharBinding;
+ return TypeBinding.CHAR;
case 'D' :
- return BaseTypes.DoubleBinding;
+ return TypeBinding.DOUBLE;
case 'B' :
- return BaseTypes.ByteBinding;
+ return TypeBinding.BYTE;
case 'F' :
- return BaseTypes.FloatBinding;
+ return TypeBinding.FLOAT;
case 'J' :
- return BaseTypes.LongBinding;
+ return TypeBinding.LONG;
case 'S' :
- return BaseTypes.ShortBinding;
+ return TypeBinding.SHORT;
case 'N':
- return BaseTypes.NullBinding;
+ return TypeBinding.NULL;
default :
return null;
}
@@ -419,11 +425,21 @@
* This key's scanner should be positioned on the package token.
*/
public CompilationUnitDeclaration getCompilationUnitDeclaration() {
- char[][] name = compoundName();
+ char[][] name = this.compoundName;
if (name.length == 0) return null;
if (this.environment == null) return null;
ReferenceBinding binding = this.environment.getType(name);
- if (!(binding instanceof SourceTypeBinding)) return null;
+ if (!(binding instanceof SourceTypeBinding)) {
+ if (this.secondarySimpleName == null)
+ return null;
+ // case of a secondary type with no primary type (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=177115)
+ int length = name.length;
+ System.arraycopy(name, 0, name = new char[length][], 0, length-1);
+ name[length-1] = this.secondarySimpleName;
+ binding = this.environment.getType(name);
+ if (!(binding instanceof SourceTypeBinding))
+ return null;
+ }
SourceTypeBinding sourceTypeBinding = (SourceTypeBinding) binding;
if (sourceTypeBinding.scope == null)
return null;
@@ -436,8 +452,13 @@
* This key's scanner should be positioned on the package token.
*/
public Binding getCompilerBinding() {
- parse();
- return this.compilerBinding;
+ try {
+ parse();
+ return this.compilerBinding;
+ } catch (RuntimeException e) {
+ Util.log(e, "Could not create binding from binding key: " + getKey()); //$NON-NLS-1$
+ return null;
+ }
}
private TypeBinding getTypeBinding(char[] simpleTypeName) {
@@ -465,7 +486,11 @@
TypeBinding[] arguments = new TypeBinding[size];
for (int i = 0; i < size; i++) {
BindingKeyResolver resolver = (BindingKeyResolver) this.types.get(i);
- arguments[i] = (TypeBinding) resolver.compilerBinding;
+ TypeBinding compilerBinding2 = (TypeBinding) resolver.compilerBinding;
+ if (compilerBinding2 == null) {
+ throw new IllegalArgumentException();
+ }
+ arguments[i] = compilerBinding2;
}
this.types = new ArrayList();
return arguments;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CharArrayBuffer.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CharArrayBuffer.java
index fb90197..aab2c32 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CharArrayBuffer.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CharArrayBuffer.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,6 +10,8 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core.util;
+import org.eclipse.jdt.internal.compiler.util.Util;
+
/**
* The <code>CharArrayBuffer</code> is intended as a lightweight partial implementation
* of the StringBuffer class, but using <code>char[]'s</code> instead of Strings.
@@ -182,10 +184,10 @@
}
/**
* Returns the contents of the buffer as a String, or
- * <code>null</code> if the buffer is empty.
+ * an empty string if the buffer is empty.
*/
public String toString() {
char[] contents = getContents();
- return (contents != null) ? new String(contents) : null;
+ return (contents != null) ? new String(contents) : Util.EMPTY_STRING;
}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ClassFileAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ClassFileAttribute.java
index fb5b1cc..60ad871 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ClassFileAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ClassFileAttribute.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ClassFileReader.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ClassFileReader.java
index 9b1916e..e018a72 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ClassFileReader.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ClassFileReader.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -25,10 +25,10 @@
import org.eclipse.jdt.core.util.IMethodInfo;
import org.eclipse.jdt.core.util.IModifierConstants;
import org.eclipse.jdt.core.util.ISourceAttribute;
+import org.eclipse.jdt.internal.compiler.util.Util;
public class ClassFileReader extends ClassFileStruct implements IClassFileReader {
private static final IFieldInfo[] NO_FIELD_INFOS = new IFieldInfo[0];
- private static final int[] NO_INTERFACE_INDEXES = new int[0];
private static final char[][] NO_INTERFACES_NAMES = CharOperation.NO_CHAR_CHAR;
private static final IMethodInfo[] NO_METHOD_INFOS = new IMethodInfo[0];
private int accessFlags;
@@ -139,6 +139,9 @@
case IConstantPoolConstant.CONSTANT_NameAndType :
constantPoolOffsets[i] = readOffset;
readOffset += IConstantPoolConstant.CONSTANT_NameAndType_SIZE;
+ break;
+ default:
+ throw new ClassFormatException(ClassFormatException.INVALID_TAG_CONSTANT);
}
}
@@ -165,7 +168,7 @@
this.interfacesCount = u2At(classFileBytes, readOffset, 0);
readOffset += 2;
this.interfaceNames = NO_INTERFACES_NAMES;
- this.interfaceIndexes = NO_INTERFACE_INDEXES;
+ this.interfaceIndexes = Util.EMPTY_INT_ARRAY;
if (this.interfacesCount != 0) {
if ((decodingFlags & IClassFileReader.SUPER_INTERFACES) != IClassFileReader.CONSTANT_POOL) {
this.interfaceNames = new char[this.interfacesCount][];
@@ -275,6 +278,7 @@
} catch(ClassFormatException e) {
throw e;
} catch (Exception e) {
+ e.printStackTrace();
throw new ClassFormatException(ClassFormatException.ERROR_TRUNCATED_INPUT);
}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ClassFileStruct.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ClassFileStruct.java
index 53a5f5c..faca05d 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ClassFileStruct.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ClassFileStruct.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CodeAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CodeAttribute.java
index abb55f0..21a7dfe 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CodeAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CodeAttribute.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -82,12 +82,15 @@
this.attributes[attributesIndex++] = this.localVariableAttribute;
} else if (equals(attributeName, IAttributeNamesConstants.LOCAL_VARIABLE_TYPE_TABLE)) {
this.attributes[attributesIndex++] = new LocalVariableTypeAttribute(classFileBytes, constantPool, offset + readOffset);
+ } else if (equals(attributeName, IAttributeNamesConstants.STACK_MAP_TABLE)) {
+ this.attributes[attributesIndex++] = new StackMapTableAttribute(classFileBytes, constantPool, offset + readOffset);
+ } else if (equals(attributeName, IAttributeNamesConstants.STACK_MAP)) {
+ this.attributes[attributesIndex++] = new StackMapAttribute(classFileBytes, constantPool, offset + readOffset);
} else {
this.attributes[attributesIndex++] = new ClassFileAttribute(classFileBytes, constantPool, offset + readOffset);
}
readOffset += (6 + u4At(classFileBytes, readOffset + 2, offset));
}
-
}
/**
* @see ICodeAttribute#getAttributes()
@@ -906,7 +909,7 @@
case IOpcodeMnemonics.TABLESWITCH :
int startpc = pc;
pc++;
- while (((pc - this.codeOffset) % 4) != 0) {
+ while (((pc - this.codeOffset) & 0x03) != 0) { // faster than % 4
pc++;
}
int defaultOffset = i4At(this.classFileBytes, 0, pc);
@@ -926,7 +929,7 @@
case IOpcodeMnemonics.LOOKUPSWITCH :
startpc = pc;
pc++;
- while (((pc - this.codeOffset) % 4) != 0) {
+ while (((pc - this.codeOffset) & 0x03) != 0) {
pc++;
}
defaultOffset = i4At(this.classFileBytes, 0, pc);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CodeSnippetParsingUtil.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CodeSnippetParsingUtil.java
index 656ef07..8a31b54 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CodeSnippetParsingUtil.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CodeSnippetParsingUtil.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2002, 2004 IBM Corporation and others.
+ * Copyright (c) 2002, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -13,7 +13,7 @@
import java.util.Locale;
import java.util.Map;
-import org.eclipse.jdt.core.compiler.IProblem;
+import org.eclipse.jdt.core.compiler.CategorizedProblem;
import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
@@ -35,16 +35,16 @@
private RecordedParsingInformation getRecordedParsingInformation(CompilationResult compilationResult, CommentRecorderParser parser) {
int problemsCount = compilationResult.problemCount;
- IProblem[] problems = null;
+ CategorizedProblem[] problems = null;
if (problemsCount != 0) {
- final IProblem[] compilationResultProblems = compilationResult.problems;
+ final CategorizedProblem[] compilationResultProblems = compilationResult.problems;
if (compilationResultProblems.length == problemsCount) {
problems = compilationResultProblems;
} else {
- System.arraycopy(compilationResultProblems, 0, (problems = new IProblem[problemsCount]), 0, problemsCount);
+ System.arraycopy(compilationResultProblems, 0, (problems = new CategorizedProblem[problemsCount]), 0, problemsCount);
}
}
- return new RecordedParsingInformation(problems, compilationResult.lineSeparatorPositions, parser.getCommentsPositions());
+ return new RecordedParsingInformation(problems, compilationResult.getLineSeparatorPositions(), parser.getCommentsPositions());
}
public ASTNode[] parseClassBodyDeclarations(char[] source, Map settings, boolean recordParsingInformation) {
@@ -62,7 +62,9 @@
new DefaultProblemFactory(Locale.getDefault()));
CommentRecorderParser parser = new CommentRecorderParser(problemReporter, false);
-
+ parser.setMethodsFullRecovery(false);
+ parser.setStatementsRecovery(false);
+
ICompilationUnit sourceUnit =
new CompilationUnit(
source,
@@ -158,11 +160,11 @@
return result;
}
- public ConstructorDeclaration parseStatements(char[] source, Map settings, boolean recordParsingInformation) {
- return parseStatements(source, 0, source.length, settings, recordParsingInformation);
+ public ConstructorDeclaration parseStatements(char[] source, Map settings, boolean recordParsingInformation, boolean enabledStatementRecovery) {
+ return parseStatements(source, 0, source.length, settings, recordParsingInformation, enabledStatementRecovery);
}
- public ConstructorDeclaration parseStatements(char[] source, int offset, int length, Map settings, boolean recordParsingInformation) {
+ public ConstructorDeclaration parseStatements(char[] source, int offset, int length, Map settings, boolean recordParsingInformation, boolean enabledStatementRecovery) {
if (source == null) {
throw new IllegalArgumentException();
}
@@ -172,6 +174,8 @@
compilerOptions,
new DefaultProblemFactory(Locale.getDefault()));
CommentRecorderParser parser = new CommentRecorderParser(problemReporter, false);
+ parser.setMethodsFullRecovery(false);
+ parser.setStatementsRecovery(enabledStatementRecovery);
ICompilationUnit sourceUnit =
new CompilationUnit(
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CommentRecorderParser.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CommentRecorderParser.java
index 541adfc..cbbcc38 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CommentRecorderParser.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CommentRecorderParser.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -11,6 +11,7 @@
package org.eclipse.jdt.internal.core.util;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.parser.Parser;
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
@@ -70,7 +71,7 @@
break nextComment;
}
if (deprecated) {
- checkAndSetModifiers(AccDeprecated);
+ checkAndSetModifiers(ClassFileConstants.AccDeprecated);
}
// modify the modifier source start to point at the first comment
if (lastCommentIndex >= 0 && checkDeprecated) {
@@ -89,13 +90,6 @@
super.consumeClassHeader();
}
/* (non-Javadoc)
- * @see org.eclipse.jdt.internal.compiler.parser.Parser#consumeEmptyClassMemberDeclaration()
- */
- protected void consumeEmptyClassMemberDeclaration() {
- pushOnCommentsStack(0, this.scanner.commentPtr);
- super.consumeEmptyClassMemberDeclaration();
- }
- /* (non-Javadoc)
* @see org.eclipse.jdt.internal.compiler.parser.Parser#consumeEmptyTypeDeclaration()
*/
protected void consumeEmptyTypeDeclaration() {
@@ -170,7 +164,8 @@
while (index<lastCommentIndex && (immediateCommentEnd = -this.scanner.commentStops[index+1]) > 0){ // only tolerating non-javadoc comments (non-javadoc comment end positions are negative)
// is there any line break until the end of the immediate comment ? (thus only tolerating line comment)
immediateCommentEnd--; // comment end in one char too far
- if (this.scanner.getLineNumber(position) != this.scanner.getLineNumber(immediateCommentEnd)) break;
+ if (org.eclipse.jdt.internal.compiler.util.Util.getLineNumber(position, this.scanner.lineEnds, 0, this.scanner.linePtr)
+ != org.eclipse.jdt.internal.compiler.util.Util.getLineNumber(immediateCommentEnd, this.scanner.lineEnds, 0, this.scanner.linePtr)) break;
position = immediateCommentEnd;
validCount--; // flush this comment
index++;
@@ -223,6 +218,13 @@
/* (non-Javadoc)
* @see org.eclipse.jdt.internal.compiler.parser.Parser#initialize()
*/
+ public void initialize(boolean initializeNLS) {
+ super.initialize(initializeNLS);
+ this.commentPtr = -1;
+ }
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.compiler.parser.Parser#initialize()
+ */
public void initialize() {
super.initialize();
this.commentPtr = -1;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CommentRecorderScanner.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CommentRecorderScanner.java
index 90a5464..050cf09 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CommentRecorderScanner.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CommentRecorderScanner.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004 IBM Corporation and others.
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ConstantPool.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ConstantPool.java
index 91c18d4..1fc2355 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ConstantPool.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ConstantPool.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ConstantValueAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ConstantValueAttribute.java
index bda70f9..6456c31 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ConstantValueAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ConstantValueAttribute.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/DefaultBytecodeVisitor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/DefaultBytecodeVisitor.java
index e672880..f13e850 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/DefaultBytecodeVisitor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/DefaultBytecodeVisitor.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -1472,33 +1472,24 @@
*/
public void _invokespecial(int pc, int index, IConstantPoolEntry constantMethodref) {
dumpPcNumber(pc);
+ final String signature = returnMethodSignature(constantMethodref);
buffer.append(Messages.bind(Messages.classformat_invokespecial, new String[] {
OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.INVOKESPECIAL],
Integer.toString(index),
- Util.toString(
- constantMethodref.getClassName(),
- constantMethodref.getMethodName(),
- constantMethodref.getMethodDescriptor(),
- true,
- isCompact())
+ signature
}));
writeNewLine();
}
-
/**
* @see IBytecodeVisitor#_invokestatic(int, int, IConstantPoolEntry)
*/
public void _invokestatic(int pc, int index, IConstantPoolEntry constantMethodref) {
dumpPcNumber(pc);
+ final String signature = returnMethodSignature(constantMethodref);
buffer.append(Messages.bind(Messages.classformat_invokestatic, new String[] {
OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.INVOKESTATIC],
Integer.toString(index),
- Util.toString(
- constantMethodref.getClassName(),
- constantMethodref.getMethodName(),
- constantMethodref.getMethodDescriptor(),
- true,
- isCompact())
+ signature
}));
writeNewLine();
}
@@ -1508,15 +1499,11 @@
*/
public void _invokevirtual(int pc, int index, IConstantPoolEntry constantMethodref) {
dumpPcNumber(pc);
+ final String signature = returnMethodSignature(constantMethodref);
buffer.append(Messages.bind(Messages.classformat_invokevirtual,new String[] {
OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.INVOKEVIRTUAL],
Integer.toString(index),
- Util.toString(
- constantMethodref.getClassName(),
- constantMethodref.getMethodName(),
- constantMethodref.getMethodDescriptor(),
- true,
- isCompact())
+ signature
}));
writeNewLine();
}
@@ -1789,7 +1776,7 @@
buffer.append(Messages.bind(Messages.classformat_ldc_w_string, new String[] {
OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LDC_W],
Integer.toString(index),
- constantPoolEntry.getStringValue()
+ Disassembler.escapeString(constantPoolEntry.getStringValue())
}));
break;
case IConstantPoolConstant.CONSTANT_Class :
@@ -1826,7 +1813,7 @@
buffer.append(Messages.bind(Messages.classformat_ldc_w_string, new String[] {
OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LDC],
Integer.toString(index),
- constantPoolEntry.getStringValue()
+ Disassembler.escapeString(constantPoolEntry.getStringValue())
}));
break;
case IConstantPoolConstant.CONSTANT_Class :
@@ -2131,8 +2118,7 @@
buffer.append(Messages.bind(Messages.classformat_multianewarray, new String[] {
OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.MULTIANEWARRAY],
Integer.toString(index),
- returnConstantClassName(constantClass),
- appendDimensions(dimensions)
+ returnConstantClassName(constantClass)
}));
writeNewLine();
}
@@ -2428,21 +2414,23 @@
writeNewLine();
}
- private String appendDimensions(int dimensions) {
- StringBuffer stringBuffer = new StringBuffer();
- for (int i = 0; i < dimensions; i++) {
- stringBuffer.append(Messages.disassembler_arraydimensions);
- }
- return String.valueOf(stringBuffer);
- }
-
private boolean isCompact() {
return (this.mode & ClassFileBytesDisassembler.COMPACT) != 0;
}
private String returnConstantClassName(IConstantPoolEntry constantClass) {
- char[] classInfoName = constantClass.getClassInfoName();
- return returnClassName(classInfoName);
+ char[] className = constantClass.getClassInfoName();
+ if (className.length == 0) {
+ return EMPTY_CLASS_NAME;
+ }
+ switch(className[0]) {
+ case '[' :
+ StringBuffer classNameBuffer = new StringBuffer();
+ Util.appendTypeSignature(className, 0, classNameBuffer, isCompact());
+ return classNameBuffer.toString();
+ default:
+ return returnClassName(className);
+ }
}
private String returnClassName(char[] classInfoName) {
if (classInfoName.length == 0) {
@@ -2462,6 +2450,19 @@
return returnClassName(className);
}
+ private String returnMethodSignature(IConstantPoolEntry constantMethodref) {
+ final char[] methodDescriptor = constantMethodref.getMethodDescriptor();
+ CharOperation.replace(methodDescriptor, '$', '#');
+ final char[] signature = Util.toString(
+ constantMethodref.getClassName(),
+ constantMethodref.getMethodName(),
+ methodDescriptor,
+ true,
+ isCompact()).toCharArray();
+ CharOperation.replace(signature, '#', '$');
+ return String.valueOf(signature);
+ }
+
private void writeNewLine() {
this.buffer.append(lineSeparator);
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/DefaultStackMapFrame.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/DefaultStackMapFrame.java
new file mode 100755
index 0000000..94d2f3f
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/DefaultStackMapFrame.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.util;
+
+import org.eclipse.jdt.core.util.ClassFormatException;
+import org.eclipse.jdt.core.util.IConstantPool;
+import org.eclipse.jdt.core.util.IStackMapFrame;
+import org.eclipse.jdt.core.util.IVerificationTypeInfo;
+
+/**
+ * Default implementation of IStackMapFrame
+ */
+public class DefaultStackMapFrame extends ClassFileStruct implements IStackMapFrame {
+ private static final IVerificationTypeInfo[] EMPTY_LOCALS_OR_STACK_ITEMS = new IVerificationTypeInfo[0];
+
+ private int readOffset;
+ private int numberOfLocals;
+ private int numberOfStackItems;
+ private IVerificationTypeInfo[] locals;
+ private IVerificationTypeInfo[] stackItems;
+ private int offsetDelta;
+
+ /**
+ * Constructor for StackMapFrame.
+ *
+ * @param classFileBytes
+ * @param constantPool
+ * @param offset
+ * @throws ClassFormatException
+ */
+ public DefaultStackMapFrame(
+ byte[] classFileBytes,
+ IConstantPool constantPool,
+ int offset) throws ClassFormatException {
+ // FULL_FRAME
+ this.offsetDelta = u2At(classFileBytes, 0, offset);
+ int tempLocals = u2At(classFileBytes, 2, offset);
+ this.numberOfLocals = tempLocals;
+ if (tempLocals != 0) {
+ this.locals = new IVerificationTypeInfo[tempLocals];
+ this.readOffset = 4;
+ for (int i = 0; i < tempLocals; i++) {
+ VerificationInfo verificationInfo = new VerificationInfo(classFileBytes, constantPool, offset + this.readOffset);
+ this.locals[i] = verificationInfo;
+ this.readOffset += verificationInfo.sizeInBytes();
+ }
+ } else {
+ this.locals = EMPTY_LOCALS_OR_STACK_ITEMS;
+ }
+ int tempStackItems = u2At(classFileBytes, readOffset, offset);
+ this.readOffset += 2;
+ this.numberOfStackItems = tempStackItems;
+ if (tempStackItems != 0) {
+ this.stackItems = new IVerificationTypeInfo[tempStackItems];
+ for (int i = 0; i < tempStackItems; i++) {
+ VerificationInfo verificationInfo = new VerificationInfo(classFileBytes, constantPool, offset + this.readOffset);
+ this.stackItems[i] = verificationInfo;
+ this.readOffset += verificationInfo.sizeInBytes();
+ }
+ } else {
+ this.stackItems = EMPTY_LOCALS_OR_STACK_ITEMS;
+ }
+ }
+ int sizeInBytes() {
+ return this.readOffset;
+ }
+ public int getFrameType() {
+ return 255; // full_frame
+ }
+ public IVerificationTypeInfo[] getLocals() {
+ return this.locals;
+ }
+ public int getNumberOfLocals() {
+ return this.numberOfLocals;
+ }
+ public int getNumberOfStackItems() {
+ return this.numberOfStackItems;
+ }
+ public int getOffsetDelta() {
+ return this.offsetDelta;
+ }
+ public IVerificationTypeInfo[] getStackItems() {
+ return this.stackItems;
+ }
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java
index 1be2fa0..69dbaab 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,28 +10,15 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core.util;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.util.*;
-import org.eclipse.jdt.core.util.ClassFormatException;
-import org.eclipse.jdt.core.util.IClassFileAttribute;
-import org.eclipse.jdt.core.util.IClassFileReader;
-import org.eclipse.jdt.core.util.ICodeAttribute;
-import org.eclipse.jdt.core.util.IConstantPoolConstant;
-import org.eclipse.jdt.core.util.IConstantPoolEntry;
-import org.eclipse.jdt.core.util.IConstantValueAttribute;
-import org.eclipse.jdt.core.util.IExceptionAttribute;
-import org.eclipse.jdt.core.util.IExceptionTableEntry;
-import org.eclipse.jdt.core.util.IFieldInfo;
-import org.eclipse.jdt.core.util.IInnerClassesAttribute;
-import org.eclipse.jdt.core.util.IInnerClassesAttributeEntry;
-import org.eclipse.jdt.core.util.ILineNumberAttribute;
-import org.eclipse.jdt.core.util.ILocalVariableAttribute;
-import org.eclipse.jdt.core.util.ILocalVariableTableEntry;
-import org.eclipse.jdt.core.util.IMethodInfo;
-import org.eclipse.jdt.core.util.IModifierConstants;
-import org.eclipse.jdt.core.util.ISourceAttribute;
+import org.eclipse.jdt.internal.compiler.codegen.AttributeNamesConstants;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
/**
* Disassembler of .class files. It generates an output in the Writer that looks close to
@@ -39,13 +26,11 @@
*/
public class Disassembler extends ClassFileBytesDisassembler {
- private static final String EMPTY_CLASS_NAME = "\"\""; //$NON-NLS-1$
private static final char[] ANY_EXCEPTION = Messages.classfileformat_anyexceptionhandler.toCharArray();
- private static final String EMPTY_OUTPUT = ""; //$NON-NLS-1$
- private static final String VERSION_UNKNOWN = "unknown";//$NON-NLS-1$
+ private static final String VERSION_UNKNOWN = Messages.classfileformat_versionUnknown;
private boolean appendModifier(StringBuffer buffer, int accessFlags, int modifierConstant, String modifier, boolean firstModifier) {
- if ((accessFlags & modifierConstant) != 0) {
+ if ((accessFlags & modifierConstant) != 0) {
if (!firstModifier) {
buffer.append(Messages.disassembler_space);
}
@@ -57,65 +42,128 @@
return firstModifier;
}
+ private void decodeModifiers(StringBuffer buffer, int accessFlags, int[] checkBits) {
+ decodeModifiers(buffer, accessFlags, false, false, checkBits);
+ }
+
+ private void decodeModifiers(StringBuffer buffer, int accessFlags, boolean printDefault, boolean asBridge, int[] checkBits) {
+ if (checkBits == null) return;
+ boolean firstModifier = true;
+ for (int i = 0, max = checkBits.length; i < max; i++) {
+ switch(checkBits[i]) {
+ case IModifierConstants.ACC_PUBLIC :
+ firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_PUBLIC, "public", firstModifier); //$NON-NLS-1$
+ break;
+ case IModifierConstants.ACC_PROTECTED :
+ firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_PROTECTED, "protected", firstModifier); //$NON-NLS-1$
+ break;
+ case IModifierConstants.ACC_PRIVATE :
+ firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_PRIVATE, "private", firstModifier); //$NON-NLS-1$
+ break;
+ case IModifierConstants.ACC_ABSTRACT :
+ firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_ABSTRACT, "abstract", firstModifier); //$NON-NLS-1$
+ break;
+ case IModifierConstants.ACC_STATIC :
+ firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_STATIC, "static", firstModifier); //$NON-NLS-1$
+ break;
+ case IModifierConstants.ACC_FINAL :
+ firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_FINAL, "final", firstModifier); //$NON-NLS-1$
+ break;
+ case IModifierConstants.ACC_SYNCHRONIZED :
+ firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_SYNCHRONIZED, "synchronized", firstModifier); //$NON-NLS-1$
+ break;
+ case IModifierConstants.ACC_NATIVE :
+ firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_NATIVE, "native", firstModifier); //$NON-NLS-1$
+ break;
+ case IModifierConstants.ACC_STRICT :
+ firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_STRICT, "strictfp", firstModifier); //$NON-NLS-1$
+ break;
+ case IModifierConstants.ACC_TRANSIENT :
+ firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_TRANSIENT, "transient", firstModifier); //$NON-NLS-1$
+ break;
+ case IModifierConstants.ACC_VOLATILE :
+ // case IModifierConstants.ACC_BRIDGE :
+ if (asBridge) {
+ firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_BRIDGE, "bridge", firstModifier); //$NON-NLS-1$
+ } else {
+ firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_VOLATILE, "volatile", firstModifier); //$NON-NLS-1$
+ }
+ break;
+ case IModifierConstants.ACC_ENUM :
+ firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_ENUM, "enum", firstModifier); //$NON-NLS-1$
+ break;
+ }
+ }
+ if (!firstModifier) {
+ if (!printDefault) buffer.append(Messages.disassembler_space);
+ } else if (printDefault) {
+ // no modifier: package default visibility
+ buffer.append("default"); //$NON-NLS-1$
+ }
+ }
+
private void decodeModifiersForField(StringBuffer buffer, int accessFlags) {
- boolean firstModifier = true;
- firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_PUBLIC, "public", firstModifier); //$NON-NLS-1$
- firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_PROTECTED, "protected", firstModifier); //$NON-NLS-1$
- firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_PRIVATE, "private", firstModifier); //$NON-NLS-1$
- firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_STATIC, "static", firstModifier); //$NON-NLS-1$
- firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_FINAL, "final", firstModifier); //$NON-NLS-1$
- firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_TRANSIENT, "transient", firstModifier); //$NON-NLS-1$
- firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_VOLATILE, "volatile", firstModifier); //$NON-NLS-1$
- firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_ENUM, "enum", firstModifier); //$NON-NLS-1$
- if (!firstModifier) {
- buffer.append(Messages.disassembler_space);
- }
- }
+ decodeModifiers(buffer, accessFlags, new int[] {
+ IModifierConstants.ACC_PUBLIC,
+ IModifierConstants.ACC_PROTECTED,
+ IModifierConstants.ACC_PRIVATE,
+ IModifierConstants.ACC_STATIC,
+ IModifierConstants.ACC_FINAL,
+ IModifierConstants.ACC_TRANSIENT,
+ IModifierConstants.ACC_VOLATILE,
+ IModifierConstants.ACC_ENUM
+ });
+ }
- private final void decodeModifiersForInnerClasses(StringBuffer buffer, int accessFlags) {
- boolean firstModifier = true;
- firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_PUBLIC, "public", firstModifier); //$NON-NLS-1$
- firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_PROTECTED, "protected", firstModifier); //$NON-NLS-1$
- firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_PRIVATE, "private", firstModifier); //$NON-NLS-1$
- firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_ABSTRACT, "abstract", firstModifier); //$NON-NLS-1$
- firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_STATIC, "static", firstModifier); //$NON-NLS-1$
- firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_FINAL, "final", firstModifier); //$NON-NLS-1$
- if (!firstModifier) {
- buffer.append(Messages.disassembler_space);
- }
+ private void decodeModifiersForFieldForWorkingCopy(StringBuffer buffer, int accessFlags) {
+ decodeModifiers(buffer, accessFlags, new int[] {
+ IModifierConstants.ACC_PUBLIC,
+ IModifierConstants.ACC_PROTECTED,
+ IModifierConstants.ACC_PRIVATE,
+ IModifierConstants.ACC_STATIC,
+ IModifierConstants.ACC_FINAL,
+ IModifierConstants.ACC_TRANSIENT,
+ IModifierConstants.ACC_VOLATILE,
+ });
+ }
+
+ private final void decodeModifiersForInnerClasses(StringBuffer buffer, int accessFlags, boolean printDefault) {
+ decodeModifiers(buffer, accessFlags, printDefault, false, new int[] {
+ IModifierConstants.ACC_PUBLIC,
+ IModifierConstants.ACC_PROTECTED,
+ IModifierConstants.ACC_PRIVATE,
+ IModifierConstants.ACC_ABSTRACT,
+ IModifierConstants.ACC_STATIC,
+ IModifierConstants.ACC_FINAL,
+ });
}
private final void decodeModifiersForMethod(StringBuffer buffer, int accessFlags) {
- boolean firstModifier = true;
- firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_PUBLIC, "public", firstModifier); //$NON-NLS-1$
- firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_PROTECTED, "protected", firstModifier); //$NON-NLS-1$
- firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_PRIVATE, "private", firstModifier); //$NON-NLS-1$
- firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_ABSTRACT, "abstract", firstModifier); //$NON-NLS-1$
- firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_STATIC, "static", firstModifier); //$NON-NLS-1$
- firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_FINAL, "final", firstModifier); //$NON-NLS-1$
- firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_SYNCHRONIZED, "synchronized", firstModifier); //$NON-NLS-1$
- firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_NATIVE, "native", firstModifier); //$NON-NLS-1$
- firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_STRICT, "strictfp", firstModifier); //$NON-NLS-1$
- firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_BRIDGE, "bridge", firstModifier); //$NON-NLS-1$
- if (!firstModifier) {
- buffer.append(Messages.disassembler_space);
- }
+ decodeModifiers(buffer, accessFlags, false, true, new int[] {
+ IModifierConstants.ACC_PUBLIC,
+ IModifierConstants.ACC_PROTECTED,
+ IModifierConstants.ACC_PRIVATE,
+ IModifierConstants.ACC_ABSTRACT,
+ IModifierConstants.ACC_STATIC,
+ IModifierConstants.ACC_FINAL,
+ IModifierConstants.ACC_SYNCHRONIZED,
+ IModifierConstants.ACC_NATIVE,
+ IModifierConstants.ACC_STRICT,
+ IModifierConstants.ACC_BRIDGE,
+ });
}
private final void decodeModifiersForType(StringBuffer buffer, int accessFlags) {
- boolean firstModifier = true;
- firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_PUBLIC, "public", firstModifier); //$NON-NLS-1$
- firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_ABSTRACT, "abstract", firstModifier); //$NON-NLS-1$
- firstModifier = appendModifier(buffer, accessFlags, IModifierConstants.ACC_FINAL, "final", firstModifier); //$NON-NLS-1$
- if (!firstModifier) {
- buffer.append(Messages.disassembler_space);
- }
+ decodeModifiers(buffer, accessFlags, new int[] {
+ IModifierConstants.ACC_PUBLIC,
+ IModifierConstants.ACC_ABSTRACT,
+ IModifierConstants.ACC_FINAL,
+ });
}
-
- private String decodeStringValue(char[] chars) {
+ public static String escapeString(String s) {
StringBuffer buffer = new StringBuffer();
- for (int i = 0, max = chars.length; i < max; i++) {
- char c = chars[i];
+ for (int i = 0, max = s.length(); i < max; i++) {
+ char c = s.charAt(i);
switch(c) {
case '\b' :
buffer.append("\\b"); //$NON-NLS-1$
@@ -132,15 +180,6 @@
case '\r' :
buffer.append("\\r"); //$NON-NLS-1$
break;
- case '\"':
- buffer.append("\\\""); //$NON-NLS-1$
- break;
- case '\'':
- buffer.append("\\\'"); //$NON-NLS-1$
- break;
- case '\\':
- buffer.append("\\\\"); //$NON-NLS-1$
- break;
case '\0' :
buffer.append("\\0"); //$NON-NLS-1$
break;
@@ -172,7 +211,58 @@
return buffer.toString();
}
- private String decodeStringValue(String s) {
+ static String decodeStringValue(char[] chars) {
+ StringBuffer buffer = new StringBuffer();
+ for (int i = 0, max = chars.length; i < max; i++) {
+ char c = chars[i];
+ switch(c) {
+ case '\b' :
+ buffer.append("\\b"); //$NON-NLS-1$
+ break;
+ case '\t' :
+ buffer.append("\\t"); //$NON-NLS-1$
+ break;
+ case '\n' :
+ buffer.append("\\n"); //$NON-NLS-1$
+ break;
+ case '\f' :
+ buffer.append("\\f"); //$NON-NLS-1$
+ break;
+ case '\r' :
+ buffer.append("\\r"); //$NON-NLS-1$
+ break;
+ case '\0' :
+ buffer.append("\\0"); //$NON-NLS-1$
+ break;
+ case '\1' :
+ buffer.append("\\1"); //$NON-NLS-1$
+ break;
+ case '\2' :
+ buffer.append("\\2"); //$NON-NLS-1$
+ break;
+ case '\3' :
+ buffer.append("\\3"); //$NON-NLS-1$
+ break;
+ case '\4' :
+ buffer.append("\\4"); //$NON-NLS-1$
+ break;
+ case '\5' :
+ buffer.append("\\5"); //$NON-NLS-1$
+ break;
+ case '\6' :
+ buffer.append("\\6"); //$NON-NLS-1$
+ break;
+ case '\7' :
+ buffer.append("\\7"); //$NON-NLS-1$
+ break;
+ default:
+ buffer.append(c);
+ }
+ }
+ return buffer.toString();
+ }
+
+ static String decodeStringValue(String s) {
return decodeStringValue(s.toCharArray());
}
@@ -180,14 +270,32 @@
* @see org.eclipse.jdt.core.util.ClassFileBytesDisassembler#disassemble(byte[], java.lang.String)
*/
public String disassemble(byte[] classFileBytes, String lineSeparator) throws ClassFormatException {
- return disassemble(new ClassFileReader(classFileBytes, IClassFileReader.ALL), lineSeparator, ClassFileBytesDisassembler.DEFAULT);
+ try {
+ return disassemble(new ClassFileReader(classFileBytes, IClassFileReader.ALL), lineSeparator, ClassFileBytesDisassembler.DEFAULT);
+ } catch (ArrayIndexOutOfBoundsException e) {
+ StringWriter stringWriter = new StringWriter();
+ PrintWriter writer = new PrintWriter(stringWriter);
+ e.printStackTrace(writer);
+ writer.flush();
+ writer.close();
+ throw new ClassFormatException(String.valueOf(stringWriter.getBuffer()));
+ }
}
/**
* @see org.eclipse.jdt.core.util.ClassFileBytesDisassembler#disassemble(byte[], java.lang.String, int)
*/
public String disassemble(byte[] classFileBytes, String lineSeparator, int mode) throws ClassFormatException {
- return disassemble(new ClassFileReader(classFileBytes, IClassFileReader.ALL), lineSeparator, mode);
+ try {
+ return disassemble(new ClassFileReader(classFileBytes, IClassFileReader.ALL), lineSeparator, mode);
+ } catch (ArrayIndexOutOfBoundsException e) {
+ StringWriter stringWriter = new StringWriter();
+ PrintWriter writer = new PrintWriter(stringWriter);
+ e.printStackTrace(writer);
+ writer.flush();
+ writer.close();
+ throw new ClassFormatException(String.valueOf(stringWriter.getBuffer()));
+ }
}
private void disassemble(IAnnotation annotation, StringBuffer buffer, String lineSeparator, int tabNumber) {
@@ -321,20 +429,97 @@
}));
}
+ private void disassembleEnumConstructor(IClassFileReader classFileReader, char[] className, IMethodInfo methodInfo, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
+ writeNewLine(buffer, lineSeparator, tabNumber);
+ final ICodeAttribute codeAttribute = methodInfo.getCodeAttribute();
+ char[] methodDescriptor = methodInfo.getDescriptor();
+ final IClassFileAttribute runtimeVisibleAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS);
+ final IClassFileAttribute runtimeInvisibleAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS);
+ // disassemble compact version of annotations
+ if (runtimeInvisibleAnnotationsAttribute != null) {
+ disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1, mode);
+ writeNewLine(buffer, lineSeparator, tabNumber);
+ }
+ if (runtimeVisibleAnnotationsAttribute != null) {
+ disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1, mode);
+ writeNewLine(buffer, lineSeparator, tabNumber);
+ }
+ final int accessFlags = methodInfo.getAccessFlags();
+ decodeModifiersForMethod(buffer, accessFlags & IModifierConstants.ACC_PRIVATE);
+ CharOperation.replace(methodDescriptor, '/', '.');
+ final boolean isVarArgs = (accessFlags & IModifierConstants.ACC_VARARGS) != 0;
+ final char[] signature = Signature.toCharArray(methodDescriptor, returnClassName(className, '.', COMPACT), getParameterNames(methodDescriptor, codeAttribute, accessFlags) , !checkMode(mode, COMPACT), false, isVarArgs);
+ int index = CharOperation.indexOf(',', signature);
+ index = CharOperation.indexOf(',', signature, index + 1);
+ buffer.append(signature, 0, CharOperation.indexOf('(', signature) + 1);
+ buffer.append(signature, index + 2, signature.length - index - 2);
+ IExceptionAttribute exceptionAttribute = methodInfo.getExceptionAttribute();
+ if (exceptionAttribute != null) {
+ buffer.append(" throws "); //$NON-NLS-1$
+ char[][] exceptionNames = exceptionAttribute.getExceptionNames();
+ int length = exceptionNames.length;
+ for (int i = 0; i < length; i++) {
+ if (i != 0) {
+ buffer
+ .append(Messages.disassembler_comma)
+ .append(Messages.disassembler_space);
+ }
+ char[] exceptionName = exceptionNames[i];
+ CharOperation.replace(exceptionName, '/', '.');
+ buffer.append(returnClassName(exceptionName, '.', mode));
+ }
+ }
+ if (((accessFlags & IModifierConstants.ACC_NATIVE) == 0)
+ && ((accessFlags & IModifierConstants.ACC_ABSTRACT) == 0)) {
+ buffer.append(" {"); //$NON-NLS-1$
+ final char[] returnType = Signature.getReturnType(methodDescriptor);
+ if (returnType.length == 1) {
+ switch(returnType[0]) {
+ case 'V' :
+ writeNewLine(buffer, lineSeparator, tabNumber);
+ break;
+ case 'I' :
+ case 'B' :
+ case 'J' :
+ case 'D' :
+ case 'F' :
+ case 'S' :
+ case 'C' :
+ writeNewLine(buffer, lineSeparator, tabNumber + 1);
+ buffer.append("return 0;"); //$NON-NLS-1$
+ writeNewLine(buffer, lineSeparator, tabNumber);
+ break;
+ default :
+ // boolean
+ writeNewLine(buffer, lineSeparator, tabNumber + 1);
+ buffer.append("return false;"); //$NON-NLS-1$
+ writeNewLine(buffer, lineSeparator, tabNumber);
+ }
+ } else {
+ // object
+ writeNewLine(buffer, lineSeparator, tabNumber + 1);
+ buffer.append("return null;"); //$NON-NLS-1$
+ writeNewLine(buffer, lineSeparator, tabNumber);
+ }
+ buffer.append('}');
+ } else {
+ buffer.append(';');
+ }
+ }
+
/**
* Disassemble a method info header
*/
- private void disassemble(IClassFileReader classFileReader, IMethodInfo methodInfo, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
+ private void disassemble(IClassFileReader classFileReader, char[] className, IMethodInfo methodInfo, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
writeNewLine(buffer, lineSeparator, tabNumber);
- ICodeAttribute codeAttribute = methodInfo.getCodeAttribute();
- char[] methodDescriptor = methodInfo.getDescriptor();
- IClassFileAttribute classFileAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.SIGNATURE);
- ISignatureAttribute signatureAttribute = (ISignatureAttribute) classFileAttribute;
- IClassFileAttribute runtimeVisibleAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS);
- IClassFileAttribute runtimeInvisibleAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS);
- IClassFileAttribute runtimeVisibleParameterAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS);
- IClassFileAttribute runtimeInvisibleParameterAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS);
- IClassFileAttribute annotationDefaultAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.ANNOTATION_DEFAULT);
+ final ICodeAttribute codeAttribute = methodInfo.getCodeAttribute();
+ final char[] methodDescriptor = methodInfo.getDescriptor();
+ final ISignatureAttribute signatureAttribute = (ISignatureAttribute) Util.getAttribute(methodInfo, IAttributeNamesConstants.SIGNATURE);
+ final IClassFileAttribute runtimeVisibleAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS);
+ final IClassFileAttribute runtimeInvisibleAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS);
+ final IClassFileAttribute runtimeVisibleParameterAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS);
+ final IClassFileAttribute runtimeInvisibleParameterAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS);
+ final IClassFileAttribute annotationDefaultAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.ANNOTATION_DEFAULT);
if (checkMode(mode, SYSTEM | DETAILED)) {
buffer.append(Messages.bind(Messages.classfileformat_methoddescriptor,
new String[] {
@@ -361,55 +546,112 @@
if (checkMode(mode, DETAILED)) {
// disassemble compact version of annotations
if (runtimeInvisibleAnnotationsAttribute != null) {
- disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1);
+ disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1, mode);
writeNewLine(buffer, lineSeparator, tabNumber);
}
if (runtimeVisibleAnnotationsAttribute != null) {
- disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1);
+ disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1, mode);
writeNewLine(buffer, lineSeparator, tabNumber);
}
}
- int accessFlags = methodInfo.getAccessFlags();
+ final int accessFlags = methodInfo.getAccessFlags();
decodeModifiersForMethod(buffer, accessFlags);
- if (methodInfo.isSynthetic()) {
+ if (methodInfo.isSynthetic() && !checkMode(mode, WORKING_COPY)) {
buffer.append("synthetic"); //$NON-NLS-1$
buffer.append(Messages.disassembler_space);
}
CharOperation.replace(methodDescriptor, '/', '.');
- char[] methodName;
+ final boolean isVarArgs = isVarArgs(methodInfo);
if (methodInfo.isConstructor()) {
- methodName = classFileReader.getClassName();
- buffer.append(Signature.toCharArray(methodDescriptor, methodName, getParameterNames(methodDescriptor, codeAttribute, accessFlags) , false, false, (accessFlags & IModifierConstants.ACC_VARARGS) != 0));
+ if (checkMode(mode, WORKING_COPY) && signatureAttribute != null) {
+ final char[] signature = signatureAttribute.getSignature();
+ CharOperation.replace(signature, '/', '.');
+ disassembleGenericSignature(mode, buffer, signature);
+ buffer.append(' ');
+ buffer.append(Signature.toCharArray(signature, returnClassName(className, '.', COMPACT), getParameterNames(methodDescriptor, codeAttribute, accessFlags) , !checkMode(mode, COMPACT), false, isVarArgs));
+ } else {
+ buffer.append(Signature.toCharArray(methodDescriptor, returnClassName(className, '.', COMPACT), getParameterNames(methodDescriptor, codeAttribute, accessFlags) , !checkMode(mode, COMPACT), false, isVarArgs));
+ }
} else if (methodInfo.isClinit()) {
buffer.append(Messages.bind(Messages.classfileformat_clinitname));
} else {
- methodName = methodInfo.getName();
- buffer.append(Signature.toCharArray(methodDescriptor, methodName, getParameterNames(methodDescriptor, codeAttribute, accessFlags) , false, true, (accessFlags & IModifierConstants.ACC_VARARGS) != 0));
+ if (checkMode(mode, WORKING_COPY) && signatureAttribute != null) {
+ final char[] signature = signatureAttribute.getSignature();
+ CharOperation.replace(signature, '/', '.');
+ disassembleGenericSignature(mode, buffer, signature);
+ buffer.append(' ');
+ buffer.append(Signature.toCharArray(signature, methodInfo.getName(), getParameterNames(methodDescriptor, codeAttribute, accessFlags) , !checkMode(mode, COMPACT), true, isVarArgs));
+ } else {
+ buffer.append(Signature.toCharArray(methodDescriptor, methodInfo.getName(), getParameterNames(methodDescriptor, codeAttribute, accessFlags) , !checkMode(mode, COMPACT), true, isVarArgs));
+ }
}
IExceptionAttribute exceptionAttribute = methodInfo.getExceptionAttribute();
if (exceptionAttribute != null) {
buffer.append(" throws "); //$NON-NLS-1$
char[][] exceptionNames = exceptionAttribute.getExceptionNames();
int length = exceptionNames.length;
- for (int i = 0; i < length - 1; i++) {
+ for (int i = 0; i < length; i++) {
+ if (i != 0) {
+ buffer
+ .append(Messages.disassembler_comma)
+ .append(Messages.disassembler_space);
+ }
char[] exceptionName = exceptionNames[i];
CharOperation.replace(exceptionName, '/', '.');
- buffer
- .append(returnClassName(exceptionName, '.', mode))
- .append(Messages.disassembler_comma)
- .append(Messages.disassembler_space);
+ buffer.append(returnClassName(exceptionName, '.', mode));
}
- char[] exceptionName = exceptionNames[length - 1];
- CharOperation.replace(exceptionName, '/', '.');
- buffer.append(returnClassName(exceptionName, '.', mode));
}
if (checkMode(mode, DETAILED)) {
if (annotationDefaultAttribute != null) {
buffer.append(" default "); //$NON-NLS-1$
- disassembleAsModifier((IAnnotationDefaultAttribute) annotationDefaultAttribute, buffer, lineSeparator, tabNumber);
+ disassembleAsModifier((IAnnotationDefaultAttribute) annotationDefaultAttribute, buffer, lineSeparator, tabNumber, mode);
}
}
- buffer.append(Messages.disassembler_endofmethodheader);
+ if (checkMode(mode, WORKING_COPY)) {
+ // put the annotation default attribute if needed
+ if (annotationDefaultAttribute != null) {
+ buffer.append(" default "); //$NON-NLS-1$
+ disassembleAsModifier((IAnnotationDefaultAttribute) annotationDefaultAttribute, buffer, lineSeparator, tabNumber, mode);
+ }
+ if (((accessFlags & IModifierConstants.ACC_NATIVE) == 0)
+ && ((accessFlags & IModifierConstants.ACC_ABSTRACT) == 0)) {
+ buffer.append(" {"); //$NON-NLS-1$
+ final char[] returnType = Signature.getReturnType(methodDescriptor);
+ if (returnType.length == 1) {
+ switch(returnType[0]) {
+ case 'V' :
+ writeNewLine(buffer, lineSeparator, tabNumber);
+ break;
+ case 'I' :
+ case 'B' :
+ case 'J' :
+ case 'D' :
+ case 'F' :
+ case 'S' :
+ case 'C' :
+ writeNewLine(buffer, lineSeparator, tabNumber + 1);
+ buffer.append("return 0;"); //$NON-NLS-1$
+ writeNewLine(buffer, lineSeparator, tabNumber);
+ break;
+ default :
+ // boolean
+ writeNewLine(buffer, lineSeparator, tabNumber + 1);
+ buffer.append("return false;"); //$NON-NLS-1$
+ writeNewLine(buffer, lineSeparator, tabNumber);
+ }
+ } else {
+ // object
+ writeNewLine(buffer, lineSeparator, tabNumber + 1);
+ buffer.append("return null;"); //$NON-NLS-1$
+ writeNewLine(buffer, lineSeparator, tabNumber);
+ }
+ buffer.append('}');
+ } else {
+ buffer.append(';');
+ }
+ } else {
+ buffer.append(Messages.disassembler_endofmethodheader);
+ }
if (checkMode(mode, SYSTEM | DETAILED)) {
if (codeAttribute != null) {
@@ -474,13 +716,21 @@
* @return the disassembled string of the IClassFileReader according to the mode
*/
public String disassemble(IClassFileReader classFileReader, String lineSeparator, int mode) {
- if (classFileReader == null) return EMPTY_OUTPUT;
+ if (classFileReader == null) return org.eclipse.jdt.internal.compiler.util.Util.EMPTY_STRING;
+ char[] className = classFileReader.getClassName();
+ if (className == null) {
+ // incomplete initialization. We cannot go further.
+ return org.eclipse.jdt.internal.compiler.util.Util.EMPTY_STRING;
+ }
+ className= CharOperation.replaceOnCopy(className, '/', '.');
+ final int classNameLength = className.length;
+ final int accessFlags = classFileReader.getAccessFlags();
+ final boolean isEnum = (accessFlags & IModifierConstants.ACC_ENUM) != 0;
+
StringBuffer buffer = new StringBuffer();
-
ISourceAttribute sourceAttribute = classFileReader.getSourceFileAttribute();
IClassFileAttribute classFileAttribute = Util.getAttribute(classFileReader, IAttributeNamesConstants.SIGNATURE);
ISignatureAttribute signatureAttribute = (ISignatureAttribute) classFileAttribute;
- final int accessFlags = classFileReader.getAccessFlags();
if (checkMode(mode, SYSTEM | DETAILED)) {
int minorVersion = classFileReader.getMinorVersion();
int majorVersion = classFileReader.getMajorVersion();
@@ -489,7 +739,7 @@
buffer.append(Messages.disassembler_sourceattributeheader);
buffer.append(sourceAttribute.getSourceFileName());
}
- String versionNumber = VERSION_UNKNOWN;//$NON-NLS-1$
+ String versionNumber = VERSION_UNKNOWN;
if (minorVersion == 3 && majorVersion == 45) {
versionNumber = JavaCore.VERSION_1_1;
} else if (minorVersion == 0 && majorVersion == 46) {
@@ -500,6 +750,10 @@
versionNumber = JavaCore.VERSION_1_4;
} else if (minorVersion == 0 && majorVersion == 49) {
versionNumber = JavaCore.VERSION_1_5;
+ } else if (minorVersion == 0 && majorVersion == 50) {
+ versionNumber = JavaCore.VERSION_1_6;
+ } else if (minorVersion == 0 && majorVersion == 51) {
+ versionNumber = JavaCore.VERSION_1_7;
}
buffer.append(
Messages.bind(Messages.classfileformat_versiondetails,
@@ -510,7 +764,7 @@
((accessFlags & IModifierConstants.ACC_SUPER) != 0
? Messages.classfileformat_superflagisset
: Messages.classfileformat_superflagisnotset)
- + (isDeprecated(classFileReader) ? ", deprecated" : EMPTY_OUTPUT)//$NON-NLS-1$
+ + (isDeprecated(classFileReader) ? ", deprecated" : org.eclipse.jdt.internal.compiler.util.Util.EMPTY_STRING)//$NON-NLS-1$
}));
writeNewLine(buffer, lineSeparator, 0);
if (signatureAttribute != null) {
@@ -518,12 +772,16 @@
writeNewLine(buffer, lineSeparator, 0);
}
}
- char[] className = classFileReader.getClassName();
- if (className == null) {
- // incomplete initialization. We cannot go further.
- return buffer.toString();
- }
+ final int lastDotIndexInClassName = CharOperation.lastIndexOf('.', className);
+ if (checkMode(mode, WORKING_COPY) && lastDotIndexInClassName != -1) {
+ // we print a package declaration
+ buffer.append("package ");//$NON-NLS-1$
+ buffer.append(className, 0, lastDotIndexInClassName);
+ buffer.append(';');
+ writeNewLine(buffer, lineSeparator, 0);
+ }
+
IInnerClassesAttribute innerClassesAttribute = classFileReader.getInnerClassesAttribute();
IClassFileAttribute runtimeVisibleAnnotationsAttribute = Util.getAttribute(classFileReader, IAttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS);
IClassFileAttribute runtimeInvisibleAnnotationsAttribute = Util.getAttribute(classFileReader, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS);
@@ -531,80 +789,105 @@
if (checkMode(mode, DETAILED)) {
// disassemble compact version of annotations
if (runtimeInvisibleAnnotationsAttribute != null) {
- disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, 1);
+ disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, 1, mode);
writeNewLine(buffer, lineSeparator, 0);
}
if (runtimeVisibleAnnotationsAttribute != null) {
- disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, 1);
+ disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, 1, mode);
writeNewLine(buffer, lineSeparator, 0);
}
}
boolean decoded = false;
- if (innerClassesAttribute != null) {
- // search the right entry
- IInnerClassesAttributeEntry[] entries = innerClassesAttribute.getInnerClassAttributesEntries();
- for (int i = 0, max = entries.length; i < max ; i++) {
- IInnerClassesAttributeEntry entry = entries[i];
- char[] innerClassName = entry.getInnerClassName();
- if (innerClassName != null) {
- if (CharOperation.equals(classFileReader.getClassName(), innerClassName)) {
- decodeModifiersForInnerClasses(buffer, entry.getAccessFlags());
- decoded = true;
+ if (isEnum && checkMode(mode, WORKING_COPY)) {
+ decodeModifiersForType(buffer, accessFlags & IModifierConstants.ACC_PUBLIC);
+ } else {
+ if (innerClassesAttribute != null) {
+ // search the right entry
+ IInnerClassesAttributeEntry[] entries = innerClassesAttribute.getInnerClassAttributesEntries();
+ for (int i = 0, max = entries.length; i < max ; i++) {
+ IInnerClassesAttributeEntry entry = entries[i];
+ char[] innerClassName = entry.getInnerClassName();
+ if (innerClassName != null) {
+ if (CharOperation.equals(classFileReader.getClassName(), innerClassName)) {
+ decodeModifiersForInnerClasses(buffer, entry.getAccessFlags(), false);
+ decoded = true;
+ }
}
}
}
- }
- if (!decoded) {
- decodeModifiersForType(buffer, accessFlags);
- if (isSynthetic(classFileReader)) {
- buffer.append("synthetic"); //$NON-NLS-1$
- buffer.append(Messages.disassembler_space);
+ if (!decoded) {
+ decodeModifiersForType(buffer, accessFlags);
+ if (isSynthetic(classFileReader)) {
+ buffer.append("synthetic"); //$NON-NLS-1$
+ buffer.append(Messages.disassembler_space);
+ }
}
}
- if ((accessFlags & IModifierConstants.ACC_ENUM) != 0) {
+ final boolean isAnnotation = (accessFlags & IModifierConstants.ACC_ANNOTATION) != 0;
+ boolean isInterface = false;
+ if (isEnum) {
buffer.append("enum "); //$NON-NLS-1$
} else if (classFileReader.isClass()) {
buffer.append("class "); //$NON-NLS-1$
} else {
- if ((accessFlags & IModifierConstants.ACC_ANNOTATION) != 0) {
+ if (isAnnotation) {
buffer.append("@"); //$NON-NLS-1$
}
buffer.append("interface "); //$NON-NLS-1$
+ isInterface = true;
}
- CharOperation.replace(className, '/', '.');
- buffer.append(className);
+
+ if (checkMode(mode, WORKING_COPY)) {
+ // we print the simple class name
+ final int start = lastDotIndexInClassName + 1;
+ buffer.append(className, start, classNameLength - start);
+ className = CharOperation.subarray(className, start, classNameLength);
+ if (signatureAttribute != null) {
+ disassembleGenericSignature(mode, buffer, signatureAttribute.getSignature());
+ }
+ } else {
+ buffer.append(className);
+ }
char[] superclassName = classFileReader.getSuperclassName();
if (superclassName != null) {
- buffer.append(" extends "); //$NON-NLS-1$
CharOperation.replace(superclassName, '/', '.');
- buffer.append(returnClassName(superclassName, '.', mode));
- }
- char[][] superclassInterfaces = classFileReader.getInterfaceNames();
- int length = superclassInterfaces.length;
- if (length != 0) {
- buffer.append(" implements "); //$NON-NLS-1$
- for (int i = 0; i < length - 1; i++) {
- char[] superinterface = superclassInterfaces[i];
- CharOperation.replace(superinterface, '/', '.');
- buffer
- .append(returnClassName(superinterface, '.', mode))
- .append(Messages.disassembler_comma)
- .append(Messages.disassembler_space);
+ if (!isJavaLangObject(superclassName) && !isEnum) {
+ buffer.append(" extends "); //$NON-NLS-1$
+ buffer.append(returnClassName(superclassName, '.', mode));
}
- char[] superinterface = superclassInterfaces[length - 1];
- CharOperation.replace(superinterface, '/', '.');
- buffer.append(returnClassName(superinterface, '.', mode));
+ }
+ if (!isAnnotation || !checkMode(mode, WORKING_COPY)) {
+ char[][] superclassInterfaces = classFileReader.getInterfaceNames();
+ int length = superclassInterfaces.length;
+ if (length != 0) {
+ if (isInterface) {
+ buffer.append(" extends "); //$NON-NLS-1$
+ } else {
+ buffer.append(" implements "); //$NON-NLS-1$
+ }
+ for (int i = 0; i < length; i++) {
+ if (i != 0) {
+ buffer
+ .append(Messages.disassembler_comma)
+ .append(Messages.disassembler_space);
+ }
+ char[] superinterface = superclassInterfaces[i];
+ CharOperation.replace(superinterface, '/', '.');
+ buffer
+ .append(returnClassName(superinterface, '.', mode));
+ }
+ }
}
buffer.append(Messages.bind(Messages.disassembler_opentypedeclaration));
if (checkMode(mode, SYSTEM)) {
disassemble(classFileReader.getConstantPool(), buffer, lineSeparator, 1);
}
- disassembleTypeMembers(classFileReader, buffer, lineSeparator, 1, mode);
+ disassembleTypeMembers(classFileReader, className, buffer, lineSeparator, 1, mode, isEnum);
if (checkMode(mode, SYSTEM | DETAILED)) {
IClassFileAttribute[] attributes = classFileReader.getAttributes();
- length = attributes.length;
+ int length = attributes.length;
IEnclosingMethodAttribute enclosingMethodAttribute = getEnclosingMethodAttribute(classFileReader);
int remainingAttributesLength = length;
if (innerClassesAttribute != null) {
@@ -656,7 +939,54 @@
buffer.append(Messages.disassembler_closetypedeclaration);
return buffer.toString();
}
+
+ private void disassembleGenericSignature(int mode, StringBuffer buffer, final char[] signature) {
+ CharOperation.replace(signature, '/', '.');
+ final char[][] typeParameters = Signature.getTypeParameters(signature);
+ final int typeParametersLength = typeParameters.length;
+ if (typeParametersLength != 0) {
+ buffer.append('<');
+ for (int i = 0; i < typeParametersLength; i++) {
+ if (i != 0) {
+ buffer.append(Messages.disassembler_comma);
+ }
+ // extract the name
+ buffer.append(typeParameters[i], 0, CharOperation.indexOf(':', typeParameters[i]));
+ final char[][] bounds = Signature.getTypeParameterBounds(typeParameters[i]);
+ final int boundsLength = bounds.length;
+ if (boundsLength != 0) {
+ if (boundsLength == 1) {
+ final char[] bound = bounds[0];
+ // check if this is java.lang.Object
+ if (!isJavaLangObject(Signature.toCharArray(bound))) {
+ buffer.append(" extends "); //$NON-NLS-1$
+ buffer.append(returnClassName(Signature.toCharArray(bound), '.', mode));
+ }
+ } else {
+ buffer.append(" extends "); //$NON-NLS-1$
+ for (int j= 0; j < boundsLength; j++) {
+ if (j != 0) {
+ buffer.append(" & "); //$NON-NLS-1$
+ }
+ buffer.append(returnClassName(Signature.toCharArray(bounds[j]), '.', mode));
+ }
+ }
+ }
+ }
+ buffer.append('>');
+ }
+ }
+
+ private boolean isJavaLangObject(final char[] className) {
+ return CharOperation.equals(TypeConstants.JAVA_LANG_OBJECT, CharOperation.splitOn('.', className));
+ }
+ private boolean isVarArgs(IMethodInfo methodInfo) {
+ int accessFlags = methodInfo.getAccessFlags();
+ if ((accessFlags & IModifierConstants.ACC_VARARGS) != 0) return true;
+ // check the presence of the unspecified Varargs attribute
+ return Util.getAttribute(methodInfo, AttributeNamesConstants.VarargsName) != null;
+ }
private void disassemble(ICodeAttribute codeAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
writeNewLine(buffer, lineSeparator, tabNumber - 1);
DefaultBytecodeVisitor visitor = new DefaultBytecodeVisitor(codeAttribute, buffer, lineSeparator, tabNumber, mode);
@@ -667,19 +997,25 @@
buffer.append(Messages.classformat_classformatexception);
writeNewLine(buffer, lineSeparator, tabNumber + 1);
}
- int exceptionTableLength = codeAttribute.getExceptionTableLength();
+ final int exceptionTableLength = codeAttribute.getExceptionTableLength();
+ boolean isFirstAttribute = true;
if (exceptionTableLength != 0) {
final int tabNumberForExceptionAttribute = tabNumber + 2;
+ isFirstAttribute = false;
dumpTab(tabNumberForExceptionAttribute, buffer);
- IExceptionTableEntry[] exceptionTableEntries = codeAttribute.getExceptionTable();
+ final IExceptionTableEntry[] exceptionTableEntries = codeAttribute.getExceptionTable();
buffer.append(Messages.disassembler_exceptiontableheader);
writeNewLine(buffer, lineSeparator, tabNumberForExceptionAttribute + 1);
- for (int i = 0; i < exceptionTableLength - 1; i++) {
+ for (int i = 0; i < exceptionTableLength; i++) {
+ if (i != 0) {
+ writeNewLine(buffer, lineSeparator, tabNumberForExceptionAttribute + 1);
+ }
IExceptionTableEntry exceptionTableEntry = exceptionTableEntries[i];
char[] catchType;
if (exceptionTableEntry.getCatchTypeIndex() != 0) {
catchType = exceptionTableEntry.getCatchType();
CharOperation.replace(catchType, '/', '.');
+ catchType = returnClassName(catchType, '.', mode);
} else {
catchType = ANY_EXCEPTION;
}
@@ -690,56 +1026,49 @@
Integer.toString(exceptionTableEntry.getHandlerPC()),
new String(catchType)
}));
- writeNewLine(buffer, lineSeparator, tabNumberForExceptionAttribute + 1);
}
- IExceptionTableEntry exceptionTableEntry = exceptionTableEntries[exceptionTableLength - 1];
- char[] catchType;
- if (exceptionTableEntry.getCatchTypeIndex() != 0) {
- catchType = exceptionTableEntry.getCatchType();
- CharOperation.replace(catchType, '/', '.');
- } else {
- catchType = ANY_EXCEPTION;
- }
- buffer.append(Messages.bind(Messages.classfileformat_exceptiontableentry,
- new String[] {
- Integer.toString(exceptionTableEntry.getStartPC()),
- Integer.toString(exceptionTableEntry.getEndPC()),
- Integer.toString(exceptionTableEntry.getHandlerPC()),
- new String(catchType)
- }));
- writeNewLine(buffer, lineSeparator, 0);
}
- ILineNumberAttribute lineNumberAttribute = codeAttribute.getLineNumberAttribute();
- int lineAttributeLength = lineNumberAttribute == null ? 0 : lineNumberAttribute.getLineNumberTableLength();
+ final ILineNumberAttribute lineNumberAttribute = codeAttribute.getLineNumberAttribute();
+ final int lineAttributeLength = lineNumberAttribute == null ? 0 : lineNumberAttribute.getLineNumberTableLength();
if (lineAttributeLength != 0) {
int tabNumberForLineAttribute = tabNumber + 2;
- dumpTab(tabNumberForLineAttribute, buffer);
+ if (!isFirstAttribute) {
+ writeNewLine(buffer, lineSeparator, tabNumberForLineAttribute);
+ } else {
+ dumpTab(tabNumberForLineAttribute, buffer);
+ isFirstAttribute = false;
+ }
buffer.append(Messages.disassembler_linenumberattributeheader);
writeNewLine(buffer, lineSeparator, tabNumberForLineAttribute + 1);
int[][] lineattributesEntries = lineNumberAttribute.getLineNumberTable();
- for (int i = 0; i < lineAttributeLength - 1; i++) {
+ for (int i = 0; i < lineAttributeLength; i++) {
+ if (i != 0) {
+ writeNewLine(buffer, lineSeparator, tabNumberForLineAttribute + 1);
+ }
buffer.append(Messages.bind(Messages.classfileformat_linenumbertableentry,
new String[] {
Integer.toString(lineattributesEntries[i][0]),
Integer.toString(lineattributesEntries[i][1])
}));
- writeNewLine(buffer, lineSeparator, tabNumberForLineAttribute + 1);
}
- buffer.append(Messages.bind(Messages.classfileformat_linenumbertableentry,
- new String[] {
- Integer.toString(lineattributesEntries[lineAttributeLength - 1][0]),
- Integer.toString(lineattributesEntries[lineAttributeLength - 1][1])
- }));
}
- ILocalVariableAttribute localVariableAttribute = codeAttribute.getLocalVariableAttribute();
- int localVariableAttributeLength = localVariableAttribute == null ? 0 : localVariableAttribute.getLocalVariableTableLength();
+ final ILocalVariableAttribute localVariableAttribute = codeAttribute.getLocalVariableAttribute();
+ final int localVariableAttributeLength = localVariableAttribute == null ? 0 : localVariableAttribute.getLocalVariableTableLength();
if (localVariableAttributeLength != 0) {
int tabNumberForLocalVariableAttribute = tabNumber + 2;
- writeNewLine(buffer, lineSeparator, tabNumberForLocalVariableAttribute);
+ if (!isFirstAttribute) {
+ writeNewLine(buffer, lineSeparator, tabNumberForLocalVariableAttribute);
+ } else {
+ isFirstAttribute = false;
+ dumpTab(tabNumberForLocalVariableAttribute, buffer);
+ }
buffer.append(Messages.disassembler_localvariabletableattributeheader);
writeNewLine(buffer, lineSeparator, tabNumberForLocalVariableAttribute + 1);
ILocalVariableTableEntry[] localVariableTableEntries = localVariableAttribute.getLocalVariableTable();
- for (int i = 0; i < localVariableAttributeLength - 1; i++) {
+ for (int i = 0; i < localVariableAttributeLength; i++) {
+ if (i != 0) {
+ writeNewLine(buffer, lineSeparator, tabNumberForLocalVariableAttribute + 1);
+ }
ILocalVariableTableEntry localVariableTableEntry = localVariableTableEntries[i];
int index= localVariableTableEntry.getIndex();
int startPC = localVariableTableEntry.getStartPC();
@@ -754,32 +1083,25 @@
Integer.toString(index),
new String(returnClassName(typeName, '.', mode))
}));
- writeNewLine(buffer, lineSeparator, tabNumberForLocalVariableAttribute + 1);
}
- ILocalVariableTableEntry localVariableTableEntry = localVariableTableEntries[localVariableAttributeLength - 1];
- int index= localVariableTableEntry.getIndex();
- int startPC = localVariableTableEntry.getStartPC();
- int length = localVariableTableEntry.getLength();
- final char[] typeName = Signature.toCharArray(localVariableTableEntry.getDescriptor());
- CharOperation.replace(typeName, '/', '.');
- buffer.append(Messages.bind(Messages.classfileformat_localvariabletableentry,
- new String[] {
- Integer.toString(startPC),
- Integer.toString(startPC + length),
- new String(localVariableTableEntry.getName()),
- Integer.toString(index),
- new String(returnClassName(typeName, '.', mode))
- }));
- }
- ILocalVariableTypeTableAttribute localVariableTypeAttribute= getLocalVariableTypeAttribute(codeAttribute);
- int localVariableTypeTableLength = localVariableTypeAttribute == null ? 0 : localVariableTypeAttribute.getLocalVariableTypeTableLength();
+ }
+ final ILocalVariableTypeTableAttribute localVariableTypeAttribute= (ILocalVariableTypeTableAttribute) getAttribute(IAttributeNamesConstants.LOCAL_VARIABLE_TYPE_TABLE, codeAttribute);
+ final int localVariableTypeTableLength = localVariableTypeAttribute == null ? 0 : localVariableTypeAttribute.getLocalVariableTypeTableLength();
if (localVariableTypeTableLength != 0) {
int tabNumberForLocalVariableAttribute = tabNumber + 2;
- writeNewLine(buffer, lineSeparator, tabNumberForLocalVariableAttribute);
+ if (!isFirstAttribute) {
+ writeNewLine(buffer, lineSeparator, tabNumberForLocalVariableAttribute);
+ } else {
+ isFirstAttribute = false;
+ dumpTab(tabNumberForLocalVariableAttribute, buffer);
+ }
buffer.append(Messages.disassembler_localvariabletypetableattributeheader);
writeNewLine(buffer, lineSeparator, tabNumberForLocalVariableAttribute + 1);
ILocalVariableTypeTableEntry[] localVariableTypeTableEntries = localVariableTypeAttribute.getLocalVariableTypeTable();
- for (int i = 0; i < localVariableTypeTableLength - 1; i++) {
+ for (int i = 0; i < localVariableTypeTableLength; i++) {
+ if (i != 0) {
+ writeNewLine(buffer, lineSeparator, tabNumberForLocalVariableAttribute + 1);
+ }
ILocalVariableTypeTableEntry localVariableTypeTableEntry = localVariableTypeTableEntries[i];
int index= localVariableTypeTableEntry.getIndex();
int startPC = localVariableTypeTableEntry.getStartPC();
@@ -794,23 +1116,176 @@
Integer.toString(index),
new String(returnClassName(typeName, '.', mode))
}));
- writeNewLine(buffer, lineSeparator, tabNumberForLocalVariableAttribute + 1);
}
- ILocalVariableTypeTableEntry localVariableTypeTableEntry = localVariableTypeTableEntries[localVariableTypeTableLength - 1];
- int index= localVariableTypeTableEntry.getIndex();
- int startPC = localVariableTypeTableEntry.getStartPC();
- int length = localVariableTypeTableEntry.getLength();
- final char[] typeName = Signature.toCharArray(localVariableTypeTableEntry.getSignature());
- CharOperation.replace(typeName, '/', '.');
- buffer.append(Messages.bind(Messages.classfileformat_localvariabletableentry,
- new String[] {
- Integer.toString(startPC),
- Integer.toString(startPC + length),
- new String(localVariableTypeTableEntry.getName()),
- Integer.toString(index),
- new String(returnClassName(typeName, '.', mode))
- }));
- }
+ }
+ final int length = codeAttribute.getAttributesCount();
+ if (length != 0) {
+ IClassFileAttribute[] attributes = codeAttribute.getAttributes();
+ for (int i = 0; i < length; i++) {
+ IClassFileAttribute attribute = attributes[i];
+ if (CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.STACK_MAP_TABLE)) {
+ IStackMapTableAttribute stackMapTableAttribute = (IStackMapTableAttribute) attribute;
+ if (!isFirstAttribute) {
+ writeNewLine(buffer, lineSeparator, tabNumber + 2);
+ } else {
+ isFirstAttribute = false;
+ dumpTab(tabNumber + 1, buffer);
+ }
+ int numberOfEntries = stackMapTableAttribute.getNumberOfEntries();
+ buffer.append(Messages.bind(Messages.disassembler_stackmaptableattributeheader, Integer.toString(numberOfEntries)));
+ if (numberOfEntries != 0) {
+ disassemble(stackMapTableAttribute, buffer, lineSeparator, tabNumber, mode);
+ }
+ } else if (CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.STACK_MAP)) {
+ IStackMapAttribute stackMapAttribute = (IStackMapAttribute) attribute;
+ if (!isFirstAttribute) {
+ writeNewLine(buffer, lineSeparator, tabNumber + 2);
+ } else {
+ isFirstAttribute = false;
+ dumpTab(tabNumber + 1, buffer);
+ }
+ int numberOfEntries = stackMapAttribute.getNumberOfEntries();
+ buffer.append(Messages.bind(Messages.disassembler_stackmapattributeheader, Integer.toString(numberOfEntries)));
+ if (numberOfEntries != 0) {
+ disassemble(stackMapAttribute, buffer, lineSeparator, tabNumber, mode);
+ }
+ } else if (attribute != lineNumberAttribute
+ && attribute != localVariableAttribute
+ && attribute != localVariableTypeAttribute) {
+ if (!isFirstAttribute) {
+ writeNewLine(buffer, lineSeparator, tabNumber + 2);
+ } else {
+ isFirstAttribute = false;
+ dumpTab(tabNumber + 1, buffer);
+ }
+ buffer.append(Messages.bind(Messages.disassembler_genericattributeheader,
+ new String[] {
+ new String(attribute.getAttributeName()),
+ Long.toString(attribute.getAttributeLength())
+ }));
+ }
+ }
+ }
+ }
+
+ private void disassemble(IStackMapTableAttribute attribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
+ writeNewLine(buffer, lineSeparator, tabNumber + 3);
+ int numberOfEntries = attribute.getNumberOfEntries();
+ final IStackMapFrame[] stackMapFrames = attribute.getStackMapFrame();
+ int absolutePC = -1;
+ for (int j = 0; j < numberOfEntries; j++) {
+ if (j > 0) {
+ writeNewLine(buffer, lineSeparator, tabNumber + 3);
+ }
+ final IStackMapFrame frame = stackMapFrames[j];
+ // disassemble each frame
+ int type = frame.getFrameType();
+ int offsetDelta = frame.getOffsetDelta();
+ if (absolutePC == -1) {
+ absolutePC = offsetDelta;
+ } else {
+ absolutePC += (offsetDelta + 1);
+ }
+ switch(type) {
+ case 247 : // SAME_LOCALS_1_STACK_ITEM_EXTENDED
+ buffer.append(
+ Messages.bind(
+ Messages.disassembler_frame_same_locals_1_stack_item_extended,
+ Integer.toString(absolutePC),
+ disassemble(frame.getStackItems(), mode)));
+ break;
+ case 248 :
+ case 249 :
+ case 250:
+ // CHOP
+ buffer.append(
+ Messages.bind(
+ Messages.disassembler_frame_chop,
+ Integer.toString(absolutePC),
+ Integer.toString(251 - type)));
+ break;
+ case 251 :
+ // SAME_FRAME_EXTENDED
+ buffer.append(
+ Messages.bind(
+ Messages.disassembler_frame_same_frame_extended,
+ Integer.toString(absolutePC)));
+ break;
+ case 252 :
+ case 253 :
+ case 254 :
+ // APPEND
+ buffer.append(
+ Messages.bind(
+ Messages.disassembler_frame_append,
+ Integer.toString(absolutePC),
+ disassemble(frame.getLocals(), mode)));
+ break;
+ case 255 :
+ // FULL_FRAME
+ buffer.append(
+ Messages.bind(
+ Messages.disassembler_frame_full_frame,
+ new String[] {
+ Integer.toString(absolutePC),
+ Integer.toString(frame.getNumberOfLocals()),
+ disassemble(frame.getLocals(), mode),
+ Integer.toString(frame.getNumberOfStackItems()),
+ disassemble(frame.getStackItems(), mode),
+ dumpNewLineWithTabs(lineSeparator, tabNumber + 5)
+ }));
+ break;
+ default:
+ if (type <= 63) {
+ // SAME_FRAME
+ offsetDelta = type;
+ buffer.append(
+ Messages.bind(
+ Messages.disassembler_frame_same_frame,
+ Integer.toString(absolutePC)));
+ } else if (type <= 127) {
+ // SAME_LOCALS_1_STACK_ITEM
+ offsetDelta = type - 64;
+ buffer.append(
+ Messages.bind(
+ Messages.disassembler_frame_same_locals_1_stack_item,
+ Integer.toString(absolutePC),
+ disassemble(frame.getStackItems(), mode)));
+ }
+ }
+ }
+ }
+
+ private void disassemble(IStackMapAttribute attribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
+ writeNewLine(buffer, lineSeparator, tabNumber + 3);
+ int numberOfEntries = attribute.getNumberOfEntries();
+ final IStackMapFrame[] stackMapFrames = attribute.getStackMapFrame();
+ int absolutePC = -1;
+ for (int j = 0; j < numberOfEntries; j++) {
+ if (j > 0) {
+ writeNewLine(buffer, lineSeparator, tabNumber + 3);
+ }
+ final IStackMapFrame frame = stackMapFrames[j];
+ // disassemble each frame
+ int offsetDelta = frame.getOffsetDelta();
+ if (absolutePC == -1) {
+ absolutePC = offsetDelta;
+ } else {
+ absolutePC += (offsetDelta + 1);
+ }
+ // FULL_FRAME
+ buffer.append(
+ Messages.bind(
+ Messages.disassembler_frame_full_frame,
+ new String[] {
+ Integer.toString(absolutePC),
+ Integer.toString(frame.getNumberOfLocals()),
+ disassemble(frame.getLocals(), mode),
+ Integer.toString(frame.getNumberOfStackItems()),
+ disassemble(frame.getStackItems(), mode),
+ dumpNewLineWithTabs(lineSeparator, tabNumber + 5)
+ }));
+ }
}
private void disassemble(IConstantPool constantPool, StringBuffer buffer, String lineSeparator, int tabNumber) {
@@ -819,6 +1294,9 @@
buffer.append(Messages.disassembler_constantpoolheader);
writeNewLine(buffer, lineSeparator, tabNumber + 1);
for (int i = 1; i < length; i++) {
+ if (i != 1) {
+ writeNewLine(buffer, lineSeparator, tabNumber + 1);
+ }
IConstantPoolEntry constantPoolEntry = constantPool.decodeEntry(i);
switch (constantPool.getEntryKind(i)) {
case IConstantPoolConstant.CONSTANT_Class :
@@ -913,19 +1391,16 @@
new String[] {
Integer.toString(i),
Integer.toString(constantPoolEntry.getStringIndex()),
- constantPoolEntry.getStringValue()}));
+ decodeStringValue(constantPoolEntry.getStringValue())}));
break;
case IConstantPoolConstant.CONSTANT_Utf8 :
buffer.append(
Messages.bind(Messages.disassembler_constantpool_utf8,
new String[] {
Integer.toString(i),
- new String(constantPoolEntry.getUtf8Value())}));
+ decodeStringValue(new String(constantPoolEntry.getUtf8Value()))}));
break;
}
- if (i < length - 1) {
- writeNewLine(buffer, lineSeparator, tabNumber + 1);
- }
}
}
@@ -939,23 +1414,72 @@
.append(Messages.disassembler_constantpoolindex)
.append(enclosingMethodAttribute.getMethodNameAndTypeIndex())
.append(" ")//$NON-NLS-1$
- .append(enclosingMethodAttribute.getEnclosingClass()); //$NON-NLS-1$
+ .append(enclosingMethodAttribute.getEnclosingClass());
if (enclosingMethodAttribute.getMethodNameAndTypeIndex() != 0) {
buffer
.append(".")//$NON-NLS-1$
- .append(enclosingMethodAttribute.getMethodName()) //$NON-NLS-1$
- .append(enclosingMethodAttribute.getMethodDescriptor()); //$NON-NLS-1$
+ .append(enclosingMethodAttribute.getMethodName())
+ .append(enclosingMethodAttribute.getMethodDescriptor());
}
}
+ private void disassembleEnumConstants(IFieldInfo fieldInfo, StringBuffer buffer, String lineSeparator, int tabNumber, char[][] argumentTypes, int mode) {
+ writeNewLine(buffer, lineSeparator, tabNumber);
+ final IClassFileAttribute runtimeVisibleAnnotationsAttribute = Util.getAttribute(fieldInfo, IAttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS);
+ final IClassFileAttribute runtimeInvisibleAnnotationsAttribute = Util.getAttribute(fieldInfo, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS);
+ // disassemble compact version of annotations
+ if (runtimeInvisibleAnnotationsAttribute != null) {
+ disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1, mode);
+ writeNewLine(buffer, lineSeparator, tabNumber);
+ }
+ if (runtimeVisibleAnnotationsAttribute != null) {
+ disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1, mode);
+ writeNewLine(buffer, lineSeparator, tabNumber);
+ }
+ buffer.append(new String(fieldInfo.getName()));
+ buffer.append('(');
+ final int length = argumentTypes.length;
+ if (length != 0) {
+ // insert default value for corresponding argument types
+ for (int i = 0; i < length; i++) {
+ if (i != 0) {
+ buffer.append(Messages.disassembler_comma);
+ }
+ final char[] type = argumentTypes[i];
+ switch(type.length) {
+ case 1 :
+ switch(type[0]) {
+ case 'B' :
+ case 'I' :
+ case 'J' :
+ case 'D' :
+ case 'F' :
+ case 'S' :
+ buffer.append('0');
+ break;
+ case 'Z' :
+ buffer.append("false"); //$NON-NLS-1$
+ break;
+ case 'C' :
+ buffer.append("\' \'"); //$NON-NLS-1$
+ break;
+ }
+ break;
+ default :
+ buffer.append("null"); //$NON-NLS-1$
+ }
+ }
+ }
+ buffer.append(')').append(Messages.disassembler_comma);
+ }
+
/**
* Disassemble a field info
*/
private void disassemble(IFieldInfo fieldInfo, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
writeNewLine(buffer, lineSeparator, tabNumber);
- char[] fieldDescriptor = fieldInfo.getDescriptor();
- IClassFileAttribute classFileAttribute = Util.getAttribute(fieldInfo, IAttributeNamesConstants.SIGNATURE);
- ISignatureAttribute signatureAttribute = (ISignatureAttribute) classFileAttribute;
+ final char[] fieldDescriptor = fieldInfo.getDescriptor();
+ final ISignatureAttribute signatureAttribute = (ISignatureAttribute) Util.getAttribute(fieldInfo, IAttributeNamesConstants.SIGNATURE);
if (checkMode(mode, SYSTEM | DETAILED)) {
buffer.append(Messages.bind(Messages.classfileformat_fieldddescriptor,
new String[] {
@@ -971,25 +1495,34 @@
writeNewLine(buffer, lineSeparator, tabNumber);
}
}
- IClassFileAttribute runtimeVisibleAnnotationsAttribute = Util.getAttribute(fieldInfo, IAttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS);
- IClassFileAttribute runtimeInvisibleAnnotationsAttribute = Util.getAttribute(fieldInfo, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS);
+ final IClassFileAttribute runtimeVisibleAnnotationsAttribute = Util.getAttribute(fieldInfo, IAttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS);
+ final IClassFileAttribute runtimeInvisibleAnnotationsAttribute = Util.getAttribute(fieldInfo, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS);
if (checkMode(mode, DETAILED)) {
// disassemble compact version of annotations
if (runtimeInvisibleAnnotationsAttribute != null) {
- disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1);
+ disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1, mode);
writeNewLine(buffer, lineSeparator, tabNumber);
}
if (runtimeVisibleAnnotationsAttribute != null) {
- disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1);
+ disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1, mode);
writeNewLine(buffer, lineSeparator, tabNumber);
}
}
- decodeModifiersForField(buffer, fieldInfo.getAccessFlags());
- if (fieldInfo.isSynthetic()) {
- buffer.append("synthetic"); //$NON-NLS-1$
- buffer.append(Messages.disassembler_space);
+ if (checkMode(mode, WORKING_COPY)) {
+ decodeModifiersForFieldForWorkingCopy(buffer, fieldInfo.getAccessFlags());
+ if (signatureAttribute != null) {
+ buffer.append(returnClassName(getSignatureForField(signatureAttribute.getSignature()), '.', mode));
+ } else {
+ buffer.append(returnClassName(getSignatureForField(fieldDescriptor), '.', mode));
+ }
+ } else {
+ decodeModifiersForField(buffer, fieldInfo.getAccessFlags());
+ if (fieldInfo.isSynthetic()) {
+ buffer.append("synthetic"); //$NON-NLS-1$
+ buffer.append(Messages.disassembler_space);
+ }
+ buffer.append(returnClassName(getSignatureForField(fieldDescriptor), '.', mode));
}
- buffer.append(getSignatureForField(fieldDescriptor));
buffer.append(' ');
buffer.append(new String(fieldInfo.getName()));
IConstantValueAttribute constantValueAttribute = fieldInfo.getConstantValueAttribute();
@@ -1004,7 +1537,18 @@
buffer.append(constantPoolEntry.getFloatValue() + "f"); //$NON-NLS-1$
break;
case IConstantPoolConstant.CONSTANT_Double :
- buffer.append(constantPoolEntry.getDoubleValue());
+ final double doubleValue = constantPoolEntry.getDoubleValue();
+ if (checkMode(mode, ClassFileBytesDisassembler.WORKING_COPY)) {
+ if (doubleValue == Double.POSITIVE_INFINITY) {
+ buffer.append("1.0 / 0.0"); //$NON-NLS-1$
+ } else if (doubleValue == Double.NEGATIVE_INFINITY) {
+ buffer.append("-1.0 / 0.0"); //$NON-NLS-1$
+ } else {
+ buffer.append(constantPoolEntry.getDoubleValue());
+ }
+ } else {
+ buffer.append(constantPoolEntry.getDoubleValue());
+ }
break;
case IConstantPoolConstant.CONSTANT_Integer:
switch(fieldDescriptor[0]) {
@@ -1062,7 +1606,11 @@
int length = innerClassesAttributeEntries.length;
int innerClassNameIndex, outerClassNameIndex, innerNameIndex, accessFlags;
IInnerClassesAttributeEntry innerClassesAttributeEntry;
- for (int i = 0; i < length - 1; i++) {
+ for (int i = 0; i < length; i++) {
+ if (i != 0) {
+ buffer.append(Messages.disassembler_comma);
+ writeNewLine(buffer, lineSeparator, tabNumber + 1);
+ }
innerClassesAttributeEntry = innerClassesAttributeEntries[i];
innerClassNameIndex = innerClassesAttributeEntry.getInnerClassNameIndex();
outerClassNameIndex = innerClassesAttributeEntry.getOuterClassNameIndex();
@@ -1107,59 +1655,10 @@
.append(Messages.disassembler_inner_accessflags)
.append(accessFlags)
.append(Messages.disassembler_space);
- decodeModifiersForInnerClasses(buffer, accessFlags);
+ decodeModifiersForInnerClasses(buffer, accessFlags, true);
buffer
- .append(Messages.disassembler_closeinnerclassentry)
- .append(Messages.disassembler_comma);
- writeNewLine(buffer, lineSeparator, tabNumber + 1);
+ .append(Messages.disassembler_closeinnerclassentry);
}
- // last entry
- innerClassesAttributeEntry = innerClassesAttributeEntries[length - 1];
- innerClassNameIndex = innerClassesAttributeEntry.getInnerClassNameIndex();
- outerClassNameIndex = innerClassesAttributeEntry.getOuterClassNameIndex();
- innerNameIndex = innerClassesAttributeEntry.getInnerNameIndex();
- accessFlags = innerClassesAttributeEntry.getAccessFlags();
- buffer
- .append(Messages.disassembler_openinnerclassentry)
- .append(Messages.disassembler_inner_class_info_name)
- .append(Messages.disassembler_constantpoolindex)
- .append(innerClassNameIndex);
- if (innerClassNameIndex != 0) {
- buffer
- .append(Messages.disassembler_space)
- .append(innerClassesAttributeEntry.getInnerClassName());
- }
- buffer
- .append(Messages.disassembler_comma)
- .append(Messages.disassembler_space)
- .append(Messages.disassembler_outer_class_info_name)
- .append(Messages.disassembler_constantpoolindex)
- .append(outerClassNameIndex);
- if (outerClassNameIndex != 0) {
- buffer
- .append(Messages.disassembler_space)
- .append(innerClassesAttributeEntry.getOuterClassName());
- }
- writeNewLine(buffer, lineSeparator, tabNumber);
- dumpTab(tabNumber, buffer);
- buffer.append(Messages.disassembler_space);
- buffer
- .append(Messages.disassembler_inner_name)
- .append(Messages.disassembler_constantpoolindex)
- .append(innerNameIndex);
- if (innerNameIndex != 0) {
- buffer
- .append(Messages.disassembler_space)
- .append(innerClassesAttributeEntry.getInnerName());
- }
- buffer
- .append(Messages.disassembler_comma)
- .append(Messages.disassembler_space)
- .append(Messages.disassembler_inner_accessflags)
- .append(accessFlags)
- .append(Messages.disassembler_space);
- decodeModifiersForInnerClasses(buffer, accessFlags);
- buffer.append(Messages.disassembler_closeinnerclassentry);
}
private void disassemble(int index, IParameterAnnotation parameterAnnotation, StringBuffer buffer, String lineSeparator, int tabNumber) {
@@ -1208,26 +1707,79 @@
}
}
- private void disassembleAsModifier(IAnnotation annotation, StringBuffer buffer, String lineSeparator, int tabNumber) {
- final char[] typeName = CharOperation.replaceOnCopy(annotation.getTypeName(), '/', '.');
- buffer.append('@').append(Signature.toCharArray(typeName)).append('(');
- final IAnnotationComponent[] components = annotation.getComponents();
- for (int i = 0, max = components.length; i < max; i++) {
- if (i > 0) {
- buffer.append(',');
- writeNewLine(buffer, lineSeparator, tabNumber);
+ private String disassemble(IVerificationTypeInfo[] infos, int mode) {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append('{');
+ for (int i = 0, max = infos.length; i < max; i++) {
+ if(i != 0) {
+ buffer
+ .append(Messages.disassembler_comma)
+ .append(Messages.disassembler_space);
}
- disassembleAsModifier(components[i], buffer, lineSeparator, tabNumber + 1);
+ switch(infos[i].getTag()) {
+ case IVerificationTypeInfo.ITEM_DOUBLE :
+ buffer.append("double"); //$NON-NLS-1$
+ break;
+ case IVerificationTypeInfo.ITEM_FLOAT :
+ buffer.append("float"); //$NON-NLS-1$
+ break;
+ case IVerificationTypeInfo.ITEM_INTEGER :
+ buffer.append("int"); //$NON-NLS-1$
+ break;
+ case IVerificationTypeInfo.ITEM_LONG :
+ buffer.append("long"); //$NON-NLS-1$
+ break;
+ case IVerificationTypeInfo.ITEM_NULL :
+ buffer.append("null"); //$NON-NLS-1$
+ break;
+ case IVerificationTypeInfo.ITEM_OBJECT :
+ char[] classTypeName = infos[i].getClassTypeName();
+ CharOperation.replace(classTypeName, '/', '.');
+ if (classTypeName.length > 0 && classTypeName[0] == '[') { // length check for resilience
+ classTypeName = Signature.toCharArray(classTypeName);
+ }
+ buffer.append(returnClassName(classTypeName, '.', mode));
+ break;
+ case IVerificationTypeInfo.ITEM_TOP :
+ buffer.append("_"); //$NON-NLS-1$
+ break;
+ case IVerificationTypeInfo.ITEM_UNINITIALIZED :
+ buffer.append("uninitialized("); //$NON-NLS-1$
+ buffer.append(infos[i].getOffset());
+ buffer.append(')');
+ break;
+ case IVerificationTypeInfo.ITEM_UNINITIALIZED_THIS :
+ buffer.append("uninitialized_this"); //$NON-NLS-1$
+ }
}
- buffer.append(')');
+ buffer.append('}');
+ return String.valueOf(buffer);
}
- private void disassembleAsModifier(IAnnotationComponent annotationComponent, StringBuffer buffer, String lineSeparator, int tabNumber) {
+ private void disassembleAsModifier(IAnnotation annotation, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
+ final char[] typeName = CharOperation.replaceOnCopy(annotation.getTypeName(), '/', '.');
+ buffer.append('@').append(returnClassName(Signature.toCharArray(typeName), '.', mode));
+ final IAnnotationComponent[] components = annotation.getComponents();
+ final int length = components.length;
+ if (length != 0) {
+ buffer.append('(');
+ for (int i = 0; i < length; i++) {
+ if (i > 0) {
+ buffer.append(',');
+ writeNewLine(buffer, lineSeparator, tabNumber);
+ }
+ disassembleAsModifier(components[i], buffer, lineSeparator, tabNumber + 1, mode);
+ }
+ buffer.append(')');
+ }
+ }
+
+ private void disassembleAsModifier(IAnnotationComponent annotationComponent, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
buffer.append(annotationComponent.getComponentName()).append('=');
- disassembleAsModifier(annotationComponent.getComponentValue(), buffer, lineSeparator, tabNumber + 1);
+ disassembleAsModifier(annotationComponent.getComponentValue(), buffer, lineSeparator, tabNumber + 1, mode);
}
- private void disassembleAsModifier(IAnnotationComponentValue annotationComponentValue, StringBuffer buffer, String lineSeparator, int tabNumber) {
+ private void disassembleAsModifier(IAnnotationComponentValue annotationComponentValue, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
switch(annotationComponentValue.getTag()) {
case IAnnotationComponentValue.BYTE_TAG:
case IAnnotationComponentValue.CHAR_TAG:
@@ -1271,7 +1823,7 @@
case IConstantPoolConstant.CONSTANT_Utf8:
value = "\"" + decodeStringValue(constantPoolEntry.getUtf8Value()) + "\"";//$NON-NLS-1$//$NON-NLS-2$
}
- buffer.append(value); //$NON-NLS-1$
+ buffer.append(value);
break;
case IAnnotationComponentValue.ENUM_TAG:
final char[] typeName = CharOperation.replaceOnCopy(annotationComponentValue.getEnumConstantTypeName(), '/', '.');
@@ -1285,7 +1837,7 @@
break;
case IAnnotationComponentValue.ANNOTATION_TAG:
IAnnotation annotation = annotationComponentValue.getAnnotationValue();
- disassembleAsModifier(annotation, buffer, lineSeparator, tabNumber + 1);
+ disassembleAsModifier(annotation, buffer, lineSeparator, tabNumber + 1, mode);
break;
case IAnnotationComponentValue.ARRAY_TAG:
final IAnnotationComponentValue[] annotationComponentValues = annotationComponentValue.getAnnotationComponentValues();
@@ -1294,48 +1846,129 @@
if (i > 0) {
buffer.append(',');
}
- disassembleAsModifier(annotationComponentValues[i], buffer, lineSeparator, tabNumber + 1);
+ disassembleAsModifier(annotationComponentValues[i], buffer, lineSeparator, tabNumber + 1, mode);
}
buffer.append('}');
}
}
- private void disassembleAsModifier(IAnnotationDefaultAttribute annotationDefaultAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) {
+ private void disassembleAsModifier(IAnnotationDefaultAttribute annotationDefaultAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
IAnnotationComponentValue componentValue = annotationDefaultAttribute.getMemberValue();
- disassembleAsModifier(componentValue, buffer, lineSeparator, tabNumber + 1);
+ disassembleAsModifier(componentValue, buffer, lineSeparator, tabNumber + 1, mode);
}
- private void disassembleAsModifier(IRuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) {
+ private void disassembleAsModifier(IRuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
IAnnotation[] annotations = runtimeInvisibleAnnotationsAttribute.getAnnotations();
for (int i = 0, max = annotations.length; i < max; i++) {
- disassembleAsModifier(annotations[i], buffer, lineSeparator, tabNumber + 1);
+ disassembleAsModifier(annotations[i], buffer, lineSeparator, tabNumber + 1, mode);
}
}
- private void disassembleAsModifier(IRuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) {
+ private void disassembleAsModifier(IRuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
IAnnotation[] annotations = runtimeVisibleAnnotationsAttribute.getAnnotations();
for (int i = 0, max = annotations.length; i < max; i++) {
- disassembleAsModifier(annotations[i], buffer, lineSeparator, tabNumber + 1);
+ disassembleAsModifier(annotations[i], buffer, lineSeparator, tabNumber + 1, mode);
}
}
- private void disassembleTypeMembers(IClassFileReader classFileReader, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
+ private void disassembleTypeMembers(IClassFileReader classFileReader, char[] className, StringBuffer buffer, String lineSeparator, int tabNumber, int mode, boolean isEnum) {
IFieldInfo[] fields = classFileReader.getFieldInfos();
- for (int i = 0, max = fields.length; i < max; i++) {
- writeNewLine(buffer, lineSeparator, tabNumber);
- disassemble(fields[i], buffer, lineSeparator, tabNumber, mode);
- }
- IMethodInfo[] methods = classFileReader.getMethodInfos();
- for (int i = 0, max = methods.length; i < max; i++) {
- writeNewLine(buffer, lineSeparator, tabNumber);
- disassemble(classFileReader, methods[i], buffer, lineSeparator, tabNumber, mode);
+ if (isEnum && checkMode(mode, WORKING_COPY)) {
+ int index = 0;
+ final int fieldsLength = fields.length;
+ IMethodInfo[] methods = classFileReader.getMethodInfos();
+ char[][] constructorArguments = getConstructorArgumentsForEnum(methods);
+ enumConstantLoop: for (; index < fieldsLength; index++) {
+ final IFieldInfo fieldInfo = fields[index];
+ final int accessFlags = fieldInfo.getAccessFlags();
+ if ((accessFlags & IModifierConstants.ACC_ENUM) != 0) {
+ writeNewLine(buffer, lineSeparator, tabNumber);
+ disassembleEnumConstants(fields[index], buffer, lineSeparator, tabNumber, constructorArguments, mode);
+ } else {
+ break enumConstantLoop;
+ }
+ }
+ buffer.append(';');
+ boolean foundSyntheticField = false;
+ fieldLoop: for (; index < fieldsLength; index++) {
+ if (!foundSyntheticField && CharOperation.equals(TypeConstants.SYNTHETIC_ENUM_VALUES, fields[index].getName())) {
+ foundSyntheticField = true;
+ continue fieldLoop;
+ }
+ writeNewLine(buffer, lineSeparator, tabNumber);
+ disassemble(fields[index], buffer, lineSeparator, tabNumber, mode);
+ }
+ methodLoop: for (int i = 0, max = methods.length; i < max; i++) {
+ final IMethodInfo methodInfo = methods[i];
+ if (CharOperation.equals(methodInfo.getName(), TypeConstants.VALUES)) {
+ final char[] descriptor = methodInfo.getDescriptor();
+ CharOperation.replace(descriptor, '/', '.');
+ if (Signature.getParameterCount(descriptor) == 0) {
+ if (CharOperation.equals(returnClassName(Signature.getReturnType(descriptor), '.', mode),
+ CharOperation.concat(new char[] {'[', 'L'}, className, new char[] {';'}))) {
+ continue methodLoop;
+ }
+ }
+ } else if (CharOperation.equals(methodInfo.getName(), TypeConstants.VALUEOF)) {
+ final char[] descriptor = methodInfo.getDescriptor();
+ CharOperation.replace(descriptor, '/', '.');
+ final char[][] parameterTypes = Signature.getParameterTypes(descriptor);
+ if (parameterTypes.length == 1
+ && CharOperation.equals(parameterTypes[0], "Ljava.lang.String;".toCharArray())) { //$NON-NLS-1$
+ if (CharOperation.equals(returnClassName(Signature.getReturnType(descriptor), '.', mode),
+ CharOperation.concat('L', className, ';'))) {
+ continue methodLoop;
+ }
+ }
+ } else if (methodInfo.isClinit() || methodInfo.isSynthetic()) {
+ continue methodLoop;
+ } else if (methodInfo.isConstructor()) {
+ writeNewLine(buffer, lineSeparator, tabNumber);
+ disassembleEnumConstructor(classFileReader, className, methodInfo, buffer, lineSeparator, tabNumber, mode);
+ } else {
+ writeNewLine(buffer, lineSeparator, tabNumber);
+ disassemble(classFileReader, className, methodInfo, buffer, lineSeparator, tabNumber, mode);
+ }
+ }
+ } else {
+ for (int i = 0, max = fields.length; i < max; i++) {
+ writeNewLine(buffer, lineSeparator, tabNumber);
+ disassemble(fields[i], buffer, lineSeparator, tabNumber, mode);
+ }
+ IMethodInfo[] methods = classFileReader.getMethodInfos();
+ for (int i = 0, max = methods.length; i < max; i++) {
+ writeNewLine(buffer, lineSeparator, tabNumber);
+ disassemble(classFileReader, className, methods[i], buffer, lineSeparator, tabNumber, mode);
+ }
}
}
+ private char[][] getConstructorArgumentsForEnum(final IMethodInfo[] methods) {
+ loop: for (int i = 0, max = methods.length; i < max; i++) {
+ IMethodInfo methodInfo = methods[i];
+ if (methodInfo.isConstructor()) {
+ char[][] parameterTypes = Signature.getParameterTypes(methodInfo.getDescriptor());
+ final int length = parameterTypes.length;
+ if (length >= 2) {
+ return CharOperation.subarray(parameterTypes, 2, length);
+ }
+ } else {
+ continue loop;
+ }
+ }
+ return null;
+ }
+
private final void dumpTab(int tabNumber, StringBuffer buffer) {
for (int i = 0; i < tabNumber; i++) {
buffer.append(Messages.disassembler_indentation);
}
+ }
+
+ private final String dumpNewLineWithTabs(String lineSeparator, int tabNumber) {
+ StringBuffer buffer = new StringBuffer();
+ writeNewLine(buffer, lineSeparator, tabNumber);
+ return String.valueOf(buffer);
}
/**
@@ -1354,29 +1987,11 @@
}
return null;
}
- /**
- * Method getEntryFor.
- * @param localIndex
- * @param entries
- * @return ILocalVariableTableEntry
- */
- private ILocalVariableTableEntry getEntryFor(
- int localIndex,
- ILocalVariableTableEntry[] entries) {
-
- for (int i = 0, max = entries.length; i < max; i++) {
- ILocalVariableTableEntry entry = entries[i];
- if (localIndex == entry.getIndex()) {
- return entry;
- }
- }
- return null;
- }
- private ILocalVariableTypeTableAttribute getLocalVariableTypeAttribute(ICodeAttribute codeAttribute) {
+ private IClassFileAttribute getAttribute(final char[] attributeName, final ICodeAttribute codeAttribute) {
IClassFileAttribute[] attributes = codeAttribute.getAttributes();
for (int i = 0, max = attributes.length; i < max; i++) {
- if (CharOperation.equals(attributes[i].getAttributeName(), IAttributeNamesConstants.LOCAL_VARIABLE_TYPE_TABLE)) {
- return (ILocalVariableTypeTableAttribute) attributes[i];
+ if (CharOperation.equals(attributes[i].getAttributeName(), attributeName)) {
+ return attributes[i];
}
}
return null;
@@ -1390,33 +2005,66 @@
ILocalVariableAttribute localVariableAttribute = codeAttribute.getLocalVariableAttribute();
if (localVariableAttribute != null) {
ILocalVariableTableEntry[] entries = localVariableAttribute.getLocalVariableTable();
- int startingIndex = (accessFlags & IModifierConstants.ACC_STATIC) != 0 ? 0 : 1;
+ final int startingIndex = (accessFlags & IModifierConstants.ACC_STATIC) != 0 ? 0 : 1;
for (int i = 0; i < paramCount; i++) {
- ILocalVariableTableEntry searchedEntry = getEntryFor(startingIndex + i, entries);
+ ILocalVariableTableEntry searchedEntry = getEntryFor(getLocalIndex(startingIndex, i, methodDescriptor), entries);
if (searchedEntry != null) {
parameterNames[i] = searchedEntry.getName();
} else {
- parameterNames[i] = Messages.disassembler_parametername.toCharArray();
+ parameterNames[i] = CharOperation.concat(Messages.disassembler_parametername.toCharArray(), Integer.toString(i).toCharArray());
}
}
} else {
for (int i = 0; i < paramCount; i++) {
- parameterNames[i] = Messages.disassembler_parametername.toCharArray();
+ parameterNames[i] = CharOperation.concat(Messages.disassembler_parametername.toCharArray(), Integer.toString(i).toCharArray());
}
}
} else {
for (int i = 0; i < paramCount; i++) {
- parameterNames[i] = Messages.disassembler_parametername.toCharArray();
+ parameterNames[i] = CharOperation.concat(Messages.disassembler_parametername.toCharArray(), Integer.toString(i).toCharArray());
}
}
return parameterNames;
}
+
+ private int getLocalIndex(final int startingSlot, final int index, final char[] methodDescriptor) {
+ int slot = startingSlot;
+ final char[][] types = Signature.getParameterTypes(methodDescriptor);
+ for (int i = 0; i < index; i++) {
+ final char[] type = types[i];
+ switch(type.length) {
+ case 1 :
+ switch(type[0]) {
+ case 'D' :
+ case 'J' :
+ slot += 2;
+ break;
+ default :
+ slot++;
+ }
+ break;
+ default :
+ slot++;
+ }
+ }
+ return slot;
+ }
+
+ private ILocalVariableTableEntry getEntryFor(final int index, final ILocalVariableTableEntry[] entries) {
+ for (int i = 0, max = entries.length; i < max; i++) {
+ ILocalVariableTableEntry entry = entries[i];
+ if (index == entry.getIndex()) {
+ return entry;
+ }
+ }
+ return null;
+ }
private char[] getSignatureForField(char[] fieldDescriptor) {
char[] newFieldDescriptor = CharOperation.replaceOnCopy(fieldDescriptor, '/', '.');
- newFieldDescriptor = CharOperation.replaceOnCopy(newFieldDescriptor, '$', '~');
+ newFieldDescriptor = CharOperation.replaceOnCopy(newFieldDescriptor, '$', '%');
char[] fieldDescriptorSignature = Signature.toCharArray(newFieldDescriptor);
- CharOperation.replace(fieldDescriptorSignature, '~', '$');
+ CharOperation.replace(fieldDescriptorSignature, '%', '$');
return fieldDescriptorSignature;
}
@@ -1452,18 +2100,16 @@
return (mode & ClassFileBytesDisassembler.COMPACT) != 0;
}
- private String returnClassName(char[] classInfoName, char separator, int mode) {
+ private char[] returnClassName(char[] classInfoName, char separator, int mode) {
if (classInfoName.length == 0) {
- return EMPTY_CLASS_NAME;
+ return CharOperation.NO_CHAR;
} else if (isCompact(mode)) {
int lastIndexOfSlash = CharOperation.lastIndexOf(separator, classInfoName);
if (lastIndexOfSlash != -1) {
- return new String(classInfoName, lastIndexOfSlash + 1, classInfoName.length - lastIndexOfSlash - 1);
+ return CharOperation.subarray(classInfoName, lastIndexOfSlash + 1, classInfoName.length);
}
- return new String(classInfoName);
- } else {
- return new String(classInfoName);
}
+ return classInfoName;
}
private void writeNewLine(StringBuffer buffer, String lineSeparator, int tabNumber) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/EnclosingMethodAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/EnclosingMethodAttribute.java
index 83a5f40..bfa9a60 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/EnclosingMethodAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/EnclosingMethodAttribute.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ExceptionAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ExceptionAttribute.java
index d0a6ff2..519bfcf 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ExceptionAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ExceptionAttribute.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -20,10 +20,7 @@
/**
* Default implementation of IExceptionAttribute.
*/
-public class ExceptionAttribute extends ClassFileAttribute implements IExceptionAttribute {
- private static final int[] NO_EXCEPTION_INDEXES = new int[0];
- private static final char[][] NO_EXCEPTION_NAMES = CharOperation.NO_CHAR_CHAR;
-
+public class ExceptionAttribute extends ClassFileAttribute implements IExceptionAttribute {
private int exceptionsNumber;
private char[][] exceptionNames;
private int[] exceptionIndexes;
@@ -32,8 +29,8 @@
super(classFileBytes, constantPool, offset);
this.exceptionsNumber = u2At(classFileBytes, 6, offset);
int exceptionLength = this.exceptionsNumber;
- this.exceptionNames = NO_EXCEPTION_NAMES;
- this.exceptionIndexes = NO_EXCEPTION_INDEXES;
+ this.exceptionNames = CharOperation.NO_CHAR_CHAR;
+ this.exceptionIndexes = org.eclipse.jdt.internal.compiler.util.Util.EMPTY_INT_ARRAY;
if (exceptionLength != 0) {
this.exceptionNames = new char[exceptionLength][];
this.exceptionIndexes = new int[exceptionLength];
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ExceptionTableEntry.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ExceptionTableEntry.java
index 37d4abc..f01ea37 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ExceptionTableEntry.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ExceptionTableEntry.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/FieldInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/FieldInfo.java
index 3ab3e51..8a0dcc1 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/FieldInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/FieldInfo.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/HandleFactory.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/HandleFactory.java
index 522f6c3..4807441 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/HandleFactory.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/HandleFactory.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -69,6 +69,7 @@
this.javaModel = JavaModelManager.getJavaModelManager().getJavaModel();
}
+
/**
* Creates an Openable handle from the given resource path.
* The resource path can be a path to a file in the workbench (eg. /Proj/com/ibm/jdt/core/HandleFactory.java)
@@ -83,9 +84,12 @@
int separatorIndex;
if ((separatorIndex= resourcePath.indexOf(IJavaSearchScope.JAR_FILE_ENTRY_SEPARATOR)) > -1) {
// path to a class file inside a jar
- String jarPath= resourcePath.substring(0, separatorIndex);
// Optimization: cache package fragment root handle and package handles
- if (!jarPath.equals(this.lastPkgFragmentRootPath)) {
+ int rootPathLength;
+ if (this.lastPkgFragmentRootPath == null
+ || (rootPathLength = this.lastPkgFragmentRootPath.length()) != resourcePath.length()
+ || !resourcePath.regionMatches(0, this.lastPkgFragmentRootPath, 0, rootPathLength)) {
+ String jarPath= resourcePath.substring(0, separatorIndex);
IPackageFragmentRoot root= this.getJarPkgFragmentRoot(jarPath, scope);
if (root == null)
return null; // match is outside classpath
@@ -151,7 +155,7 @@
return (Openable) classFile;
}
}
- }
+ }
/**
* Returns a handle denoting the class member identified by its scope.
@@ -254,13 +258,10 @@
// is NOT on the classpath of org.eclipse.swt.win32
IFile jarFile = (IFile)target;
JavaProject javaProject = (JavaProject) this.javaModel.getJavaProject(jarFile);
- IClasspathEntry[] classpathEntries;
try {
- classpathEntries = javaProject.getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/);
- for (int j= 0, entryCount= classpathEntries.length; j < entryCount; j++) {
- if (classpathEntries[j].getPath().equals(jarPath)) {
- return javaProject.getPackageFragmentRoot(jarFile);
- }
+ IClasspathEntry entry = javaProject.getClasspathEntryFor(jarPath);
+ if (entry != null) {
+ return javaProject.getPackageFragmentRoot(jarFile);
}
} catch (JavaModelException e) {
// ignore and try to find another project
@@ -306,16 +307,14 @@
for (int i= 0, projectCount= projects.length; i < projectCount; i++) {
try {
JavaProject javaProject= (JavaProject)projects[i];
- IClasspathEntry[] classpathEntries= javaProject.getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/);
- for (int j= 0, entryCount= classpathEntries.length; j < entryCount; j++) {
- if (classpathEntries[j].getPath().equals(jarPath)) {
- if (target instanceof IFile) {
- // internal jar
- return javaProject.getPackageFragmentRoot((IFile)target);
- } else {
- // external jar
- return javaProject.getPackageFragmentRoot0(jarPath);
- }
+ IClasspathEntry classpathEnty = javaProject.getClasspathEntryFor(jarPath);
+ if (classpathEnty != null) {
+ if (target instanceof IFile) {
+ // internal jar
+ return javaProject.getPackageFragmentRoot((IFile)target);
+ } else {
+ // external jar
+ return javaProject.getPackageFragmentRoot0(jarPath);
}
}
} catch (JavaModelException e) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/HashSetOfArray.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/HashSetOfArray.java
new file mode 100755
index 0000000..984b74b
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/HashSetOfArray.java
@@ -0,0 +1,149 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.util;
+
+/**
+ * HashSet of Object[]
+ */
+public final class HashSetOfArray implements Cloneable {
+
+ // to avoid using Enumerations, walk the individual tables skipping nulls
+ public Object[][] set;
+
+ public int elementSize; // number of elements in the table
+ int threshold;
+
+ public HashSetOfArray() {
+ this(13);
+ }
+
+ public HashSetOfArray(int size) {
+
+ this.elementSize = 0;
+ this.threshold = size; // size represents the expected number of elements
+ int extraRoom = (int) (size * 1.75f);
+ if (this.threshold == extraRoom)
+ extraRoom++;
+ this.set = new Object[extraRoom][];
+ }
+
+ public Object clone() throws CloneNotSupportedException {
+ HashSetOfArray result = (HashSetOfArray) super.clone();
+ result.elementSize = this.elementSize;
+ result.threshold = this.threshold;
+
+ int length = this.set.length;
+ result.set = new Object[length][];
+ System.arraycopy(this.set, 0, result.set, 0, length);
+
+ return result;
+ }
+
+ public boolean contains(Object[] array) {
+ int length = this.set.length;
+ int index = hashCode(array) % length;
+ int arrayLength = array.length;
+ Object[] currentArray;
+ while ((currentArray = this.set[index]) != null) {
+ if (currentArray.length == arrayLength && Util.equalArraysOrNull(currentArray, array))
+ return true;
+ if (++index == length) {
+ index = 0;
+ }
+ }
+ return false;
+ }
+
+ private int hashCode(Object[] element) {
+ return hashCode(element, element.length);
+ }
+
+ private int hashCode(Object[] element, int length) {
+ int hash = 0;
+ for (int i = length-1; i >= 0; i--)
+ hash = Util.combineHashCodes(hash, element[i].hashCode());
+ return hash & 0x7FFFFFFF;
+ }
+
+ public Object add(Object[] array) {
+ int length = this.set.length;
+ int index = hashCode(array) % length;
+ int arrayLength = array.length;
+ Object[] currentArray;
+ while ((currentArray = this.set[index]) != null) {
+ if (currentArray.length == arrayLength && Util.equalArraysOrNull(currentArray, array))
+ return this.set[index] = array;
+ if (++index == length) {
+ index = 0;
+ }
+ }
+ this.set[index] = array;
+
+ // assumes the threshold is never equal to the size of the table
+ if (++this.elementSize > threshold)
+ rehash();
+ return array;
+ }
+
+ public Object remove(Object[] array) {
+ int length = this.set.length;
+ int index = hashCode(array) % length;
+ int arrayLength = array.length;
+ Object[] currentArray;
+ while ((currentArray = this.set[index]) != null) {
+ if (currentArray.length == arrayLength && Util.equalArraysOrNull(currentArray, array)) {
+ Object existing = this.set[index];
+ this.elementSize--;
+ this.set[index] = null;
+ rehash();
+ return existing;
+ }
+ if (++index == length) {
+ index = 0;
+ }
+ }
+ return null;
+ }
+
+ private void rehash() {
+
+ HashSetOfArray newHashSet = new HashSetOfArray(elementSize * 2); // double the number of expected elements
+ Object[] currentArray;
+ for (int i = this.set.length; --i >= 0;)
+ if ((currentArray = this.set[i]) != null)
+ newHashSet.add(currentArray);
+
+ this.set = newHashSet.set;
+ this.threshold = newHashSet.threshold;
+ }
+
+ public int size() {
+ return elementSize;
+ }
+
+ public String toString() {
+ StringBuffer buffer = new StringBuffer();
+ Object[] element;
+ for (int i = 0, length = this.set.length; i < length; i++)
+ if ((element = this.set[i]) != null) {
+ buffer.append('{');
+ for (int j = 0, length2 = element.length; j < length2; j++) {
+ buffer.append(element[j]);
+ if (j != length2-1)
+ buffer.append(", "); //$NON-NLS-1$
+ }
+ buffer.append("}"); //$NON-NLS-1$
+ if (i != length-1)
+ buffer.append('\n');
+ }
+ return buffer.toString();
+ }
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/HashtableOfArrayToObject.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/HashtableOfArrayToObject.java
index 79b712f..f20a91c 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/HashtableOfArrayToObject.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/HashtableOfArrayToObject.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -53,39 +53,45 @@
}
public boolean containsKey(Object[] key) {
-
- int index = hashCode(key) % this.valueTable.length;
+ int length = this.keyTable.length;
+ int index = hashCode(key) % length;
int keyLength = key.length;
Object[] currentKey;
while ((currentKey = this.keyTable[index]) != null) {
if (currentKey.length == keyLength && Util.equalArraysOrNull(currentKey, key))
return true;
- index = (index + 1) % this.keyTable.length;
+ if (++index == length) {
+ index = 0;
+ }
}
return false;
}
public Object get(Object[] key) {
-
- int index = hashCode(key) % this.valueTable.length;
+ int length = this.keyTable.length;
+ int index = hashCode(key) % length;
int keyLength = key.length;
Object[] currentKey;
while ((currentKey = this.keyTable[index]) != null) {
if (currentKey.length == keyLength && Util.equalArraysOrNull(currentKey, key))
return this.valueTable[index];
- index = (index + 1) % keyTable.length;
+ if (++index == length) {
+ index = 0;
+ }
}
return null;
}
public Object[] getKey(Object[] key, int keyLength) {
-
- int index = hashCode(key, keyLength) % this.valueTable.length;
+ int length = this.keyTable.length;
+ int index = hashCode(key, keyLength) % length;
Object[] currentKey;
while ((currentKey = this.keyTable[index]) != null) {
if (currentKey.length == keyLength && Util.equalArrays(currentKey, key, keyLength))
return currentKey;
- index = (index + 1) % this.keyTable.length;
+ if (++index == length) {
+ index = 0;
+ }
}
return null;
}
@@ -96,20 +102,22 @@
private int hashCode(Object[] element, int length) {
int hash = 0;
- for (int i = 0; i < length; i++)
+ for (int i = length-1; i >= 0; i--)
hash = Util.combineHashCodes(hash, element[i].hashCode());
return hash & 0x7FFFFFFF;
}
public Object put(Object[] key, Object value) {
-
- int index = hashCode(key) % this.valueTable.length;
+ int length = this.keyTable.length;
+ int index = hashCode(key) % length;
int keyLength = key.length;
Object[] currentKey;
while ((currentKey = this.keyTable[index]) != null) {
if (currentKey.length == keyLength && Util.equalArraysOrNull(currentKey, key))
return this.valueTable[index] = value;
- index = (index + 1) % keyTable.length;
+ if (++index == length) {
+ index = 0;
+ }
}
this.keyTable[index] = key;
this.valueTable[index] = value;
@@ -121,8 +129,8 @@
}
public Object removeKey(Object[] key) {
-
- int index = hashCode(key) % this.valueTable.length;
+ int length = this.keyTable.length;
+ int index = hashCode(key) % length;
int keyLength = key.length;
Object[] currentKey;
while ((currentKey = this.keyTable[index]) != null) {
@@ -134,7 +142,9 @@
rehash();
return value;
}
- index = (index + 1) % this.keyTable.length;
+ if (++index == length) {
+ index = 0;
+ }
}
return null;
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ICacheEnumeration.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ICacheEnumeration.java
index 3a968bf..925b887 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ICacheEnumeration.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ICacheEnumeration.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ILRUCacheable.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ILRUCacheable.java
index e282405..29caa9e 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ILRUCacheable.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ILRUCacheable.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/InnerClassesAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/InnerClassesAttribute.java
index 3bb2b75..9cec55a 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/InnerClassesAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/InnerClassesAttribute.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/InnerClassesAttributeEntry.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/InnerClassesAttributeEntry.java
index 80b18c5..9ac227c 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/InnerClassesAttributeEntry.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/InnerClassesAttributeEntry.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/KeyToSignature.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/KeyToSignature.java
index 99ff0e2..54f13af 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/KeyToSignature.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/KeyToSignature.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005 IBM Corporation and others.
+ * Copyright (c) 2005, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -25,11 +25,13 @@
public static final int SIGNATURE = 0;
public static final int TYPE_ARGUMENTS = 1;
public static final int DECLARING_TYPE = 2;
+ public static final int THROWN_EXCEPTIONS = 3;
public StringBuffer signature = new StringBuffer();
private int kind;
private ArrayList arguments = new ArrayList();
private ArrayList typeParameters = new ArrayList();
+ private ArrayList thrownExceptions = new ArrayList();
private int mainTypeStart = -1;
private int mainTypeEnd;
private int typeSigStart = -1;
@@ -68,10 +70,21 @@
public void consumeMethod(char[] selector, char[] methodSignature) {
this.arguments = new ArrayList();
- if (this.kind == SIGNATURE) {
- this.signature = new StringBuffer();
- CharOperation.replace(methodSignature, '/', '.');
- this.signature.append(methodSignature);
+ CharOperation.replace(methodSignature, '/', '.');
+ switch(this.kind) {
+ case SIGNATURE:
+ this.signature = new StringBuffer();
+ this.signature.append(methodSignature);
+ break;
+ case THROWN_EXCEPTIONS:
+ if (CharOperation.indexOf('^', methodSignature) > 0) {
+ char[][] types = Signature.getThrownExceptionTypes(methodSignature);
+ int length = types.length;
+ for (int i=0; i<length; i++) {
+ this.thrownExceptions.add(new String(types[i]));
+ }
+ }
+ break;
}
}
@@ -198,6 +211,16 @@
}
}
+ public void consumeException() {
+ int size = this.arguments.size();
+ if (size > 0) {
+ for (int i=0; i<size; i++) {
+ this.thrownExceptions.add(((KeyToSignature) this.arguments.get(i)).signature.toString());
+ }
+ this.arguments = new ArrayList();
+ }
+ }
+
public void consumeFullyQualifiedName(char[] fullyQualifiedName) {
this.typeSigStart = this.signature.length();
this.signature.append('L');
@@ -252,6 +275,7 @@
KeyToSignature keyToSignature = (KeyToSignature) this.arguments.get(0);
this.signature = keyToSignature.signature;
this.arguments = keyToSignature.arguments;
+ this.thrownExceptions = keyToSignature.thrownExceptions;
}
public void consumeWildCard(int wildCardKind) {
@@ -275,6 +299,15 @@
}
}
+ public String[] getThrownExceptions() {
+ int length = this.thrownExceptions.size();
+ String[] result = new String[length];
+ for (int i = 0; i < length; i++) {
+ result[i] = (String) this.thrownExceptions.get(i);
+ }
+ return result;
+ }
+
public String[] getTypeArguments() {
int length = this.arguments.size();
String[] result = new String[length];
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LRUCache.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LRUCache.java
index 405afa5..14933ec 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LRUCache.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LRUCache.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,6 +10,7 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core.util;
+import java.text.NumberFormat;
import java.util.Enumeration;
import java.util.Hashtable;
@@ -160,6 +161,9 @@
}
return newCache;
}
+ public double fillingRatio() {
+ return (fCurrentSpace) * 100.0 / fSpaceLimit;
+ }
/**
* Flushes all entries from the cache.
*/
@@ -170,7 +174,6 @@
fEntryTable = new Hashtable(); // Clear it out
fEntryQueue = fEntryQueueTail = null;
while (entry != null) { // send deletion notifications in LRU order
- privateNotifyDeletionFromCache(entry);
entry = entry._fPrevious;
}
}
@@ -290,6 +293,20 @@
return new LRUCache(size);
}
/**
+ * Answers the value in the cache at the given key.
+ * If the value is not in the cache, returns null
+ *
+ * This function does not modify timestamps.
+ */
+ public Object peek(Object key) {
+
+ LRUCacheEntry entry = (LRUCacheEntry) fEntryTable.get(key);
+ if (entry == null) {
+ return null;
+ }
+ return entry._fValue;
+ }
+ /**
* Adds an entry for the given key/value/space.
*/
protected void privateAdd (Object key, Object value, int space) {
@@ -325,14 +342,6 @@
fEntryQueue = entry;
}
/**
- * An entry has been removed from the cache, for example because it has
- * fallen off the bottom of the LRU queue.
- * Subclasses could over-ride this to implement a persistent cache below the LRU cache.
- */
- protected void privateNotifyDeletionFromCache(LRUCacheEntry entry) {
- // Default is NOP.
- }
- /**
* Removes the entry from the entry queue.
* @param shuffle indicates whether we are just shuffling the queue
* (in which case, the entry table is not modified).
@@ -347,7 +356,6 @@
if (!shuffle) {
fEntryTable.remove(entry._fKey);
fCurrentSpace -= entry._fSpace;
- privateNotifyDeletionFromCache(entry);
}
/* if this was the first entry */
@@ -443,45 +451,57 @@
return 1;
}
}
-/**
- * Returns a String that represents the value of this object. This method
- * is for debugging purposes only.
- */
-public String toString() {
- return
- "LRUCache " + (fCurrentSpace * 100.0 / fSpaceLimit) + "% full\n" + //$NON-NLS-1$ //$NON-NLS-2$
- this.toStringContents();
-}
-/**
- * Returns a String that represents the contents of this object. This method
- * is for debugging purposes only.
- */
-protected String toStringContents() {
- StringBuffer result = new StringBuffer();
- int length = fEntryTable.size();
- Object[] unsortedKeys = new Object[length];
- String[] unsortedToStrings = new String[length];
- Enumeration e = this.keys();
- for (int i = 0; i < length; i++) {
- Object key = e.nextElement();
- unsortedKeys[i] = key;
- unsortedToStrings[i] =
- (key instanceof org.eclipse.jdt.internal.core.JavaElement) ?
- ((org.eclipse.jdt.internal.core.JavaElement)key).getElementName() :
- key.toString();
+ /**
+ * Returns a String that represents the value of this object. This method
+ * is for debugging purposes only.
+ */
+ public String toString() {
+ return
+ toStringFillingRation("LRUCache") + //$NON-NLS-1$
+ toStringContents();
}
- ToStringSorter sorter = new ToStringSorter();
- sorter.sort(unsortedKeys, unsortedToStrings);
- for (int i = 0; i < length; i++) {
- String toString = sorter.sortedStrings[i];
- Object value = this.get(sorter.sortedObjects[i]);
- result.append(toString);
- result.append(" -> "); //$NON-NLS-1$
- result.append(value);
- result.append("\n"); //$NON-NLS-1$
+
+ /**
+ * Returns a String that represents the contents of this object. This method
+ * is for debugging purposes only.
+ */
+ protected String toStringContents() {
+ StringBuffer result = new StringBuffer();
+ int length = fEntryTable.size();
+ Object[] unsortedKeys = new Object[length];
+ String[] unsortedToStrings = new String[length];
+ Enumeration e = this.keys();
+ for (int i = 0; i < length; i++) {
+ Object key = e.nextElement();
+ unsortedKeys[i] = key;
+ unsortedToStrings[i] =
+ (key instanceof org.eclipse.jdt.internal.core.JavaElement) ?
+ ((org.eclipse.jdt.internal.core.JavaElement)key).getElementName() :
+ key.toString();
+ }
+ ToStringSorter sorter = new ToStringSorter();
+ sorter.sort(unsortedKeys, unsortedToStrings);
+ for (int i = 0; i < length; i++) {
+ String toString = sorter.sortedStrings[i];
+ Object value = this.get(sorter.sortedObjects[i]);
+ result.append(toString);
+ result.append(" -> "); //$NON-NLS-1$
+ result.append(value);
+ result.append("\n"); //$NON-NLS-1$
+ }
+ return result.toString();
}
- return result.toString();
-}
+
+ public String toStringFillingRation(String cacheName) {
+ StringBuffer buffer = new StringBuffer(cacheName);
+ buffer.append('[');
+ buffer.append(getSpaceLimit());
+ buffer.append("]: "); //$NON-NLS-1$
+ buffer.append(NumberFormat.getInstance().format(fillingRatio()));
+ buffer.append("% full"); //$NON-NLS-1$
+ return buffer.toString();
+ }
+
/**
* Updates the timestamp for the given entry, ensuring that the queue is
* kept in correct order. The entry must exist
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LineNumberAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LineNumberAttribute.java
index edfe140..3f5c296 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LineNumberAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LineNumberAttribute.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LocalVariableAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LocalVariableAttribute.java
index 00fe845..60c82c6 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LocalVariableAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LocalVariableAttribute.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LocalVariableTableEntry.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LocalVariableTableEntry.java
index 1f2a8f4..4dc11ad 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LocalVariableTableEntry.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LocalVariableTableEntry.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LocalVariableTypeAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LocalVariableTypeAttribute.java
index 91e87dc..cfd1173 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LocalVariableTypeAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LocalVariableTypeAttribute.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004 IBM Corporation and others.
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LocalVariableTypeTableEntry.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LocalVariableTypeTableEntry.java
index e3eb83d..a3bbabd 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LocalVariableTypeTableEntry.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LocalVariableTypeTableEntry.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/MementoTokenizer.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/MementoTokenizer.java
index 7d7c76f..e3d0095 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/MementoTokenizer.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/MementoTokenizer.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004 IBM Corporation and others.
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Messages.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Messages.java
index 6b5bf2e..d2b890e 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Messages.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Messages.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -36,7 +36,13 @@
public static String element_nullName;
public static String element_nullType;
public static String element_illegalParent;
- public static String sourcetype_invalidName;
+ public static String javamodel_initialization;
+ public static String javamodel_building_after_upgrade;
+ public static String javamodel_configuring;
+ public static String javamodel_configuring_classpath_containers;
+ public static String javamodel_configuring_searchengine;
+ public static String javamodel_getting_build_state_number;
+ public static String javamodel_refreshing_external_jars;
public static String operation_needElements;
public static String operation_needName;
public static String operation_needPath;
@@ -98,6 +104,7 @@
public static String build_prereqProjectHasClasspathProblems;
public static String build_prereqProjectMustBeRebuilt;
public static String build_abortDueToClasspathProblems;
+ public static String status_cannot_retrieve_attached_javadoc;
public static String status_cannotUseDeviceOnPath;
public static String status_coreException;
public static String status_defaultPackageReadOnly;
@@ -119,9 +126,11 @@
public static String status_OK;
public static String status_readOnly;
public static String status_targetException;
+ public static String status_unknown_javadoc_format;
public static String status_updateConflict;
public static String classpath_buildPath;
public static String classpath_cannotNestEntryInEntry;
+ public static String classpath_cannotNestEntryInEntryNoExclusion;
public static String classpath_cannotNestEntryInLibrary;
public static String classpath_cannotNestEntryInOutput;
public static String classpath_cannotNestOutputInEntry;
@@ -159,15 +168,21 @@
public static String classpath_disabledMultipleOutputLocations;
public static String classpath_incompatibleLibraryJDKLevel;
public static String classpath_duplicateEntryExtraAttribute;
+ public static String classpath_deprecated_variable;
public static String file_notFound;
public static String file_badFormat;
public static String path_nullPath;
public static String path_mustBeAbsolute;
public static String cache_invalidLoadFactor;
public static String savedState_jobName;
- public static String javamodel_initialization;
public static String restrictedAccess_project;
public static String restrictedAccess_library;
+ public static String restrictedAccess_constructor_project;
+ public static String restrictedAccess_constructor_library;
+ public static String restrictedAccess_field_project;
+ public static String restrictedAccess_field_library;
+ public static String restrictedAccess_method_project;
+ public static String restrictedAccess_method_library;
public static String convention_unit_nullName;
public static String convention_unit_notJavaName;
public static String convention_classFile_nullName;
@@ -204,6 +219,7 @@
public static String dom_addAncestorAsSibling;
public static String dom_addNullInterface;
public static String dom_nullInterfaces;
+ public static String importRewrite_processDescription;
public static String correction_nullRequestor;
public static String correction_nullUnit;
public static String engine_searching;
@@ -270,6 +286,8 @@
public static String disassembler_runtimevisibleparameterannotationsattributeheader;
public static String disassembler_runtimeinvisibleparameterannotationsattributeheader;
public static String disassembler_parameterannotationentrystart;
+ public static String disassembler_stackmaptableattributeheader;
+ public static String disassembler_stackmapattributeheader;
public static String classfileformat_versiondetails;
public static String classfileformat_methoddescriptor;
public static String classfileformat_fieldddescriptor;
@@ -312,6 +330,15 @@
public static String classfileformat_exceptiontableentry;
public static String classfileformat_linenumbertableentry;
public static String classfileformat_localvariabletableentry;
+ public static String classfileformat_versionUnknown;
+
+ public static String disassembler_frame_same_locals_1_stack_item_extended;
+ public static String disassembler_frame_chop;
+ public static String disassembler_frame_same_frame_extended;
+ public static String disassembler_frame_append;
+ public static String disassembler_frame_full_frame;
+ public static String disassembler_frame_same_frame;
+ public static String disassembler_frame_same_locals_1_stack_item;
static {
NLS.initializeMessages(BUNDLE_NAME, Messages.class);
@@ -360,4 +387,4 @@
public static String bind(String message, Object[] bindings) {
return MessageFormat.format(message, bindings);
}
-}
\ No newline at end of file
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/MethodInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/MethodInfo.java
index 9cae81d..b874fbf 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/MethodInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/MethodInfo.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ParameterAnnotation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ParameterAnnotation.java
index c99113f..3e7d304 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ParameterAnnotation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ParameterAnnotation.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004 IBM Corporation and others.
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/PublicScanner.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/PublicScanner.java
index 6d9095f..db587e2 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/PublicScanner.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/PublicScanner.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,18 +10,15 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core.util;
-import java.util.Iterator;
-
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.compiler.IScanner;
import org.eclipse.jdt.core.compiler.ITerminalSymbols;
import org.eclipse.jdt.core.compiler.InvalidInputException;
import org.eclipse.jdt.internal.compiler.CompilationResult;
-import org.eclipse.jdt.internal.compiler.ast.StringLiteral;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
-import org.eclipse.jdt.internal.compiler.parser.NLSLine;
-import org.eclipse.jdt.internal.compiler.parser.Scanner;
+import org.eclipse.jdt.internal.compiler.parser.NLSTag;
import org.eclipse.jdt.internal.compiler.parser.ScannerHelper;
+import org.eclipse.jdt.internal.compiler.util.Util;
public class PublicScanner implements IScanner, ITerminalSymbols {
@@ -35,8 +32,8 @@
- sourceStart gives the position into the stream
- currentPosition-1 gives the sourceEnd position into the stream
*/
- protected long sourceLevel;
- protected long complianceLevel;
+ public long sourceLevel;
+ public long complianceLevel;
// 1.4 feature
public boolean useAssertAsAnIndentifier = false;
@@ -68,7 +65,7 @@
public boolean scanningFloatLiteral = false;
//support for /** comments
- public static int COMMENT_ARRAYS_SIZE = 30;
+ public final static int COMMENT_ARRAYS_SIZE = 30;
public int[] commentStops = new int[COMMENT_ARRAYS_SIZE];
public int[] commentStarts = new int[COMMENT_ARRAYS_SIZE];
public int[] commentTagStarts = new int[COMMENT_ARRAYS_SIZE];
@@ -111,7 +108,7 @@
public static final String UNTERMINATED_COMMENT = "Unterminated_Comment"; //$NON-NLS-1$
public static final String INVALID_CHAR_IN_STRING = "Invalid_Char_In_String"; //$NON-NLS-1$
public static final String INVALID_DIGIT = "Invalid_Digit"; //$NON-NLS-1$
- private static final int[] EMPTY_LINE_ENDS = new int[0];
+ private static final int[] EMPTY_LINE_ENDS = Util.EMPTY_INT_ARRAY;
//----------------optimized identifier managment------------------
static final char[] charArray_a = new char[] {'a'},
@@ -145,69 +142,17 @@
new char[] {'\u0000', '\u0000', '\u0000', '\u0000', '\u0000', '\u0000'};
static final int TableSize = 30, InternalTableSize = 6; //30*6 =210 entries
- public final static int MAX_OBVIOUS = 128;
- static final int[] ObviousIdentCharNatures = new int[MAX_OBVIOUS];
- public final static int C_LETTER = 4;
- public final static int C_DIGIT = 3;
- public final static int C_SEPARATOR = 2;
- public final static int C_SPACE = 1;
- static {
- for (int i = '0'; i <= '9'; i++)
- ObviousIdentCharNatures[i] = C_DIGIT;
-
- for (int i = 'a'; i <= 'z'; i++)
- ObviousIdentCharNatures[i] = C_LETTER;
- for (int i = 'A'; i <= 'Z'; i++)
- ObviousIdentCharNatures[i] = C_LETTER;
- ObviousIdentCharNatures['_'] = C_LETTER;
- ObviousIdentCharNatures['$'] = C_LETTER;
-
- ObviousIdentCharNatures[10] = C_SPACE; // \ u000a: LINE FEED
- ObviousIdentCharNatures[12] = C_SPACE; // \ u000c: FORM FEED
- ObviousIdentCharNatures[13] = C_SPACE; // \ u000d: CARRIAGE RETURN
- ObviousIdentCharNatures[32] = C_SPACE; // \ u0020: SPACE
- ObviousIdentCharNatures[ 9] = C_SPACE; // \ u0009: HORIZONTAL TABULATION
-
- ObviousIdentCharNatures['.'] = C_SEPARATOR;
- ObviousIdentCharNatures[':'] = C_SEPARATOR;
- ObviousIdentCharNatures[';'] = C_SEPARATOR;
- ObviousIdentCharNatures[','] = C_SEPARATOR;
- ObviousIdentCharNatures['['] = C_SEPARATOR;
- ObviousIdentCharNatures[']'] = C_SEPARATOR;
- ObviousIdentCharNatures['('] = C_SEPARATOR;
- ObviousIdentCharNatures[')'] = C_SEPARATOR;
- ObviousIdentCharNatures['{'] = C_SEPARATOR;
- ObviousIdentCharNatures['}'] = C_SEPARATOR;
- ObviousIdentCharNatures['+'] = C_SEPARATOR;
- ObviousIdentCharNatures['-'] = C_SEPARATOR;
- ObviousIdentCharNatures['*'] = C_SEPARATOR;
- ObviousIdentCharNatures['/'] = C_SEPARATOR;
- ObviousIdentCharNatures['='] = C_SEPARATOR;
- ObviousIdentCharNatures['&'] = C_SEPARATOR;
- ObviousIdentCharNatures['|'] = C_SEPARATOR;
- ObviousIdentCharNatures['?'] = C_SEPARATOR;
- ObviousIdentCharNatures['<'] = C_SEPARATOR;
- ObviousIdentCharNatures['>'] = C_SEPARATOR;
- ObviousIdentCharNatures['!'] = C_SEPARATOR;
- ObviousIdentCharNatures['%'] = C_SEPARATOR;
- ObviousIdentCharNatures['^'] = C_SEPARATOR;
- ObviousIdentCharNatures['~'] = C_SEPARATOR;
- ObviousIdentCharNatures['"'] = C_SEPARATOR;
- ObviousIdentCharNatures['\''] = C_SEPARATOR;
- }
-
public static final int OptimizedLength = 7;
public /*static*/ final char[][][][] charArray_length =
new char[OptimizedLength][TableSize][InternalTableSize][];
// support for detecting non-externalized string literals
- public NLSLine currentLine= null;
- public static final String TAG_PREFIX= "//$NON-NLS-"; //$NON-NLS-1$
- public static final int TAG_PREFIX_LENGTH= TAG_PREFIX.length();
- public static final String TAG_POSTFIX= "$"; //$NON-NLS-1$
- public static final int TAG_POSTFIX_LENGTH= TAG_POSTFIX.length();
- public StringLiteral[] nonNLSStrings = null;
- public boolean checkNonExternalizedStringLiterals = false;
- public boolean wasNonExternalizedStringLiteral = false;
+ public static final char[] TAG_PREFIX= "//$NON-NLS-".toCharArray(); //$NON-NLS-1$
+ public static final int TAG_PREFIX_LENGTH= TAG_PREFIX.length;
+ public static final char TAG_POSTFIX= '$';
+ public static final int TAG_POSTFIX_LENGTH= 1;
+ private NLSTag[] nlsTags = null;
+ protected int nlsTagsPtr;
+ public boolean checkNonExternalizedStringLiterals;
// generic support
public boolean returnOnlyGreater = false;
@@ -226,6 +171,7 @@
newEntry4 = 0,
newEntry5 = 0,
newEntry6 = 0;
+ public boolean insideRecovery = false;
public static final int RoundBracket = 0;
public static final int SquareBracket = 1;
@@ -243,57 +189,51 @@
}
public PublicScanner(
- boolean tokenizeComments,
- boolean tokenizeWhiteSpace,
- boolean checkNonExternalizedStringLiterals,
- long sourceLevel,
- long complianceLevel,
- char[][] taskTags,
- char[][] taskPriorities,
- boolean isTaskCaseSensitive) {
+ boolean tokenizeComments,
+ boolean tokenizeWhiteSpace,
+ boolean checkNonExternalizedStringLiterals,
+ long sourceLevel,
+ long complianceLevel,
+ char[][] taskTags,
+ char[][] taskPriorities,
+ boolean isTaskCaseSensitive) {
this.eofPosition = Integer.MAX_VALUE;
this.tokenizeComments = tokenizeComments;
this.tokenizeWhiteSpace = tokenizeWhiteSpace;
- this.checkNonExternalizedStringLiterals = checkNonExternalizedStringLiterals;
this.sourceLevel = sourceLevel;
this.complianceLevel = complianceLevel;
+ this.checkNonExternalizedStringLiterals = checkNonExternalizedStringLiterals;
this.taskTags = taskTags;
this.taskPriorities = taskPriorities;
this.isTaskCaseSensitive = isTaskCaseSensitive;
}
public PublicScanner(
- boolean tokenizeComments,
- boolean tokenizeWhiteSpace,
- boolean checkNonExternalizedStringLiterals,
- long sourceLevel,
- char[][] taskTags,
- char[][] taskPriorities,
- boolean isTaskCaseSensitive) {
+ boolean tokenizeComments,
+ boolean tokenizeWhiteSpace,
+ boolean checkNonExternalizedStringLiterals,
+ long sourceLevel,
+ char[][] taskTags,
+ char[][] taskPriorities,
+ boolean isTaskCaseSensitive) {
- this.eofPosition = Integer.MAX_VALUE;
- this.tokenizeComments = tokenizeComments;
- this.tokenizeWhiteSpace = tokenizeWhiteSpace;
- this.checkNonExternalizedStringLiterals = checkNonExternalizedStringLiterals;
- this.sourceLevel = sourceLevel;
- this.complianceLevel = sourceLevel;
- this.taskTags = taskTags;
- this.taskPriorities = taskPriorities;
- this.isTaskCaseSensitive = isTaskCaseSensitive;
+ this(
+ tokenizeComments,
+ tokenizeWhiteSpace,
+ checkNonExternalizedStringLiterals,
+ sourceLevel,
+ sourceLevel,
+ taskTags,
+ taskPriorities,
+ isTaskCaseSensitive);
}
-public final boolean atEnd() {
+public final boolean atEnd() {
// This code is not relevant if source is
// Only a part of the real stream input
- return this.source.length == this.currentPosition;
-}
-
-protected void checkNonExternalizedString() {
- if (this.currentLine == null)
- return;
- parseTags(this.currentLine);
+ return this.eofPosition <= this.currentPosition;
}
// chech presence of task: tags
@@ -308,7 +248,7 @@
}
int foundTaskIndex = this.foundTaskCount;
char previous = src[commentStart+1]; // should be '*' or '/'
- nextChar : for (
+ for (
int i = commentStart + 2; i < commentEnd && i < this.eofPosition; i++) {
char[] tag = null;
char[] priority = null;
@@ -320,8 +260,8 @@
if (tagLength == 0) continue nextTag;
// ensure tag is not leaded with letter if tag starts with a letter
- if (Character.isJavaIdentifierStart(tag[0])) {
- if (Character.isJavaIdentifierPart(previous)) {
+ if (ScannerHelper.isJavaIdentifierStart(tag[0])) {
+ if (ScannerHelper.isJavaIdentifierPart(previous)) {
continue nextTag;
}
}
@@ -331,14 +271,14 @@
int x = i+t;
if (x >= this.eofPosition || x >= commentEnd) continue nextTag;
if ((sc = src[i + t]) != (tc = tag[t])) { // case sensitive check
- if (this.isTaskCaseSensitive || (Character.toLowerCase(sc) != Character.toLowerCase(tc))) { // case insensitive check
+ if (this.isTaskCaseSensitive || (ScannerHelper.toLowerCase(sc) != ScannerHelper.toLowerCase(tc))) { // case insensitive check
continue nextTag;
}
}
}
// ensure tag is not followed with letter if tag finishes with a letter
- if (i+tagLength < commentEnd && Character.isJavaIdentifierPart(src[i+tagLength-1])) {
- if (Character.isJavaIdentifierPart(src[i + tagLength]))
+ if (i+tagLength < commentEnd && ScannerHelper.isJavaIdentifierPart(src[i+tagLength-1])) {
+ if (ScannerHelper.isJavaIdentifierPart(src[i + tagLength]))
continue nextTag;
}
if (this.foundTaskTags == null) {
@@ -368,6 +308,7 @@
}
previous = src[i];
}
+ boolean containsEmptyTask = false;
for (int i = foundTaskIndex; i < this.foundTaskCount; i++) {
// retrieve message start and end positions
int msgStart = this.foundTaskPositions[i][0] + this.foundTaskTags[i].length;
@@ -396,8 +337,12 @@
if (end == -1)
end = max_value;
}
- if (msgStart == end)
- continue; // empty
+ if (msgStart == end) {
+ // if the description is empty, we might want to see if two tags are not sharing the same message
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=110797
+ containsEmptyTask = true;
+ continue;
+ }
// trim the message
while (CharOperation.isWhitespace(src[end]) && msgStart <= end)
end--;
@@ -411,6 +356,19 @@
System.arraycopy(src, msgStart, message, 0, messageLength);
this.foundTaskMessages[i] = message;
}
+ if (containsEmptyTask) {
+ for (int i = foundTaskIndex, max = this.foundTaskCount; i < max; i++) {
+ if (this.foundTaskMessages[i].length == 0) {
+ loop: for (int j = i + 1; j < max; j++) {
+ if (this.foundTaskMessages[j].length != 0) {
+ this.foundTaskMessages[i] = this.foundTaskMessages[j];
+ this.foundTaskPositions[i][1] = this.foundTaskPositions[j][1];
+ break loop;
+ }
+ }
+ }
+ }
+ }
}
public char[] getCurrentIdentifierSource() {
@@ -427,7 +385,7 @@
this.withoutUnicodePtr);
} else {
int length = this.currentPosition - this.startPosition;
- if (length == this.source.length) return this.source;
+ if (length == this.eofPosition) return this.source;
switch (length) { // see OptimizedLength
case 1 :
return optimizedCurrentTokenSource1();
@@ -451,7 +409,7 @@
public int getCurrentTokenEndPosition(){
return this.currentPosition - 1;
}
-public final char[] getCurrentTokenSource() {
+public char[] getCurrentTokenSource() {
// Return the token REAL source (aka unicodes are precomputed)
char[] result;
@@ -489,7 +447,7 @@
this.startPosition,
this.currentPosition - this.startPosition);
}
-public final char[] getCurrentTokenSourceString() {
+public char[] getCurrentTokenSourceString() {
//return the token REAL source (aka unicodes are precomputed).
//REMOVE the two " that are at the beginning and the end.
@@ -614,6 +572,32 @@
return -1;
}
}
+public final int getNextCharWithBoundChecks() {
+ if (this.currentPosition >= this.eofPosition) {
+ return -1;
+ }
+ this.currentCharacter = this.source[this.currentPosition++];
+ if (this.currentPosition >= this.eofPosition) {
+ this.unicodeAsBackSlash = false;
+ if (this.withoutUnicodePtr != 0) {
+ unicodeStore();
+ }
+ return this.currentCharacter;
+ }
+ if (this.currentCharacter == '\\' && this.source[this.currentPosition] == 'u') {
+ try {
+ getNextUnicodeChar();
+ } catch (InvalidInputException e) {
+ return -1;
+ }
+ } else {
+ this.unicodeAsBackSlash = false;
+ if (this.withoutUnicodePtr != 0) {
+ unicodeStore();
+ }
+ }
+ return this.currentCharacter;
+}
public final boolean getNextChar(char testedChar) {
//BOOLEAN
//handle the case of unicode.
@@ -625,7 +609,7 @@
//ALL getNextChar.... ARE OPTIMIZED COPIES
- if (this.currentPosition >= this.source.length) { // handle the obvious case upfront
+ if (this.currentPosition >= this.eofPosition) { // handle the obvious case upfront
this.unicodeAsBackSlash = false;
return false;
}
@@ -673,7 +657,7 @@
//On false, no side effect has occured.
//ALL getNextChar.... ARE OPTIMIZED COPIES
- if (this.currentPosition >= this.source.length) // handle the obvious case upfront
+ if (this.currentPosition >= this.eofPosition) // handle the obvious case upfront
return -1;
int temp = this.currentPosition;
@@ -724,7 +708,7 @@
//On false, no side effect has occured.
//ALL getNextChar.... ARE OPTIMIZED COPIES
- if (this.currentPosition >= this.source.length) // handle the obvious case upfront
+ if (this.currentPosition >= this.eofPosition) // handle the obvious case upfront
return false;
int temp = this.currentPosition;
@@ -732,14 +716,14 @@
if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
&& (this.source[this.currentPosition] == 'u')) {
getNextUnicodeChar();
- if (!isDigit(this.currentCharacter)) {
+ if (!ScannerHelper.isDigit(this.currentCharacter)) {
this.currentPosition = temp;
this.withoutUnicodePtr--;
return false;
}
return true;
} else {
- if (!isDigit(this.currentCharacter)) {
+ if (!ScannerHelper.isDigit(this.currentCharacter)) {
this.currentPosition = temp;
return false;
}
@@ -765,7 +749,7 @@
//On false, no side effect has occured.
//ALL getNextChar.... ARE OPTIMIZED COPIES
- if (this.currentPosition >= this.source.length) // handle the obvious case upfront
+ if (this.currentPosition >= this.eofPosition) // handle the obvious case upfront
return false;
int temp = this.currentPosition;
@@ -773,14 +757,14 @@
if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
&& (this.source[this.currentPosition] == 'u')) {
getNextUnicodeChar();
- if (Character.digit(this.currentCharacter, radix) == -1) {
+ if (ScannerHelper.digit(this.currentCharacter, radix) == -1) {
this.currentPosition = temp;
this.withoutUnicodePtr--;
return false;
}
return true;
} else {
- if (Character.digit(this.currentCharacter, radix) == -1) {
+ if (ScannerHelper.digit(this.currentCharacter, radix) == -1) {
this.currentPosition = temp;
return false;
}
@@ -796,6 +780,78 @@
return false;
}
}
+public boolean getNextCharAsJavaIdentifierPartWithBoundCheck() {
+ //BOOLEAN
+ //handle the case of unicode.
+ //when a unicode appears then we must use a buffer that holds char internal values
+ //At the end of this method currentCharacter holds the new visited char
+ //and currentPosition points right next after it
+ //Both previous lines are true if the currentCharacter is a JavaIdentifierPart
+ //On false, no side effect has occured.
+
+ //ALL getNextChar.... ARE OPTIMIZED COPIES
+ int pos = this.currentPosition;
+ if (pos >= this.eofPosition) // handle the obvious case upfront
+ return false;
+
+ int temp2 = this.withoutUnicodePtr;
+ try {
+ boolean unicode = false;
+ this.currentCharacter = this.source[this.currentPosition++];
+ if (this.currentPosition < this.eofPosition) {
+ if (this.currentCharacter == '\\' && this.source[this.currentPosition] == 'u') {
+ getNextUnicodeChar();
+ unicode = true;
+ }
+ }
+ char c = this.currentCharacter;
+ boolean isJavaIdentifierPart = false;
+ if (c >= HIGH_SURROGATE_MIN_VALUE && c <= HIGH_SURROGATE_MAX_VALUE) {
+ if (this.complianceLevel < ClassFileConstants.JDK1_5) {
+ this.currentPosition = pos;
+ this.withoutUnicodePtr = temp2;
+ return false;
+ }
+ // Unicode 4 detection
+ char low = (char) getNextCharWithBoundChecks();
+ if (low < LOW_SURROGATE_MIN_VALUE || low > LOW_SURROGATE_MAX_VALUE) {
+ // illegal low surrogate
+ this.currentPosition = pos;
+ this.withoutUnicodePtr = temp2;
+ return false;
+ }
+ isJavaIdentifierPart = ScannerHelper.isJavaIdentifierPart(c, low);
+ }
+ else if (c >= LOW_SURROGATE_MIN_VALUE && c <= LOW_SURROGATE_MAX_VALUE) {
+ this.currentPosition = pos;
+ this.withoutUnicodePtr = temp2;
+ return false;
+ } else {
+ isJavaIdentifierPart = ScannerHelper.isJavaIdentifierPart(c);
+ }
+ if (unicode) {
+ if (!isJavaIdentifierPart) {
+ this.currentPosition = pos;
+ this.withoutUnicodePtr = temp2;
+ return false;
+ }
+ return true;
+ } else {
+ if (!isJavaIdentifierPart) {
+ this.currentPosition = pos;
+ return false;
+ }
+
+ if (this.withoutUnicodePtr != 0)
+ unicodeStore();
+ return true;
+ }
+ } catch(InvalidInputException e) {
+ this.currentPosition = pos;
+ this.withoutUnicodePtr = temp2;
+ return false;
+ }
+}
public boolean getNextCharAsJavaIdentifierPart() {
//BOOLEAN
//handle the case of unicode.
@@ -807,7 +863,7 @@
//ALL getNextChar.... ARE OPTIMIZED COPIES
int pos;
- if ((pos = this.currentPosition) >= this.source.length) // handle the obvious case upfront
+ if ((pos = this.currentPosition) >= this.eofPosition) // handle the obvious case upfront
return false;
int temp2 = this.withoutUnicodePtr;
@@ -841,7 +897,7 @@
this.withoutUnicodePtr = temp2;
return false;
} else {
- isJavaIdentifierPart = Character.isJavaIdentifierPart(c);
+ isJavaIdentifierPart = ScannerHelper.isJavaIdentifierPart(c);
}
if (unicode) {
if (!isJavaIdentifierPart) {
@@ -870,12 +926,118 @@
return false;
}
}
+/*
+ * External API in JavaConventions.
+ * This is used to optimize the case where the scanner is used to scan a single identifier.
+ * In this case, the AIOOBE is slower to handle than a bound check
+ */
+public int scanIdentifier() throws InvalidInputException {
+ int whiteStart = 0;
+ while (true) { //loop for jumping over comments
+ this.withoutUnicodePtr = 0;
+ //start with a new token (even comment written with unicode )
+ // ---------Consume white space and handles startPosition---------
+ whiteStart = this.currentPosition;
+ boolean isWhiteSpace, hasWhiteSpaces = false;
+ int offset;
+ int unicodePtr;
+ boolean checkIfUnicode = false;
+ do {
+ unicodePtr = this.withoutUnicodePtr;
+ offset = this.currentPosition;
+ this.startPosition = this.currentPosition;
+ if (this.currentPosition < this.eofPosition) {
+ this.currentCharacter = this.source[this.currentPosition++];
+ checkIfUnicode = this.currentPosition < this.eofPosition
+ && this.currentCharacter == '\\'
+ && this.source[this.currentPosition] == 'u';
+ } else if (this.tokenizeWhiteSpace && (whiteStart != this.currentPosition - 1)) {
+ // reposition scanner in case we are interested by spaces as tokens
+ this.currentPosition--;
+ this.startPosition = whiteStart;
+ return TokenNameWHITESPACE;
+ } else {
+ return TokenNameEOF;
+ }
+ if (checkIfUnicode) {
+ isWhiteSpace = jumpOverUnicodeWhiteSpace();
+ offset = this.currentPosition - offset;
+ } else {
+ offset = this.currentPosition - offset;
+ // inline version of:
+ //isWhiteSpace =
+ // (this.currentCharacter == ' ') || ScannerHelper.isWhitespace(this.currentCharacter);
+ switch (this.currentCharacter) {
+ case 10 : /* \ u000a: LINE FEED */
+ case 12 : /* \ u000c: FORM FEED */
+ case 13 : /* \ u000d: CARRIAGE RETURN */
+ case 32 : /* \ u0020: SPACE */
+ case 9 : /* \ u0009: HORIZONTAL TABULATION */
+ isWhiteSpace = true;
+ break;
+ default :
+ isWhiteSpace = false;
+ }
+ }
+ if (isWhiteSpace) {
+ hasWhiteSpaces = true;
+ }
+ } while (isWhiteSpace);
+ if (hasWhiteSpaces) {
+ if (this.tokenizeWhiteSpace) {
+ // reposition scanner in case we are interested by spaces as tokens
+ this.currentPosition-=offset;
+ this.startPosition = whiteStart;
+ if (checkIfUnicode) {
+ this.withoutUnicodePtr = unicodePtr;
+ }
+ return TokenNameWHITESPACE;
+ } else if (checkIfUnicode) {
+ this.withoutUnicodePtr = 0;
+ unicodeStore();
+ } else {
+ this.withoutUnicodePtr = 0;
+ }
+ }
+ char c = this.currentCharacter;
+ if (c < ScannerHelper.MAX_OBVIOUS) {
+ if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_IDENT_START) != 0) {
+ return scanIdentifierOrKeywordWithBoundCheck();
+ }
+ return TokenNameERROR;
+ }
+ boolean isJavaIdStart;
+ if (c >= HIGH_SURROGATE_MIN_VALUE && c <= HIGH_SURROGATE_MAX_VALUE) {
+ if (this.complianceLevel < ClassFileConstants.JDK1_5) {
+ throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
+ }
+ // Unicode 4 detection
+ char low = (char) getNextCharWithBoundChecks();
+ if (low < LOW_SURROGATE_MIN_VALUE || low > LOW_SURROGATE_MAX_VALUE) {
+ // illegal low surrogate
+ throw new InvalidInputException(INVALID_LOW_SURROGATE);
+ }
+ isJavaIdStart = ScannerHelper.isJavaIdentifierStart(c, low);
+ } else if (c >= LOW_SURROGATE_MIN_VALUE && c <= LOW_SURROGATE_MAX_VALUE) {
+ if (this.complianceLevel < ClassFileConstants.JDK1_5) {
+ throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
+ }
+ throw new InvalidInputException(INVALID_HIGH_SURROGATE);
+ } else {
+ // optimized case already checked
+ isJavaIdStart = Character.isJavaIdentifierStart(c);
+ }
+ if (isJavaIdStart)
+ return scanIdentifierOrKeywordWithBoundCheck();
+ return TokenNameERROR;
+ }
+}
public int getNextToken() throws InvalidInputException {
this.wasAcr = false;
if (this.diet) {
jumpOverMethodBody();
this.diet = false;
- return this.currentPosition > this.source.length ? TokenNameEOF : TokenNameRBRACE;
+ return this.currentPosition > this.eofPosition ? TokenNameEOF : TokenNameRBRACE;
}
int whiteStart = 0;
try {
@@ -906,7 +1068,6 @@
if (this.currentPosition > this.eofPosition)
return TokenNameEOF;
}
- //little trick to get out in the middle of a source compuation
if (this.currentPosition > this.eofPosition)
return TokenNameEOF;
if (checkIfUnicode) {
@@ -915,16 +1076,13 @@
} else {
offset = this.currentPosition - offset;
if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
- checkNonExternalizedString();
if (this.recordLineSeparator) {
pushLineSeparator();
- } else {
- this.currentLine = null;
}
}
// inline version of:
//isWhiteSpace =
- // (this.currentCharacter == ' ') || CharOperation.isWhitespace(this.currentCharacter);
+ // (this.currentCharacter == ' ') || ScannerHelper.isWhitespace(this.currentCharacter);
switch (this.currentCharacter) {
case 10 : /* \ u000a: LINE FEED */
case 12 : /* \ u000c: FORM FEED */
@@ -986,22 +1144,6 @@
if (getNextCharAsDigit()) {
return scanNumber(true);
}
-/* if (this.sourceLevel >= ClassFileConstants.JDK1_5) {
- int temp = this.currentPosition;
- if (getNextChar('.')) {
- if (getNextChar('.')) {
- return TokenNameELLIPSIS;
- } else {
- this.currentPosition = temp;
- return TokenNameDOT;
- }
- } else {
- this.currentPosition = temp;
- return TokenNameDOT;
- }
- } else {
- return TokenNameDOT;
- }*/
int temp = this.currentPosition;
if (getNextChar('.')) {
if (getNextChar('.')) {
@@ -1117,7 +1259,7 @@
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 (this.currentPosition + lookAhead == this.source.length)
+ if (this.currentPosition + lookAhead == this.eofPosition)
break;
if (this.source[this.currentPosition + lookAhead] == '\n')
break;
@@ -1132,7 +1274,7 @@
if (getNextChar('\'')) {
// relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
for (int lookAhead = 0; lookAhead < 3; lookAhead++) {
- if (this.currentPosition + lookAhead == this.source.length)
+ if (this.currentPosition + lookAhead == this.eofPosition)
break;
if (this.source[this.currentPosition + lookAhead] == '\n')
break;
@@ -1180,7 +1322,7 @@
return TokenNameCharacterLiteral;
// relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
for (int lookAhead = 0; lookAhead < 20; lookAhead++) {
- if (this.currentPosition + lookAhead == this.source.length)
+ if (this.currentPosition + lookAhead == this.eofPosition)
break;
if (this.source[this.currentPosition + lookAhead] == '\n')
break;
@@ -1242,7 +1384,10 @@
this.unicodeAsBackSlash = false;
if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) {
getNextUnicodeChar();
+ isUnicode = true;
this.withoutUnicodePtr--;
+ } else {
+ isUnicode = false;
}
} else {
if (this.withoutUnicodePtr == 0) {
@@ -1262,7 +1407,9 @@
if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
&& (this.source[this.currentPosition] == 'u')) {
getNextUnicodeChar();
+ isUnicode = true;
} else {
+ isUnicode = false;
if (this.withoutUnicodePtr != 0) {
unicodeStore();
}
@@ -1276,7 +1423,7 @@
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 (this.currentPosition + lookAhead == this.source.length)
+ if (this.currentPosition + lookAhead == this.eofPosition)
break;
if (this.source[this.currentPosition + lookAhead] == '\n')
break;
@@ -1289,16 +1436,6 @@
}
throw e; // rethrow
}
- if (this.checkNonExternalizedStringLiterals){ // check for presence of NLS tags //$NON-NLS-?$ where ? is an int.
- if (this.currentLine == null) {
- this.currentLine = new NLSLine();
- }
- this.currentLine.add(
- new StringLiteral(
- getCurrentTokenSourceString(),
- this.startPosition,
- this.currentPosition - 1));
- }
return TokenNameStringLiteral;
case '/' :
{
@@ -1336,7 +1473,7 @@
* We need to completely consume the line break
*/
if (this.currentCharacter == '\r'
- && this.source.length > this.currentPosition) {
+ && this.eofPosition > this.currentPosition) {
if (this.source[this.currentPosition] == '\n') {
this.currentPosition++;
this.currentCharacter = '\n';
@@ -1349,15 +1486,15 @@
recordComment(TokenNameCOMMENT_LINE);
if (this.taskTags != null) checkTaskTag(this.startPosition, this.currentPosition);
if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
- checkNonExternalizedString();
+ if (this.checkNonExternalizedStringLiterals) {
+ parseTags();
+ }
if (this.recordLineSeparator) {
if (isUnicode) {
pushUnicodeLineSeparator();
} else {
pushLineSeparator();
}
- } else {
- this.currentLine = null;
}
}
if (this.tokenizeComments) {
@@ -1367,6 +1504,9 @@
this.currentPosition--;
recordComment(TokenNameCOMMENT_LINE);
if (this.taskTags != null) checkTaskTag(this.startPosition, this.currentPosition);
+ if (this.checkNonExternalizedStringLiterals) {
+ parseTags();
+ }
if (this.tokenizeComments) {
return TokenNameCOMMENT_LINE;
} else {
@@ -1398,15 +1538,12 @@
star = true;
}
if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
- checkNonExternalizedString();
if (this.recordLineSeparator) {
if (isUnicode) {
pushUnicodeLineSeparator();
} else {
pushLineSeparator();
}
- } else {
- this.currentLine = null;
}
}
isUnicode = false;
@@ -1432,15 +1569,12 @@
int firstTag = 0;
while ((this.currentCharacter != '/') || (!star)) {
if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
- checkNonExternalizedString();
if (this.recordLineSeparator) {
if (isUnicode) {
pushUnicodeLineSeparator();
} else {
pushLineSeparator();
}
- } else {
- this.currentLine = null;
}
}
switch (this.currentCharacter) {
@@ -1498,15 +1632,15 @@
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 :
char c = this.currentCharacter;
- if (c < MAX_OBVIOUS) {
- switch (ObviousIdentCharNatures[c]) {
- case C_LETTER :
- return scanIdentifierOrKeyword();
- case C_DIGIT :
+ if (c < ScannerHelper.MAX_OBVIOUS) {
+ if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_IDENT_START) != 0) {
+ return scanIdentifierOrKeyword();
+ } else if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_DIGIT) != 0) {
return scanNumber(false);
+ } else {
+ return TokenNameERROR;
}
}
boolean isJavaIdStart;
@@ -1528,11 +1662,12 @@
}
throw new InvalidInputException(INVALID_HIGH_SURROGATE);
} else {
+ // optimized case already checked
isJavaIdStart = Character.isJavaIdentifierStart(c);
}
if (isJavaIdStart)
return scanIdentifierOrKeyword();
- if (isDigit(this.currentCharacter)) {
+ if (ScannerHelper.isDigit(this.currentCharacter)) {
return scanNumber(false);
}
return TokenNameERROR;
@@ -1558,70 +1693,66 @@
//and currentPosition points right next after it
//ALL getNextChar.... ARE OPTIMIZED COPIES
-
- try {
- int c1 = 0, c2 = 0, c3 = 0, c4 = 0, unicodeSize = 6;
- this.currentPosition++;
+ int c1 = 0, c2 = 0, c3 = 0, c4 = 0, unicodeSize = 6;
+ this.currentPosition++;
+ if (this.currentPosition < this.eofPosition) {
while (this.source[this.currentPosition] == 'u') {
this.currentPosition++;
+ if (this.currentPosition >= this.eofPosition) {
+ this.currentPosition--;
+ throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
+ }
unicodeSize++;
}
-
- if ((c1 = Character.getNumericValue(this.source[this.currentPosition++])) > 15
- || c1 < 0
- || (c2 = Character.getNumericValue(this.source[this.currentPosition++])) > 15
- || c2 < 0
- || (c3 = Character.getNumericValue(this.source[this.currentPosition++])) > 15
- || c3 < 0
- || (c4 = Character.getNumericValue(this.source[this.currentPosition++])) > 15
- || c4 < 0){
- throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
- }
- this.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
- //need the unicode buffer
- if (this.withoutUnicodePtr == 0) {
- //buffer all the entries that have been left aside....
- unicodeInitializeBuffer(this.currentPosition - unicodeSize - this.startPosition);
- }
- //fill the buffer with the char
- unicodeStore();
- this.unicodeAsBackSlash = this.currentCharacter == '\\';
- } catch (ArrayIndexOutOfBoundsException e) {
+ } else {
this.currentPosition--;
throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
}
-}
+ if ((this.currentPosition + 4) > this.eofPosition) {
+ this.currentPosition += (this.eofPosition - this.currentPosition);
+ throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
+ }
+ if ((c1 = ScannerHelper.getNumericValue(this.source[this.currentPosition++])) > 15
+ || c1 < 0
+ || (c2 = ScannerHelper.getNumericValue(this.source[this.currentPosition++])) > 15
+ || c2 < 0
+ || (c3 = ScannerHelper.getNumericValue(this.source[this.currentPosition++])) > 15
+ || c3 < 0
+ || (c4 = ScannerHelper.getNumericValue(this.source[this.currentPosition++])) > 15
+ || c4 < 0){
+ throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
+ }
+ this.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+ //need the unicode buffer
+ if (this.withoutUnicodePtr == 0) {
+ //buffer all the entries that have been left aside....
+ unicodeInitializeBuffer(this.currentPosition - unicodeSize - this.startPosition);
+ }
+ //fill the buffer with the char
+ unicodeStore();
+ this.unicodeAsBackSlash = this.currentCharacter == '\\';
+}
+public NLSTag[] getNLSTags() {
+ final int length = this.nlsTagsPtr;
+ if (length != 0) {
+ NLSTag[] result = new NLSTag[length];
+ System.arraycopy(this.nlsTags, 0, result, 0, length);
+ this.nlsTagsPtr = 0;
+ return result;
+ }
+ return null;
+}
public char[] getSource(){
return this.source;
}
-// TODO (philippe) should simply switch on character
-protected boolean isDigit(char c) throws InvalidInputException {
- if (Character.isDigit(c)) {
- switch(c) {
- case '0' :
- case '1' :
- case '2' :
- case '3' :
- case '4' :
- case '5' :
- case '6' :
- case '7' :
- case '8' :
- case '9' :
- return true;
- }
- throw new InvalidInputException(Scanner.INVALID_DIGIT);
- } else {
- return false;
- }
-}
public final void jumpOverMethodBody() {
this.wasAcr = false;
int found = 1;
try {
while (true) { //loop for jumping over comments
+ this.withoutUnicodePtr = 0;
// ---------Consume white space and handles startPosition---------
boolean isWhiteSpace;
do {
@@ -1631,8 +1762,9 @@
isWhiteSpace = jumpOverUnicodeWhiteSpace();
} else {
if (this.recordLineSeparator
- && ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')))
+ && ((this.currentCharacter == '\r') || (this.currentCharacter == '\n'))) {
pushLineSeparator();
+ }
isWhiteSpace = CharOperation.isWhitespace(this.currentCharacter);
}
} while (isWhiteSpace);
@@ -1785,7 +1917,7 @@
* We need to completely consume the line break
*/
if (this.currentCharacter == '\r'
- && this.source.length > this.currentPosition) {
+ && this.eofPosition > this.currentPosition) {
if (this.source[this.currentPosition] == '\n') {
this.currentPosition++;
this.currentCharacter = '\n';
@@ -1798,16 +1930,24 @@
recordComment(TokenNameCOMMENT_LINE);
if (this.recordLineSeparator
&& ((this.currentCharacter == '\r') || (this.currentCharacter == '\n'))) {
- if (isUnicode) {
- pushUnicodeLineSeparator();
- } else {
- pushLineSeparator();
+ if (this.checkNonExternalizedStringLiterals) {
+ parseTags();
+ }
+ if (this.recordLineSeparator) {
+ if (isUnicode) {
+ pushUnicodeLineSeparator();
+ } else {
+ pushLineSeparator();
+ }
}
}
} catch (IndexOutOfBoundsException e) {
//an eof will then be generated
this.currentPosition--;
recordComment(TokenNameCOMMENT_LINE);
+ if (this.checkNonExternalizedStringLiterals) {
+ parseTags();
+ }
if (!this.tokenizeComments) {
this.currentPosition++;
}
@@ -1844,8 +1984,6 @@
} else {
pushLineSeparator();
}
- } else {
- this.currentLine = null;
}
}
isUnicode = false;
@@ -1876,8 +2014,6 @@
} else {
pushLineSeparator();
}
- } else {
- this.currentLine = null;
}
}
switch (this.currentCharacter) {
@@ -1920,14 +2056,15 @@
default :
try {
char c = this.currentCharacter;
- if (c < MAX_OBVIOUS) {
- switch (ObviousIdentCharNatures[c]) {
- case C_LETTER :
- scanIdentifierOrKeyword();
- break NextToken;
- case C_DIGIT :
- scanNumber(false);
- break NextToken;
+ if (c < ScannerHelper.MAX_OBVIOUS) {
+ if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_IDENT_START) != 0) {
+ scanIdentifierOrKeyword();
+ break NextToken;
+ } else if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_DIGIT) != 0) {
+ scanNumber(false);
+ break NextToken;
+ } else {
+ break NextToken;
}
}
boolean isJavaIdStart;
@@ -1939,26 +2076,23 @@
char low = (char) getNextChar();
if (low < LOW_SURROGATE_MIN_VALUE || low > LOW_SURROGATE_MAX_VALUE) {
// illegal low surrogate
- throw new InvalidInputException(INVALID_LOW_SURROGATE);
+ break NextToken;
}
isJavaIdStart = ScannerHelper.isJavaIdentifierStart(c, low);
- }
- else if (c >= LOW_SURROGATE_MIN_VALUE && c <= LOW_SURROGATE_MAX_VALUE) {
- if (this.complianceLevel < ClassFileConstants.JDK1_5) {
- throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
- }
- throw new InvalidInputException(INVALID_HIGH_SURROGATE);
+ } else if (c >= LOW_SURROGATE_MIN_VALUE && c <= LOW_SURROGATE_MAX_VALUE) {
+ break NextToken;
} else {
+ // optimized case already checked
isJavaIdStart = Character.isJavaIdentifierStart(c);
}
if (isJavaIdStart) {
scanIdentifierOrKeyword();
break NextToken;
}
- if (isDigit(this.currentCharacter)) {
- scanNumber(false);
- break NextToken;
- }
+// if (ScannerHelper.isDigit(this.currentCharacter)) {
+// scanNumber(false);
+// break NextToken;
+// }
} catch (InvalidInputException ex) {
// ignore
}
@@ -1979,14 +2113,9 @@
//On false, the currentCharacter is filled up with a potential
//correct char
- try {
- this.wasAcr = false;
- getNextUnicodeChar();
- return CharOperation.isWhitespace(this.currentCharacter);
- } catch (IndexOutOfBoundsException e){
- this.currentPosition--;
- throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
- }
+ this.wasAcr = false;
+ getNextUnicodeChar();
+ return CharOperation.isWhitespace(this.currentCharacter);
}
final char[] optimizedCurrentTokenSource1() {
@@ -2225,64 +2354,120 @@
return table[newEntry6 = max] = r; //(r = new char[] {c0, c1, c2, c3, c4, c5});
}
-protected void parseTags(NLSLine line) {
- String s = new String(getCurrentTokenSource());
- int pos = s.indexOf(TAG_PREFIX);
- int lineLength = line.size();
- while (pos != -1) {
- int start = pos + TAG_PREFIX_LENGTH;
- int end = s.indexOf(TAG_POSTFIX, start);
- if (end != -1) {
- String index = s.substring(start, end);
- int i = 0;
- try {
- i = Integer.parseInt(index) - 1; // Tags are one based not zero based.
- } catch (NumberFormatException e) {
- i = -1; // we don't want to consider this as a valid NLS tag
- }
- if (line.exists(i)) {
- line.set(i, null);
- }
- }
- pos = s.indexOf(TAG_PREFIX, start);
+private void parseTags() {
+ int position = 0;
+ final int currentStartPosition = this.startPosition;
+ final int currentLinePtr = this.linePtr;
+ if (currentLinePtr >= 0) {
+ position = this.lineEnds[currentLinePtr] + 1;
}
-
- this.nonNLSStrings = new StringLiteral[lineLength];
- int nonNLSCounter = 0;
- for (Iterator iterator = line.iterator(); iterator.hasNext(); ) {
- StringLiteral literal = (StringLiteral) iterator.next();
- if (literal != null) {
- this.nonNLSStrings[nonNLSCounter++] = literal;
- }
+ while (ScannerHelper.isWhitespace(this.source[position])) {
+ position++;
}
- if (nonNLSCounter == 0) {
- this.nonNLSStrings = null;
- this.currentLine = null;
+ if (currentStartPosition == position) {
+ // the whole line is commented out
return;
- }
- this.wasNonExternalizedStringLiteral = true;
- if (nonNLSCounter != lineLength) {
- System.arraycopy(this.nonNLSStrings, 0, (this.nonNLSStrings = new StringLiteral[nonNLSCounter]), 0, nonNLSCounter);
}
- this.currentLine = null;
+ char[] s = null;
+ int sourceEnd = this.currentPosition;
+ int sourceStart = currentStartPosition;
+ int sourceDelta = 0;
+ if (this.withoutUnicodePtr != 0) {
+ // 0 is used as a fast test flag so the real first char is in position 1
+ System.arraycopy(
+ this.withoutUnicodeBuffer,
+ 1,
+ s = new char[this.withoutUnicodePtr],
+ 0,
+ this.withoutUnicodePtr);
+ sourceEnd = this.withoutUnicodePtr;
+ sourceStart = 1;
+ sourceDelta = currentStartPosition;
+ } else {
+ s = this.source;
+ }
+ int pos = CharOperation.indexOf(TAG_PREFIX, s, true, sourceStart, sourceEnd);
+ if (pos != -1) {
+ if (this.nlsTags == null) {
+ this.nlsTags = new NLSTag[10];
+ this.nlsTagsPtr = 0;
+ }
+ while (pos != -1) {
+ int start = pos + TAG_PREFIX_LENGTH;
+ int end = CharOperation.indexOf(TAG_POSTFIX, s, start, sourceEnd);
+ if (end != -1) {
+ NLSTag currentTag = null;
+ final int currentLine = currentLinePtr + 1;
+ try {
+ currentTag = new NLSTag(pos + sourceDelta, end + sourceDelta, currentLine, extractInt(s, start, end));
+ } catch (NumberFormatException e) {
+ currentTag = new NLSTag(pos + sourceDelta, end + sourceDelta, currentLine, -1);
+ }
+ if (this.nlsTagsPtr == this.nlsTags.length) {
+ // resize
+ System.arraycopy(this.nlsTags, 0, (this.nlsTags = new NLSTag[this.nlsTagsPtr + 10]), 0, this.nlsTagsPtr);
+ }
+ this.nlsTags[this.nlsTagsPtr++] = currentTag;
+ } else {
+ end = start;
+ }
+ pos = CharOperation.indexOf(TAG_PREFIX, s, true, end, sourceEnd);
+ }
+ }
}
-
+private int extractInt(char[] array, int start, int end) {
+ int value = 0;
+ for (int i = start; i < end; i++) {
+ final char currentChar = array[i];
+ int digit = 0;
+ switch(currentChar) {
+ case '0' :
+ digit = 0;
+ break;
+ case '1' :
+ digit = 1;
+ break;
+ case '2' :
+ digit = 2;
+ break;
+ case '3' :
+ digit = 3;
+ break;
+ case '4' :
+ digit = 4;
+ break;
+ case '5' :
+ digit = 5;
+ break;
+ case '6' :
+ digit = 6;
+ break;
+ case '7' :
+ digit = 7;
+ break;
+ case '8' :
+ digit = 8;
+ break;
+ case '9' :
+ digit = 9;
+ break;
+ default :
+ throw new NumberFormatException();
+ }
+ value *= 10;
+ if (digit < 0) throw new NumberFormatException();
+ value += digit;
+ }
+ return value;
+}
public final void pushLineSeparator() {
//see comment on isLineDelimiter(char) for the use of '\n' and '\r'
final int INCREMENT = 250;
-
- if (this.checkNonExternalizedStringLiterals) {
- // reinitialize the current line for non externalize strings purpose
- this.currentLine = null;
- }
//currentCharacter is at position currentPosition-1
-
// cr 000D
if (this.currentCharacter == '\r') {
int separatorPos = this.currentPosition - 1;
- //TODO (olivier) david - why the following line was "if ((this.linePtr > 0) && (this.lineEnds[this.linePtr] >= separatorPos)) return;" ?
if ((this.linePtr >= 0) && (this.lineEnds[this.linePtr] >= separatorPos)) return;
- //System.out.println("CR-" + separatorPos);
int length = this.lineEnds.length;
if (++this.linePtr >= length)
System.arraycopy(this.lineEnds, 0, this.lineEnds = new int[length + INCREMENT], 0, length);
@@ -2308,9 +2493,7 @@
this.lineEnds[this.linePtr] = this.currentPosition - 1;
} else {
int separatorPos = this.currentPosition - 1;
- //TODO (olivier) david - why the following line was "if ((this.linePtr > 0) && (this.lineEnds[this.linePtr] >= separatorPos)) return;" ?
if ((this.linePtr >= 0) && (this.lineEnds[this.linePtr] >= separatorPos)) return;
- // System.out.println("LF-" + separatorPos);
int length = this.lineEnds.length;
if (++this.linePtr >= length)
System.arraycopy(this.lineEnds, 0, this.lineEnds = new int[length + INCREMENT], 0, length);
@@ -2321,11 +2504,6 @@
}
}
public final void pushUnicodeLineSeparator() {
- if (this.checkNonExternalizedStringLiterals) {
- // reinitialize the current line for non externalize strings purpose
- this.currentLine = null;
- }
-
// cr 000D
if (this.currentCharacter == '\r') {
if (this.source[this.currentPosition] == '\n') {
@@ -2420,18 +2598,18 @@
// OctalDigit OctalDigit
// ZeroToThree OctalDigit OctalDigit
- int number = Character.getNumericValue(this.currentCharacter);
+ int number = ScannerHelper.getNumericValue(this.currentCharacter);
if (number >= 0 && number <= 7) {
boolean zeroToThreeNot = number > 3;
- if (isDigit(this.currentCharacter = this.source[this.currentPosition++])) {
- int digit = Character.getNumericValue(this.currentCharacter);
+ if (ScannerHelper.isDigit(this.currentCharacter = this.source[this.currentPosition++])) {
+ int digit = ScannerHelper.getNumericValue(this.currentCharacter);
if (digit >= 0 && digit <= 7) {
number = (number * 8) + digit;
- if (isDigit(this.currentCharacter = this.source[this.currentPosition++])) {
+ if (ScannerHelper.isDigit(this.currentCharacter = this.source[this.currentPosition++])) {
if (zeroToThreeNot) {// has read \NotZeroToThree OctalDigit Digit --> ignore last character
this.currentPosition--;
} else {
- digit = Character.getNumericValue(this.currentCharacter);
+ digit = ScannerHelper.getNumericValue(this.currentCharacter);
if (digit >= 0 && digit <= 7){ // has read \ZeroToThree OctalDigit OctalDigit
number = (number * 8) + digit;
} else {// has read \ZeroToThree OctalDigit NonOctalDigit --> ignore last character
@@ -2454,6 +2632,68 @@
throw new InvalidInputException(INVALID_ESCAPE);
}
}
+public int scanIdentifierOrKeywordWithBoundCheck() {
+ //test keywords
+
+ //first dispatch on the first char.
+ //then the length. If there are several
+ //keywors with the same length AND the same first char, then do another
+ //dispatch on the second char
+ this.useAssertAsAnIndentifier = false;
+ this.useEnumAsAnIndentifier = false;
+
+ char[] src = this.source;
+ identLoop: {
+ int pos;
+ int srcLength = this.eofPosition;
+ while (true) {
+ if ((pos = this.currentPosition) >= srcLength) // handle the obvious case upfront
+ break identLoop;
+ char c = src[pos];
+ if (c < ScannerHelper.MAX_OBVIOUS) {
+ if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] &
+ (ScannerHelper.C_UPPER_LETTER | ScannerHelper.C_LOWER_LETTER | ScannerHelper.C_IDENT_PART | ScannerHelper.C_DIGIT)) != 0) {
+ if (this.withoutUnicodePtr != 0) {
+ this.currentCharacter = c;
+ unicodeStore();
+ }
+ this.currentPosition++;
+ } else if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & (ScannerHelper.C_SEPARATOR | ScannerHelper.C_JLS_SPACE)) != 0) {
+ this.currentCharacter = c;
+ break identLoop;
+ } else {
+ //System.out.println("slow<=128: "+ c);
+ while (getNextCharAsJavaIdentifierPartWithBoundCheck()){/*empty*/}
+ break identLoop;
+ }
+ } else {
+ //System.out.println("slow>>128: "+ c);
+ while (getNextCharAsJavaIdentifierPartWithBoundCheck()){/*empty*/}
+ break identLoop;
+ }
+ }
+ }
+
+ int index, length;
+ char[] data;
+ if (this.withoutUnicodePtr == 0) {
+ //quick test on length == 1 but not on length > 12 while most identifier
+ //have a length which is <= 12...but there are lots of identifier with
+ //only one char....
+ if ((length = this.currentPosition - this.startPosition) == 1) {
+ return TokenNameIdentifier;
+ }
+ data = this.source;
+ index = this.startPosition;
+ } else {
+ if ((length = this.withoutUnicodePtr) == 1)
+ return TokenNameIdentifier;
+ data = this.withoutUnicodeBuffer;
+ index = 1;
+ }
+
+ return internalScanIdentifierOrKeyword(index, length, data);
+}
public int scanIdentifierOrKeyword() {
//test keywords
@@ -2466,31 +2706,27 @@
char[] src = this.source;
identLoop: {
- int pos, srcLength = this.source.length;
+ int pos;
+ int srcLength = this.eofPosition;
while (true) {
if ((pos = this.currentPosition) >= srcLength) // handle the obvious case upfront
break identLoop;
char c = src[pos];
- if (c < MAX_OBVIOUS) {
- switch (ObviousIdentCharNatures[c]) {
- case C_LETTER :
- case C_DIGIT :
+ if (c < ScannerHelper.MAX_OBVIOUS) {
+ if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] &
+ (ScannerHelper.C_UPPER_LETTER | ScannerHelper.C_LOWER_LETTER | ScannerHelper.C_IDENT_PART | ScannerHelper.C_DIGIT)) != 0) {
if (this.withoutUnicodePtr != 0) {
this.currentCharacter = c;
unicodeStore();
}
this.currentPosition++;
- break;
-
- case C_SEPARATOR :
- case C_SPACE :
+ } else if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & (ScannerHelper.C_SEPARATOR | ScannerHelper.C_JLS_SPACE)) != 0) {
this.currentCharacter = c;
- break identLoop;
-
- default:
- //System.out.println("slow<=128: "+ c);
- while (getNextCharAsJavaIdentifierPart()){/*empty*/}
- break identLoop;
+ break identLoop;
+ } else {
+ //System.out.println("slow<=128: "+ c);
+ while (getNextCharAsJavaIdentifierPart()){/*empty*/}
+ break identLoop;
}
} else {
//System.out.println("slow>>128: "+ c);
@@ -2502,15 +2738,13 @@
int index, length;
char[] data;
- if (this.withoutUnicodePtr == 0)
-
+ if (this.withoutUnicodePtr == 0) {
//quick test on length == 1 but not on length > 12 while most identifier
//have a length which is <= 12...but there are lots of identifier with
//only one char....
-
- {
- if ((length = this.currentPosition - this.startPosition) == 1)
+ if ((length = this.currentPosition - this.startPosition) == 1) {
return TokenNameIdentifier;
+ }
data = this.source;
index = this.startPosition;
} else {
@@ -2520,9 +2754,11 @@
index = 1;
}
+ return internalScanIdentifierOrKeyword(index, length, data);
+}
+private int internalScanIdentifierOrKeyword(int index, int length, char[] data) {
switch (data[index]) {
-
case 'a' :
switch(length) {
case 8: //abstract
@@ -3130,7 +3366,7 @@
}
}
}
- if (!isDigit(this.currentCharacter)) {
+ if (!ScannerHelper.isDigit(this.currentCharacter)) {
throw new InvalidInputException(INVALID_HEXA);
}
while (getNextCharAsDigit()){/*empty*/}
@@ -3175,7 +3411,7 @@
}
}
}
- if (!isDigit(this.currentCharacter))
+ if (!ScannerHelper.isDigit(this.currentCharacter))
throw new InvalidInputException(INVALID_FLOAT);
while (getNextCharAsDigit()){/*empty*/}
if (getNextChar('f', 'F') >= 0)
@@ -3238,7 +3474,7 @@
}
}
}
- if (!isDigit(this.currentCharacter))
+ if (!ScannerHelper.isDigit(this.currentCharacter))
throw new InvalidInputException(INVALID_FLOAT);
while (getNextCharAsDigit()){/*empty*/}
}
@@ -3290,7 +3526,7 @@
}
}
}
- if (!isDigit(this.currentCharacter))
+ if (!ScannerHelper.isDigit(this.currentCharacter))
throw new InvalidInputException(INVALID_FLOAT);
while (getNextCharAsDigit()){/*empty*/}
}
@@ -3304,34 +3540,14 @@
return floating ? TokenNameDoubleLiteral : TokenNameIntegerLiteral;
}
+
/**
* Search the line number corresponding to a specific position
* @param position int
* @return int
*/
public final int getLineNumber(int position) {
-
- if (this.lineEnds == null)
- return 1;
- int length = this.linePtr+1;
- if (length == 0)
- return 1;
- int g = 0, d = length - 1;
- int m = 0;
- while (g <= d) {
- m = (g + d) /2;
- if (position < this.lineEnds[m]) {
- d = m-1;
- } else if (position > this.lineEnds[m]) {
- g = m+1;
- } else {
- return m + 1;
- }
- }
- if (position < this.lineEnds[m]) {
- return m+1;
- }
- return m+2;
+ return Util.getLineNumber(position, this.lineEnds, 0, this.linePtr);
}
public final void setSource(char[] sourceString){
//the source-buffer is set to sourceString
@@ -3375,9 +3591,9 @@
setSource(null, compilationResult);
}
public String toString() {
- if (this.startPosition == this.source.length)
+ if (this.startPosition == this.eofPosition)
return "EOF\n\n" + new String(this.source); //$NON-NLS-1$
- if (this.currentPosition > this.source.length)
+ if (this.currentPosition > this.eofPosition)
return "behind the EOF\n\n" + new String(this.source); //$NON-NLS-1$
char front[] = new char[this.startPosition];
@@ -3397,13 +3613,13 @@
middle = CharOperation.NO_CHAR;
}
- char end[] = new char[this.source.length - (this.currentPosition - 1)];
+ char end[] = new char[this.eofPosition - (this.currentPosition - 1)];
System.arraycopy(
this.source,
(this.currentPosition - 1) + 1,
end,
0,
- this.source.length - (this.currentPosition - 1) - 1);
+ this.eofPosition - (this.currentPosition - 1) - 1);
return new String(front)
+ "\n===============================\nStarts here -->" //$NON-NLS-1$
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/RecordedParsingInformation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/RecordedParsingInformation.java
index d490044..9cd31e7 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/RecordedParsingInformation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/RecordedParsingInformation.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2002, 2004 IBM Corporation and others.
+ * Copyright (c) 2002, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,7 +10,7 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core.util;
-import org.eclipse.jdt.core.compiler.IProblem;
+import org.eclipse.jdt.core.compiler.CategorizedProblem;
import org.eclipse.jdt.internal.compiler.CompilationResult;
/**
@@ -18,12 +18,12 @@
* line ends or problems.
*/
public class RecordedParsingInformation {
- public IProblem[] problems;
+ public CategorizedProblem[] problems;
public int problemsCount;
public int[] lineEnds;
public int[][] commentPositions;
- public RecordedParsingInformation(IProblem[] problems, int[] lineEnds, int[][] commentPositions) {
+ public RecordedParsingInformation(CategorizedProblem[] problems, int[] lineEnds, int[][] commentPositions) {
this.problems = problems;
this.lineEnds = lineEnds;
this.commentPositions = commentPositions;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ReferenceInfoAdapter.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ReferenceInfoAdapter.java
index b0c5a6b..fba1212 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ReferenceInfoAdapter.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ReferenceInfoAdapter.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ResourceCompilationUnit.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ResourceCompilationUnit.java
new file mode 100755
index 0000000..0e55fff
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ResourceCompilationUnit.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.util;
+
+import java.net.URI;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.batch.CompilationUnit;
+
+/**
+ * An ICompilationUnit that retrieves its contents using an IFile
+ */
+public class ResourceCompilationUnit extends CompilationUnit {
+
+ private IFile file;
+
+ public ResourceCompilationUnit(IFile file, URI location) {
+ super(null/*no contents*/, location == null ? file.getFullPath().toString() : location.getPath(), null/*encoding is used only when retrieving the contents*/);
+ this.file = file;
+ }
+
+ public char[] getContents() {
+ if (this.contents != null)
+ return this.contents; // answer the cached source
+
+ // otherwise retrieve it
+ try {
+ return Util.getResourceContentsAsCharArray(this.file);
+ } catch (CoreException e) {
+ return CharOperation.NO_CHAR;
+ }
+ }
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/RuntimeInvisibleAnnotationsAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/RuntimeInvisibleAnnotationsAttribute.java
index e0bb58f..2598546 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/RuntimeInvisibleAnnotationsAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/RuntimeInvisibleAnnotationsAttribute.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004 IBM Corporation and others.
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/RuntimeInvisibleParameterAnnotationsAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/RuntimeInvisibleParameterAnnotationsAttribute.java
index 91cd147..099a032 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/RuntimeInvisibleParameterAnnotationsAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/RuntimeInvisibleParameterAnnotationsAttribute.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004 IBM Corporation and others.
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/RuntimeVisibleAnnotationsAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/RuntimeVisibleAnnotationsAttribute.java
index 5360535..62af5b1 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/RuntimeVisibleAnnotationsAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/RuntimeVisibleAnnotationsAttribute.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004 IBM Corporation and others.
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/RuntimeVisibleParameterAnnotationsAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/RuntimeVisibleParameterAnnotationsAttribute.java
index 9e4d5ab..6f3e8d1 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/RuntimeVisibleParameterAnnotationsAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/RuntimeVisibleParameterAnnotationsAttribute.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004 IBM Corporation and others.
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SignatureAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SignatureAttribute.java
index fa7612e..e6e65b1 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SignatureAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SignatureAttribute.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SimpleDocument.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SimpleDocument.java
index 3362c19..7fb4386 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SimpleDocument.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SimpleDocument.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SimpleSet.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SimpleSet.java
deleted file mode 100644
index fe7c065..0000000
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SimpleSet.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.jdt.internal.core.util;
-
-/**
- * A simple lookup table is a non-synchronized Hashtable, whose keys
- * and values are Objects. It also uses linear probing to resolve collisions
- * rather than a linked list of hash table entries.
- */
-public final class SimpleSet implements Cloneable {
-
-// to avoid using Enumerations, walk the individual values skipping nulls
-public Object[] values;
-public int elementSize; // number of elements in the table
-public int threshold;
-
-public SimpleSet() {
- this(13);
-}
-
-public SimpleSet(int size) {
- if (size < 3) size = 3;
- this.elementSize = 0;
- this.threshold = size + 1; // size is the expected number of elements
- this.values = new Object[2 * size + 1];
-}
-
-public Object add(Object object) {
- int length = values.length;
- int index = (object.hashCode() & 0x7FFFFFFF) % length;
- Object current;
- while ((current = values[index]) != null) {
- if (current.equals(object)) return values[index] = object;
- if (++index == length) index = 0;
- }
- values[index] = object;
-
- // assumes the threshold is never equal to the size of the table
- if (++elementSize > threshold) rehash();
- return object;
-}
-
-public void clear() {
- for (int i = this.values.length; --i >= 0;)
- this.values[i] = null;
- this.elementSize = 0;
-}
-
-public Object clone() throws CloneNotSupportedException {
- SimpleSet result = (SimpleSet) super.clone();
- result.elementSize = this.elementSize;
- result.threshold = this.threshold;
-
- int length = this.values.length;
- result.values = new Object[length];
- System.arraycopy(this.values, 0, result.values, 0, length);
- return result;
-}
-
-public boolean includes(Object object) {
- int length = values.length;
- int index = (object.hashCode() & 0x7FFFFFFF) % length;
- Object current;
- while ((current = values[index]) != null) {
- if (current.equals(object)) return true;
- if (++index == length) index = 0;
- }
- return false;
-}
-
-public Object remove(Object object) {
- int length = values.length;
- int index = (object.hashCode() & 0x7FFFFFFF) % length;
- Object current;
- while ((current = values[index]) != null) {
- if (current.equals(object)) {
- elementSize--;
- Object oldValue = values[index];
- values[index] = null;
- if (values[index + 1 == length ? 0 : index + 1] != null)
- rehash(); // only needed if a possible collision existed
- return oldValue;
- }
- if (++index == length) index = 0;
- }
- return null;
-}
-
-private void rehash() {
- SimpleSet newSet = new SimpleSet(elementSize * 2); // double the number of expected elements
- Object current;
- for (int i = values.length; --i >= 0;)
- if ((current = values[i]) != null)
- newSet.add(current);
-
- this.values = newSet.values;
- this.elementSize = newSet.elementSize;
- this.threshold = newSet.threshold;
-}
-
-public String toString() {
- String s = ""; //$NON-NLS-1$
- Object object;
- for (int i = 0, l = values.length; i < l; i++)
- if ((object = values[i]) != null)
- s += object.toString() + "\n"; //$NON-NLS-1$
- return s;
-}
-}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SimpleWordSet.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SimpleWordSet.java
index 306c5cc..a9e6197 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SimpleWordSet.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SimpleWordSet.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SourceFileAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SourceFileAttribute.java
index b0cadcd..fcba33d 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SourceFileAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SourceFileAttribute.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/StackMapAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/StackMapAttribute.java
new file mode 100755
index 0000000..5c32a64
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/StackMapAttribute.java
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.util;
+
+import org.eclipse.jdt.core.util.ClassFormatException;
+import org.eclipse.jdt.core.util.IConstantPool;
+import org.eclipse.jdt.core.util.IStackMapFrame;
+import org.eclipse.jdt.core.util.IStackMapAttribute;
+/**
+ * Default implementation of IStackMapAttribute.
+ * @see IStackMapAttribute
+ */
+public class StackMapAttribute
+ extends ClassFileAttribute
+ implements IStackMapAttribute {
+
+ private static final IStackMapFrame[] NO_FRAMES = new IStackMapFrame[0];
+ private static final byte[] NO_ENTRIES = new byte[0];
+
+ private int numberOfEntries;
+ private IStackMapFrame[] frames;
+
+ private byte[] bytes;
+
+ /**
+ * Constructor for LineNumberAttribute.
+ * @param classFileBytes
+ * @param constantPool
+ * @param offset
+ * @throws ClassFormatException
+ */
+ public StackMapAttribute(
+ byte[] classFileBytes,
+ IConstantPool constantPool,
+ int offset)
+ throws ClassFormatException {
+ super(classFileBytes, constantPool, offset);
+
+ final int length = u2At(classFileBytes, 6, offset);
+ this.numberOfEntries = length;
+ if (length != 0) {
+ int readOffset = 8;
+ this.frames = new IStackMapFrame[length];
+ for (int i = 0; i < length; i++) {
+ DefaultStackMapFrame frame = new DefaultStackMapFrame(classFileBytes, constantPool, offset + readOffset);
+ this.frames[i] = frame;
+ readOffset += frame.sizeInBytes();
+ }
+ } else {
+ this.frames = NO_FRAMES;
+ }
+ final int byteLength = (int) u4At(classFileBytes, 2, offset);
+
+ if (length != 0) {
+ System.arraycopy(classFileBytes, offset + 6, this.bytes = new byte[byteLength], 0, byteLength);
+ } else {
+ this.bytes = NO_ENTRIES;
+ }
+ }
+
+ public int getNumberOfEntries() {
+ return this.numberOfEntries;
+ }
+
+ public IStackMapFrame[] getStackMapFrame() {
+ return this.frames;
+ }
+
+ /**
+ */
+ public byte[] getBytes() {
+ return this.bytes;
+ }
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/StackMapFrame.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/StackMapFrame.java
new file mode 100755
index 0000000..3e6d060
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/StackMapFrame.java
@@ -0,0 +1,170 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.util;
+
+import org.eclipse.jdt.core.util.ClassFormatException;
+import org.eclipse.jdt.core.util.IConstantPool;
+import org.eclipse.jdt.core.util.IStackMapFrame;
+import org.eclipse.jdt.core.util.IVerificationTypeInfo;
+
+/**
+ * Default implementation of IStackMapFrame
+ */
+public class StackMapFrame extends ClassFileStruct implements IStackMapFrame {
+ private static final IVerificationTypeInfo[] EMPTY_LOCALS_OR_STACK_ITEMS = new IVerificationTypeInfo[0];
+
+ private int readOffset;
+ private int frameType;
+ private int numberOfLocals;
+ private int numberOfStackItems;
+ private IVerificationTypeInfo[] locals;
+ private IVerificationTypeInfo[] stackItems;
+ private int offsetDelta;
+
+ /**
+ * Constructor for StackMapFrame.
+ *
+ * @param classFileBytes
+ * @param constantPool
+ * @param offset
+ * @throws ClassFormatException
+ */
+ public StackMapFrame(
+ byte[] classFileBytes,
+ IConstantPool constantPool,
+ int offset) throws ClassFormatException {
+
+ final int type = u1At(classFileBytes, 0, offset);
+ this.frameType = type;
+ switch(type) {
+ case 247 : // SAME_LOCALS_1_STACK_ITEM_EXTENDED
+ this.offsetDelta = u2At(classFileBytes, 1, offset);
+ this.numberOfStackItems = 1;
+ this.stackItems = new VerificationInfo[1];
+ this.readOffset = 3;
+ VerificationInfo info = new VerificationInfo(classFileBytes, constantPool, offset + this.readOffset);
+ this.stackItems[0] = info;
+ this.readOffset += info.sizeInBytes();
+ this.locals = EMPTY_LOCALS_OR_STACK_ITEMS;
+ this.numberOfLocals = 0;
+ break;
+ case 248 :
+ case 249 :
+ case 250:
+ // CHOP
+ this.offsetDelta = u2At(classFileBytes, 1, offset);
+ this.numberOfStackItems = 0;
+ this.stackItems = EMPTY_LOCALS_OR_STACK_ITEMS;
+ this.readOffset = 3;
+ this.locals = EMPTY_LOCALS_OR_STACK_ITEMS;
+ this.numberOfLocals = 0;
+ break;
+ case 251 :
+ // SAME_FRAME_EXTENDED
+ this.offsetDelta = u2At(classFileBytes, 1, offset);
+ this.numberOfStackItems = 0;
+ this.stackItems = EMPTY_LOCALS_OR_STACK_ITEMS;
+ this.readOffset = 3;
+ this.locals = EMPTY_LOCALS_OR_STACK_ITEMS;
+ this.numberOfLocals = 0;
+ break;
+ case 252 :
+ case 253 :
+ case 254 :
+ // APPEND
+ this.offsetDelta = u2At(classFileBytes, 1, offset);
+ this.numberOfStackItems = 0;
+ this.stackItems = EMPTY_LOCALS_OR_STACK_ITEMS;
+ this.readOffset = 3;
+ int diffLocals = type - 251;
+ this.numberOfLocals = diffLocals;
+ this.locals = new IVerificationTypeInfo[diffLocals];
+ for (int i = 0; i < diffLocals; i++) {
+ VerificationInfo verificationInfo = new VerificationInfo(classFileBytes, constantPool, offset + readOffset);
+ this.locals[i] = verificationInfo;
+ this.readOffset += verificationInfo.sizeInBytes();
+ }
+ break;
+ case 255 :
+ // FULL_FRAME
+ this.offsetDelta = u2At(classFileBytes, 1, offset);
+ int tempLocals = u2At(classFileBytes, 3, offset);
+ this.numberOfLocals = tempLocals;
+ this.readOffset = 5;
+ if (tempLocals != 0) {
+ this.locals = new IVerificationTypeInfo[tempLocals];
+ for (int i = 0; i < tempLocals; i++) {
+ VerificationInfo verificationInfo = new VerificationInfo(classFileBytes, constantPool, offset + this.readOffset);
+ this.locals[i] = verificationInfo;
+ this.readOffset += verificationInfo.sizeInBytes();
+ }
+ } else {
+ this.locals = EMPTY_LOCALS_OR_STACK_ITEMS;
+ }
+ int tempStackItems = u2At(classFileBytes, readOffset, offset);
+ this.readOffset += 2;
+ this.numberOfStackItems = tempStackItems;
+ if (tempStackItems != 0) {
+ this.stackItems = new IVerificationTypeInfo[tempStackItems];
+ for (int i = 0; i < tempStackItems; i++) {
+ VerificationInfo verificationInfo = new VerificationInfo(classFileBytes, constantPool, offset + this.readOffset);
+ this.stackItems[i] = verificationInfo;
+ this.readOffset += verificationInfo.sizeInBytes();
+ }
+ } else {
+ this.stackItems = EMPTY_LOCALS_OR_STACK_ITEMS;
+ }
+ break;
+ default:
+ if (type <= 63) {
+ // SAME_FRAME
+ this.offsetDelta = type;
+ this.numberOfStackItems = 0;
+ this.stackItems = EMPTY_LOCALS_OR_STACK_ITEMS;
+ this.locals = EMPTY_LOCALS_OR_STACK_ITEMS;
+ this.numberOfLocals = 0;
+ this.readOffset = 1;
+ } else if (type <= 127) {
+ // SAME_LOCALS_1_STACK_ITEM
+ this.offsetDelta = type - 64;
+ this.numberOfStackItems = 1;
+ this.stackItems = new VerificationInfo[1];
+ this.readOffset = 1;
+ info = new VerificationInfo(classFileBytes, constantPool, offset + this.readOffset);
+ this.stackItems[0] = info;
+ this.readOffset += info.sizeInBytes();
+ this.locals = EMPTY_LOCALS_OR_STACK_ITEMS;
+ this.numberOfLocals = 0;
+ }
+ }
+ }
+ int sizeInBytes() {
+ return this.readOffset;
+ }
+ public int getFrameType() {
+ return this.frameType;
+ }
+ public IVerificationTypeInfo[] getLocals() {
+ return this.locals;
+ }
+ public int getNumberOfLocals() {
+ return this.numberOfLocals;
+ }
+ public int getNumberOfStackItems() {
+ return this.numberOfStackItems;
+ }
+ public int getOffsetDelta() {
+ return this.offsetDelta;
+ }
+ public IVerificationTypeInfo[] getStackItems() {
+ return this.stackItems;
+ }
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/StackMapTableAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/StackMapTableAttribute.java
new file mode 100755
index 0000000..a184f97
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/StackMapTableAttribute.java
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.util;
+
+import org.eclipse.jdt.core.util.ClassFormatException;
+import org.eclipse.jdt.core.util.IConstantPool;
+import org.eclipse.jdt.core.util.IStackMapFrame;
+import org.eclipse.jdt.core.util.IStackMapTableAttribute;
+/**
+ * Default implementation of IStackMapTableAttribute.
+ * @see IStackMapTableAttribute
+ */
+public class StackMapTableAttribute
+ extends ClassFileAttribute
+ implements IStackMapTableAttribute {
+
+ private static final IStackMapFrame[] NO_FRAMES = new IStackMapFrame[0];
+ private static final byte[] NO_ENTRIES = new byte[0];
+
+ private int numberOfEntries;
+ private IStackMapFrame[] frames;
+
+ private byte[] bytes;
+
+ /**
+ * Constructor for LineNumberAttribute.
+ * @param classFileBytes
+ * @param constantPool
+ * @param offset
+ * @throws ClassFormatException
+ */
+ public StackMapTableAttribute(
+ byte[] classFileBytes,
+ IConstantPool constantPool,
+ int offset)
+ throws ClassFormatException {
+ super(classFileBytes, constantPool, offset);
+
+ final int length = u2At(classFileBytes, 6, offset);
+ this.numberOfEntries = length;
+ if (length != 0) {
+ int readOffset = 8;
+ this.frames = new IStackMapFrame[length];
+ for (int i = 0; i < length; i++) {
+ StackMapFrame frame = new StackMapFrame(classFileBytes, constantPool, offset + readOffset);
+ this.frames[i] = frame;
+ readOffset += frame.sizeInBytes();
+ }
+ } else {
+ this.frames = NO_FRAMES;
+ }
+ final int byteLength = (int) u4At(classFileBytes, 2, offset);
+
+ if (length != 0) {
+ System.arraycopy(classFileBytes, offset + 6, this.bytes = new byte[byteLength], 0, byteLength);
+ } else {
+ this.bytes = NO_ENTRIES;
+ }
+ }
+
+ public int getNumberOfEntries() {
+ return this.numberOfEntries;
+ }
+
+ public IStackMapFrame[] getStackMapFrame() {
+ return this.frames;
+ }
+
+ /**
+ */
+ public byte[] getBytes() {
+ return this.bytes;
+ }
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ToStringSorter.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ToStringSorter.java
index c20a83b..1b711b8 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ToStringSorter.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ToStringSorter.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -32,7 +32,7 @@
private void quickSort(int left, int right) {
int originalLeft = left;
int originalRight = right;
- int midIndex = (left + right) / 2;
+ int midIndex = left + (right - left) / 2;
String midToString = this.sortedStrings[midIndex];
do {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Util.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Util.java
index 2bdd34f..6d80a22 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Util.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Util.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -11,10 +11,13 @@
package org.eclipse.jdt.internal.core.util;
import java.io.*;
+import java.net.URI;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
+import org.eclipse.core.filesystem.EFS;
+import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.content.IContentType;
@@ -40,8 +43,9 @@
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
+import org.eclipse.jdt.internal.compiler.parser.ScannerHelper;
import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
-import org.eclipse.jdt.internal.core.Assert;
+import org.eclipse.jdt.internal.core.JavaElement;
import org.eclipse.jdt.internal.core.JavaModelManager;
import org.eclipse.jdt.internal.core.PackageFragmentRoot;
import org.eclipse.jface.text.BadLocationException;
@@ -73,6 +77,7 @@
private static final String EMPTY_ARGUMENT = " "; //$NON-NLS-1$
private static char[][] JAVA_LIKE_EXTENSIONS;
+ public static boolean ENABLE_JAVA_LIKE_EXTENSIONS = true;
private static final char[] BOOLEAN = "boolean".toCharArray(); //$NON-NLS-1$
private static final char[] BYTE = "byte".toCharArray(); //$NON-NLS-1$
@@ -84,7 +89,7 @@
private static final char[] SHORT = "short".toCharArray(); //$NON-NLS-1$
private static final char[] VOID = "void".toCharArray(); //$NON-NLS-1$
private static final char[] INIT = "<init>".toCharArray(); //$NON-NLS-1$
-
+
private Util() {
// cannot be instantiated
}
@@ -434,7 +439,7 @@
// return false if any character of the end are
// not the same in lower case.
for(int i = 1 ; i <= endLength; i++){
- if(Character.toLowerCase(end.charAt(endLength - i)) != Character.toLowerCase(str.charAt(strLength - i)))
+ if(ScannerHelper.toLowerCase(end.charAt(endLength - i)) != ScannerHelper.toLowerCase(str.charAt(strLength - i)))
return false;
}
@@ -496,7 +501,9 @@
int len = a.length;
if (len != b.length) return false;
- for (int i = 0; i < len; ++i) {
+ // walk array from end to beginning as this optimizes package name cases
+ // where the first part is always the same (e.g. org.eclipse.jdt)
+ for (int i = len-1; i >= 0; i--) {
if (a[i] == null) {
if (b[i] != null) return false;
} else {
@@ -590,9 +597,11 @@
char[][] javaLikeExtensions = getJavaLikeExtensions();
suffixes: for (int i = 0, length = javaLikeExtensions.length; i < length; i++) {
char[] suffix = javaLikeExtensions[i];
- if (stringLength + suffix.length != fileNameLength) continue;
- for (int j = stringLength; j < fileNameLength; j++) {
- if (fileName.charAt(j) != suffix[j-stringLength])
+ int extensionStart = stringLength+1;
+ if (extensionStart + suffix.length != fileNameLength) continue;
+ if (fileName.charAt(stringLength) != '.') continue;
+ for (int j = extensionStart; j < fileNameLength; j++) {
+ if (fileName.charAt(j) != suffix[j-extensionStart])
continue suffixes;
}
return true;
@@ -733,37 +742,40 @@
}
return null;
}
+
/**
* Returns the registered Java like extensions.
*/
public static char[][] getJavaLikeExtensions() {
if (JAVA_LIKE_EXTENSIONS == null) {
// TODO (jerome) reenable once JDT UI supports other file extensions (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=71460)
- if (true)
- JAVA_LIKE_EXTENSIONS = new char[][] {SuffixConstants.SUFFIX_java};
+ if (!ENABLE_JAVA_LIKE_EXTENSIONS)
+ JAVA_LIKE_EXTENSIONS = new char[][] {SuffixConstants.EXTENSION_java.toCharArray()};
else {
- IContentType javaContentType = Platform.getContentTypeManager().getContentType(JavaModelManager.JAVA_SOURCE_CONTENT_TYPE);
- String[] fileExtensions = javaContentType == null ? null : javaContentType.getFileSpecs(IContentType.FILE_EXTENSION_SPEC);
- // note that file extensions contains "java" as it is defined in JDT Core's plugin.xml
- int length = fileExtensions == null ? 0 : fileExtensions.length;
- char[][] extensions = new char[length][];
- SimpleWordSet knownExtensions = new SimpleWordSet(length); // used to ensure no duplicate extensions
- extensions[0] = SuffixConstants.SUFFIX_java; // ensure that ".java" is first
- knownExtensions.add(SuffixConstants.SUFFIX_java);
- int index = 1;
- for (int i = 0; i < length; i++) {
- String fileExtension = fileExtensions[i];
- int extensionLength = fileExtension.length() + 1;
- char[] extension = new char[extensionLength];
- extension[0] = '.';
- fileExtension.getChars(0, extensionLength-1, extension, 1);
- if (!knownExtensions.includes(extension)) {
- extensions[index++] = extension;
- knownExtensions.add(extension);
+ IContentType javaContentType = Platform.getContentTypeManager().getContentType(JavaCore.JAVA_SOURCE_CONTENT_TYPE);
+ HashSet fileExtensions = new HashSet();
+ // content types derived from java content type should be included (https://bugs.eclipse.org/bugs/show_bug.cgi?id=121715)
+ IContentType[] contentTypes = Platform.getContentTypeManager().getAllContentTypes();
+ for (int i = 0, length = contentTypes.length; i < length; i++) {
+ if (contentTypes[i].isKindOf(javaContentType)) { // note that javaContentType.isKindOf(javaContentType) == true
+ String[] fileExtension = contentTypes[i].getFileSpecs(IContentType.FILE_EXTENSION_SPEC);
+ for (int j = 0, length2 = fileExtension.length; j < length2; j++) {
+ fileExtensions.add(fileExtension[j]);
+ }
}
}
- if (index != length)
- System.arraycopy(extensions, 0, extensions = new char[index][], 0, index);
+ int length = fileExtensions.size();
+ // note that file extensions contains "java" as it is defined in JDT Core's plugin.xml
+ char[][] extensions = new char[length][];
+ extensions[0] = SuffixConstants.EXTENSION_java.toCharArray(); // ensure that "java" is first
+ int index = 1;
+ Iterator iterator = fileExtensions.iterator();
+ while (iterator.hasNext()) {
+ String fileExtension = (String) iterator.next();
+ if (SuffixConstants.EXTENSION_java.equals(fileExtension))
+ continue;
+ extensions[index++] = fileExtension.toCharArray();
+ }
JAVA_LIKE_EXTENSIONS = extensions;
}
}
@@ -780,48 +792,45 @@
*/
public static long getJdkLevel(Object targetLibrary) {
try {
- ClassFileReader reader = null;
- if (targetLibrary instanceof IFolder) {
- IFile classFile = findFirstClassFile((IFolder) targetLibrary); // only internal classfolders are allowed
- if (classFile != null) {
- byte[] bytes = Util.getResourceContentsAsByteArray(classFile);
- IPath location = classFile.getLocation();
- reader = new ClassFileReader(bytes, location == null ? null : location.toString().toCharArray());
+ ClassFileReader reader = null;
+ if (targetLibrary instanceof IFolder) {
+ IFile classFile = findFirstClassFile((IFolder) targetLibrary); // only internal classfolders are allowed
+ if (classFile != null)
+ reader = Util.newClassFileReader(classFile);
+ } else {
+ // root is a jar file or a zip file
+ ZipFile jar = null;
+ try {
+ IPath path = null;
+ if (targetLibrary instanceof IResource) {
+ path = ((IResource)targetLibrary).getFullPath();
+ } else if (targetLibrary instanceof File){
+ File f = (File) targetLibrary;
+ if (!f.isDirectory()) {
+ path = new Path(((File)targetLibrary).getPath());
+ }
}
- } else {
- // root is a jar file or a zip file
- ZipFile jar = null;
- try {
- IPath path = null;
- if (targetLibrary instanceof IResource) {
- path = ((IResource)targetLibrary).getLocation();
- } else if (targetLibrary instanceof File){
- File f = (File) targetLibrary;
- if (!f.isDirectory()) {
- path = new Path(((File)targetLibrary).getPath());
+ if (path != null) {
+ jar = JavaModelManager.getJavaModelManager().getZipFile(path);
+ for (Enumeration e= jar.entries(); e.hasMoreElements();) {
+ ZipEntry member= (ZipEntry) e.nextElement();
+ String entryName= member.getName();
+ if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(entryName)) {
+ reader = ClassFileReader.read(jar, entryName);
+ break;
}
}
- if (path != null) {
- jar = JavaModelManager.getJavaModelManager().getZipFile(path);
- for (Enumeration e= jar.entries(); e.hasMoreElements();) {
- ZipEntry member= (ZipEntry) e.nextElement();
- String entryName= member.getName();
- if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(entryName)) {
- reader = ClassFileReader.read(jar, entryName);
- break;
- }
- }
- }
- } catch (CoreException e) {
- // ignore
- } finally {
- JavaModelManager.getJavaModelManager().closeZipFile(jar);
}
+ } catch (CoreException e) {
+ // ignore
+ } finally {
+ JavaModelManager.getJavaModelManager().closeZipFile(jar);
}
- if (reader != null) {
- return reader.getVersion();
- }
- } catch(JavaModelException e) {
+ }
+ if (reader != null) {
+ return reader.getVersion();
+ }
+ } catch (CoreException e) {
// ignore
} catch(ClassFormatException e) {
// ignore
@@ -832,10 +841,14 @@
}
/**
- * Returns the substring of the given file name, ending at the start of a Java like extension.
+ * Returns the substring of the given file name, ending at the start of a
+ * Java like extension. The entire file name is returned if it doesn't end
+ * with a Java like extension.
*/
public static String getNameWithoutJavaLikeExtension(String fileName) {
int index = indexOfJavaLikeExtension(fileName);
+ if (index == -1)
+ return fileName;
return fileName.substring(0, index);
}
@@ -849,7 +862,7 @@
String lineSeparator = null;
// line delimiter in given text
- if (text != null) {
+ if (text != null && text.length() != 0) {
lineSeparator = findLineSeparator(text.toCharArray());
if (lineSeparator != null)
return lineSeparator;
@@ -989,7 +1002,7 @@
public static byte[] getResourceContentsAsByteArray(IFile file) throws JavaModelException {
InputStream stream= null;
try {
- stream = new BufferedInputStream(file.getContents(true));
+ stream = file.getContents(true);
} catch (CoreException e) {
throw new JavaModelException(e);
}
@@ -1011,26 +1024,42 @@
*/
public static char[] getResourceContentsAsCharArray(IFile file) throws JavaModelException {
// Get encoding from file
- String encoding = null;
+ String encoding;
try {
encoding = file.getCharset();
- }
- catch(CoreException ce) {
+ } catch(CoreException ce) {
// do not use any encoding
+ encoding = null;
}
return getResourceContentsAsCharArray(file, encoding);
}
-
- public static char[] getResourceContentsAsCharArray(IFile file, String encoding) throws JavaModelException {
+
+ public static char[] getResourceContentsAsCharArray(IFile file, String encoding) throws JavaModelException {
+ // Get file length
+ // workaround https://bugs.eclipse.org/bugs/show_bug.cgi?id=130736 by using java.io.File if possible
+ IPath location = file.getLocation();
+ long length;
+ if (location == null) {
+ // non local file
+ try {
+ length = EFS.getStore(file.getLocationURI()).fetchInfo().getLength();
+ } catch (CoreException e) {
+ throw new JavaModelException(e);
+ }
+ } else {
+ // local file
+ length = location.toFile().length();
+ }
+
// Get resource contents
InputStream stream= null;
try {
- stream = new BufferedInputStream(file.getContents(true));
+ stream = file.getContents(true);
} catch (CoreException e) {
throw new JavaModelException(e, IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST);
}
try {
- return org.eclipse.jdt.internal.compiler.util.Util.getInputStreamAsCharArray(stream, -1, encoding);
+ return org.eclipse.jdt.internal.compiler.util.Util.getInputStreamAsCharArray(stream, (int) length, encoding);
} catch (IOException e) {
throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
} finally {
@@ -1041,7 +1070,8 @@
}
}
}
-/*
+
+ /*
* Returns the signature of the given type.
*/
public static String getSignature(Type type) {
@@ -1051,6 +1081,43 @@
}
/*
+ * Returns the source attachment property for this package fragment root's path
+ */
+ public static String getSourceAttachmentProperty(IPath path) throws JavaModelException {
+ Map rootPathToAttachments = JavaModelManager.getJavaModelManager().rootPathToAttachments;
+ String property = (String) rootPathToAttachments.get(path);
+ if (property == null) {
+ try {
+ property = ResourcesPlugin.getWorkspace().getRoot().getPersistentProperty(getSourceAttachmentPropertyName(path));
+ if (property == null) {
+ rootPathToAttachments.put(path, PackageFragmentRoot.NO_SOURCE_ATTACHMENT);
+ return null;
+ }
+ rootPathToAttachments.put(path, property);
+ return property;
+ } catch (CoreException e) {
+ throw new JavaModelException(e);
+ }
+ } else if (property.equals(PackageFragmentRoot.NO_SOURCE_ATTACHMENT)) {
+ return null;
+ } else
+ return property;
+ }
+
+ private static QualifiedName getSourceAttachmentPropertyName(IPath path) {
+ return new QualifiedName(JavaCore.PLUGIN_ID, "sourceattachment: " + path.toOSString()); //$NON-NLS-1$
+ }
+
+ public static void setSourceAttachmentProperty(IPath path, String property) {
+ JavaModelManager.getJavaModelManager().rootPathToAttachments.put(path, property);
+ try {
+ ResourcesPlugin.getWorkspace().getRoot().setPersistentProperty(getSourceAttachmentPropertyName(path), property);
+ } catch (CoreException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /*
* Returns the declaring type signature of the element represented by the given binding key.
* Returns the signature of the element if it is a type.
*
@@ -1148,6 +1215,7 @@
/*
* Returns the index of the Java like extension of the given file name
* or -1 if it doesn't end with a known Java like extension.
+ * Note this is the index of the '.' even if it is not considered part of the extension.
*/
public static int indexOfJavaLikeExtension(String fileName) {
int fileNameLength = fileName.length();
@@ -1156,12 +1224,14 @@
char[] extension = javaLikeExtensions[i];
int extensionLength = extension.length;
int extensionStart = fileNameLength - extensionLength;
- if (extensionStart < 0) continue;
+ int dotIndex = extensionStart - 1;
+ if (dotIndex < 0) continue;
+ if (fileName.charAt(dotIndex) != '.') continue;
for (int j = 0; j < extensionLength; j++) {
if (fileName.charAt(extensionStart + j) != extension[j])
continue extensions;
}
- return extensionStart;
+ return dotIndex;
}
return -1;
}
@@ -1188,6 +1258,36 @@
}
return -1;
}
+ /**
+ * Returns whether the local file system supports accessing and modifying
+ * the given attribute.
+ */
+ protected static boolean isAttributeSupported(int attribute) {
+ return (EFS.getLocalFileSystem().attributes() & attribute) != 0;
+ }
+
+ /**
+ * Returns whether the given resource is read-only or not.
+ * @param resource
+ * @return <code>true</code> if the resource is read-only, <code>false</code> if it is not or
+ * if the file system does not support the read-only attribute.
+ */
+ public static boolean isReadOnly(IResource resource) {
+ if (isReadOnlySupported()) {
+ ResourceAttributes resourceAttributes = resource.getResourceAttributes();
+ if (resourceAttributes == null) return false; // not supported on this platform for this resource
+ return resourceAttributes.isReadOnly();
+ }
+ return false;
+ }
+
+ /**
+ * Returns whether the local file system supports accessing and modifying
+ * the read only flag.
+ */
+ public static boolean isReadOnlySupported() {
+ return isAttributeSupported(EFS.ATTRIBUTE_READ_ONLY);
+ }
/*
* Returns whether the given java element is exluded from its root's classpath.
@@ -1209,7 +1309,9 @@
case IJavaElement.COMPILATION_UNIT:
root = (PackageFragmentRoot)element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
resource = element.getResource();
- if (resource != null && isExcluded(resource, root.fullInclusionPatternChars(), root.fullExclusionPatternChars()))
+ if (resource == null)
+ return false;
+ if (isExcluded(resource, root.fullInclusionPatternChars(), root.fullExclusionPatternChars()))
return true;
return isExcluded(element.getParent());
@@ -1238,9 +1340,11 @@
public final static boolean isExcluded(IResource resource, char[][] inclusionPatterns, char[][] exclusionPatterns) {
IPath path = resource.getFullPath();
// ensure that folders are only excluded if all of their children are excluded
- return isExcluded(path, inclusionPatterns, exclusionPatterns, resource.getType() == IResource.FOLDER);
+ int resourceType = resource.getType();
+ return isExcluded(path, inclusionPatterns, exclusionPatterns, resourceType == IResource.FOLDER || resourceType == IResource.PROJECT);
}
+
/**
* Validate the given .class file name.
* A .class file name must obey the following rules:
@@ -1251,14 +1355,17 @@
* </ul>
* </p>
* @param name the name of a .class file
+ * @param sourceLevel the source level
+ * @param complianceLevel the compliance level
* @return a status object with code <code>IStatus.OK</code> if
* the given name is valid as a .class file name, otherwise a status
* object indicating what is wrong with the name
*/
- public static boolean isValidClassFileName(String name) {
- return JavaConventions.validateClassFileName(name).getSeverity() != IStatus.ERROR;
+ public static boolean isValidClassFileName(String name, String sourceLevel, String complianceLevel) {
+ return JavaConventions.validateClassFileName(name, sourceLevel, complianceLevel).getSeverity() != IStatus.ERROR;
}
+
/**
* Validate the given compilation unit name.
* A compilation unit name must obey the following rules:
@@ -1269,20 +1376,25 @@
* </ul>
* </p>
* @param name the name of a compilation unit
+ * @param sourceLevel the source level
+ * @param complianceLevel the compliance level
* @return a status object with code <code>IStatus.OK</code> if
* the given name is valid as a compilation unit name, otherwise a status
* object indicating what is wrong with the name
*/
- public static boolean isValidCompilationUnitName(String name) {
- return JavaConventions.validateCompilationUnitName(name).getSeverity() != IStatus.ERROR;
+ public static boolean isValidCompilationUnitName(String name, String sourceLevel, String complianceLevel) {
+ return JavaConventions.validateCompilationUnitName(name, sourceLevel, complianceLevel).getSeverity() != IStatus.ERROR;
}
-
+
/**
* Returns true if the given folder name is valid for a package,
* false if it is not.
+ * @param folderName the name of the folder
+ * @param sourceLevel the source level
+ * @param complianceLevel the compliance level
*/
- public static boolean isValidFolderNameForPackage(String folderName) {
- return JavaConventions.validateIdentifier(folderName).getSeverity() != IStatus.ERROR;
+ public static boolean isValidFolderNameForPackage(String folderName, String sourceLevel, String complianceLevel) {
+ return JavaConventions.validateIdentifier(folderName, sourceLevel, complianceLevel).getSeverity() != IStatus.ERROR;
}
/**
@@ -1318,9 +1430,13 @@
/*
* Returns the simple name of a local type from the given binary type name.
- * The last '$' is at lastDollar. The ;last character of the type name is at end-1.
+ * The last '$' is at lastDollar. The last character of the type name is at end-1.
*/
public static String localTypeName(String binaryTypeName, int lastDollar, int end) {
+ if (lastDollar > 0 && binaryTypeName.charAt(lastDollar-1) == '$')
+ // local name starts with a dollar sign
+ // (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=103466)
+ return binaryTypeName;
int nameStart = lastDollar+1;
while (nameStart < end && Character.isDigit(binaryTypeName.charAt(nameStart)))
nameStart++;
@@ -1343,8 +1459,19 @@
message,
e);
JavaCore.getPlugin().getLog().log(status);
- }
+ }
+ public static ClassFileReader newClassFileReader(IResource resource) throws CoreException, ClassFormatException, IOException {
+ InputStream in = null;
+ try {
+ in = ((IFile) resource).getContents(true);
+ return ClassFileReader.read(in, resource.getFullPath().toString());
+ } finally {
+ if (in != null)
+ in.close();
+ }
+ }
+
/**
* Normalizes the cariage returns in the given text.
* They are all changed to use the given buffer's line separator.
@@ -1416,12 +1543,15 @@
/**
* Converts the given relative path into a package name.
* Returns null if the path is not a valid package name.
+ * @param pkgPath the package path
+ * @param sourceLevel the source level
+ * @param complianceLevel the compliance level
*/
- public static String packageName(IPath pkgPath) {
+ public static String packageName(IPath pkgPath, String sourceLevel, String complianceLevel) {
StringBuffer pkgName = new StringBuffer(IPackageFragment.DEFAULT_PACKAGE_NAME);
for (int j = 0, max = pkgPath.segmentCount(); j < max; j++) {
String segment = pkgPath.segment(j);
- if (!isValidFolderNameForPackage(segment)) {
+ if (!isValidFolderNameForPackage(segment, sourceLevel, complianceLevel)) {
return null;
}
pkgName.append(segment);
@@ -1455,7 +1585,7 @@
private static void quickSort(char[][] list, int left, int right) {
int original_left= left;
int original_right= right;
- char[] mid= list[(left + right) / 2];
+ char[] mid= list[left + (right - left) / 2];
do {
while (compare(list[left], mid) < 0) {
left++;
@@ -1485,7 +1615,7 @@
private static void quickSort(Comparable[] sortedCollection, int left, int right) {
int original_left = left;
int original_right = right;
- Comparable mid = sortedCollection[ (left + right) / 2];
+ Comparable mid = sortedCollection[ left + (right - left) / 2];
do {
while (sortedCollection[left].compareTo(mid) < 0) {
left++;
@@ -1511,7 +1641,7 @@
private static void quickSort(int[] list, int left, int right) {
int original_left= left;
int original_right= right;
- int mid= list[(left + right) / 2];
+ int mid= list[left + (right - left) / 2];
do {
while (list[left] < mid) {
left++;
@@ -1541,7 +1671,7 @@
private static void quickSort(Object[] sortedCollection, int left, int right, Comparer comparer) {
int original_left = left;
int original_right = right;
- Object mid = sortedCollection[ (left + right) / 2];
+ Object mid = sortedCollection[ left + (right - left) / 2];
do {
while (comparer.compare(sortedCollection[left], mid) < 0) {
left++;
@@ -1566,45 +1696,12 @@
}
/**
- * Sort the objects in the given collection using the given sort order.
- */
- private static void quickSort(Object[] sortedCollection, int left, int right, int[] sortOrder) {
- int original_left = left;
- int original_right = right;
- int mid = sortOrder[ (left + right) / 2];
- do {
- while (sortOrder[left] < mid) {
- left++;
- }
- while (mid < sortOrder[right]) {
- right--;
- }
- if (left <= right) {
- Object tmp = sortedCollection[left];
- sortedCollection[left] = sortedCollection[right];
- sortedCollection[right] = tmp;
- int tmp2 = sortOrder[left];
- sortOrder[left] = sortOrder[right];
- sortOrder[right] = tmp2;
- left++;
- right--;
- }
- } while (left <= right);
- if (original_left < right) {
- quickSort(sortedCollection, original_left, right, sortOrder);
- }
- if (left < original_right) {
- quickSort(sortedCollection, left, original_right, sortOrder);
- }
- }
-
- /**
* Sort the strings in the given collection.
*/
private static void quickSort(String[] sortedCollection, int left, int right) {
int original_left = left;
int original_right = right;
- String mid = sortedCollection[ (left + right) / 2];
+ String mid = sortedCollection[ left + (right - left) / 2];
do {
while (sortedCollection[left].compareTo(mid) < 0) {
left++;
@@ -1629,112 +1726,6 @@
}
/**
- * Sort the strings in the given collection in reverse alphabetical order.
- */
- private static void quickSortReverse(String[] sortedCollection, int left, int right) {
- int original_left = left;
- int original_right = right;
- String mid = sortedCollection[ (left + right) / 2];
- do {
- while (sortedCollection[left].compareTo(mid) > 0) {
- left++;
- }
- while (mid.compareTo(sortedCollection[right]) > 0) {
- right--;
- }
- if (left <= right) {
- String tmp = sortedCollection[left];
- sortedCollection[left] = sortedCollection[right];
- sortedCollection[right] = tmp;
- left++;
- right--;
- }
- } while (left <= right);
- if (original_left < right) {
- quickSortReverse(sortedCollection, original_left, right);
- }
- if (left < original_right) {
- quickSortReverse(sortedCollection, left, original_right);
- }
- }
- /**
- * Reads in a string from the specified data input stream. The
- * string has been encoded using a modified UTF-8 format.
- * <p>
- * The first two bytes are read as if by
- * <code>readUnsignedShort</code>. This value gives the number of
- * following bytes that are in the encoded string, not
- * the length of the resulting string. The following bytes are then
- * interpreted as bytes encoding characters in the UTF-8 format
- * and are converted into characters.
- * <p>
- * This method blocks until all the bytes are read, the end of the
- * stream is detected, or an exception is thrown.
- *
- * @param in a data input stream.
- * @return a Unicode string.
- * @exception EOFException if the input stream reaches the end
- * before all the bytes.
- * @exception IOException if an I/O error occurs.
- * @exception UTFDataFormatException if the bytes do not represent a
- * valid UTF-8 encoding of a Unicode string.
- * @see java.io.DataInputStream#readUnsignedShort()
- */
- public final static char[] readUTF(DataInput in) throws IOException {
- int utflen= in.readUnsignedShort();
- char str[]= new char[utflen];
- int count= 0;
- int strlen= 0;
- while (count < utflen) {
- int c= in.readUnsignedByte();
- int char2, char3;
- switch (c >> 4) {
- case 0 :
- case 1 :
- case 2 :
- case 3 :
- case 4 :
- case 5 :
- case 6 :
- case 7 :
- // 0xxxxxxx
- count++;
- str[strlen++]= (char) c;
- break;
- case 12 :
- case 13 :
- // 110x xxxx 10xx xxxx
- count += 2;
- if (count > utflen)
- throw new UTFDataFormatException();
- char2= in.readUnsignedByte();
- if ((char2 & 0xC0) != 0x80)
- throw new UTFDataFormatException();
- str[strlen++]= (char) (((c & 0x1F) << 6) | (char2 & 0x3F));
- break;
- case 14 :
- // 1110 xxxx 10xx xxxx 10xx xxxx
- count += 3;
- if (count > utflen)
- throw new UTFDataFormatException();
- char2= in.readUnsignedByte();
- char3= in.readUnsignedByte();
- if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80))
- throw new UTFDataFormatException();
- str[strlen++]= (char) (((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0));
- break;
- default :
- // 10xx xxxx, 1111 xxxx
- throw new UTFDataFormatException();
- }
- }
- if (strlen < utflen) {
- System.arraycopy(str, 0, str= new char[strlen], 0, strlen);
- }
- return str;
- }
-
- /**
* Returns the toString() of the given full path minus the first given number of segments.
* The returned string is always a relative path (it has no leading slash)
*/
@@ -1776,6 +1767,13 @@
return new String(result);
}
+ /*
+ * Resets the list of Java-like extensions after a change in content-type.
+ */
+ public static void resetJavaLikeExtensions() {
+ JAVA_LIKE_EXTENSIONS = null;
+ }
+
/**
* Return a new array which is the split of the given string using the given divider. The given end
* is exclusive and the given start is inclusive.
@@ -1824,19 +1822,24 @@
split[currentWord] = string.substring(last, end);
return split;
}
- public static boolean isReadOnly(IResource resource) {
- ResourceAttributes resourceAttributes = resource.getResourceAttributes();
- if (resourceAttributes == null) return false; // not supported on this platform for this resource
- return resourceAttributes.isReadOnly();
- }
+ /**
+ * Sets or unsets the given resource as read-only in the file system.
+ * It's a no-op if the file system does not support the read-only attribute.
+ *
+ * @param resource The resource to set as read-only
+ * @param readOnly <code>true</code> to set it to read-only,
+ * <code>false</code> to unset
+ */
public static void setReadOnly(IResource resource, boolean readOnly) {
- ResourceAttributes resourceAttributes = resource.getResourceAttributes();
- if (resourceAttributes == null) return; // not supported on this platform for this resource
- resourceAttributes.setReadOnly(readOnly);
- try {
- resource.setResourceAttributes(resourceAttributes);
- } catch (CoreException e) {
- // ignore
+ if (isReadOnlySupported()) {
+ ResourceAttributes resourceAttributes = resource.getResourceAttributes();
+ if (resourceAttributes == null) return; // not supported on this platform for this resource
+ resourceAttributes.setReadOnly(readOnly);
+ try {
+ resource.setResourceAttributes(resourceAttributes);
+ } catch (CoreException e) {
+ // ignore
+ }
}
}
public static void sort(char[][] list) {
@@ -1866,14 +1869,6 @@
}
/**
- * Sorts an array of objects in place, using the sort order given for each item.
- */
- public static void sort(Object[] objects, int[] sortOrder) {
- if (objects.length > 1)
- quickSort(objects, 0, objects.length - 1, sortOrder);
- }
-
- /**
* Sorts an array of strings in place using quicksort.
*/
public static void sort(String[] strings) {
@@ -1894,6 +1889,23 @@
}
/**
+ * Sorts an array of Java elements based on their toStringWithAncestors(),
+ * returning a new array with the sorted items.
+ * The original array is left untouched.
+ */
+ public static IJavaElement[] sortCopy(IJavaElement[] elements) {
+ int len = elements.length;
+ IJavaElement[] copy = new IJavaElement[len];
+ System.arraycopy(elements, 0, copy, 0, len);
+ sort(copy, new Comparer() {
+ public int compare(Object a, Object b) {
+ return ((JavaElement) a).toStringWithAncestors().compareTo(((JavaElement) b).toStringWithAncestors());
+ }
+ });
+ return copy;
+ }
+
+ /**
* Sorts an array of Strings, returning a new array
* with the sorted items. The original array is left untouched.
*/
@@ -1917,21 +1929,12 @@
return copy;
}
- /**
- * Sorts an array of strings in place using quicksort
- * in reverse alphabetical order.
- */
- public static void sortReverseOrder(String[] strings) {
- if (strings.length > 1)
- quickSortReverse(strings, 0, strings.length - 1);
- }
-
/*
* Returns whether the given compound name starts with the given prefix.
* Returns true if the n first elements of the prefix are equals and the last element of the
* prefix is a prefix of the corresponding element in the compound name.
*/
- public static boolean startsWithIgnoreCase(String[] compoundName, String[] prefix) {
+ public static boolean startsWithIgnoreCase(String[] compoundName, String[] prefix, boolean partialMatch) {
int prefixLength = prefix.length;
int nameLength = compoundName.length;
if (prefixLength > nameLength) return false;
@@ -1939,7 +1942,31 @@
if (!compoundName[i].equalsIgnoreCase(prefix[i]))
return false;
}
- return compoundName[prefixLength-1].toLowerCase().startsWith(prefix[prefixLength-1].toLowerCase());
+ return (partialMatch || prefixLength == nameLength) && compoundName[prefixLength-1].toLowerCase().startsWith(prefix[prefixLength-1].toLowerCase());
+ }
+
+ /*
+ * Returns whether the given compound name matches the given pattern.
+ */
+ public static boolean matchesWithIgnoreCase(String[] compoundName, String pattern) {
+ if (pattern.equals("*")) return true; //$NON-NLS-1$
+ int nameLength = compoundName.length;
+ if (pattern.length() == 0) return nameLength == 0;
+ if (nameLength == 0) return false;
+ int length = nameLength-1;
+ for (int i=0; i<nameLength; i++) {
+ length += compoundName[i].length();
+ }
+ char[] compoundChars = new char[length];
+ int pos = 0;
+ for (int i=0; i<nameLength; i++) {
+ if (pos > 0) compoundChars[pos++] = '.';
+ char[] array = compoundName[i].toCharArray();
+ int size = array.length;
+ System.arraycopy(array, 0, compoundChars, pos, size);
+ pos += size;
+ }
+ return CharOperation.match(pattern.toCharArray(), compoundChars, false);
}
/**
@@ -1947,6 +1974,7 @@
*/
public static char[][] toCharArrays(String[] a) {
int len = a.length;
+ if (len == 0) return CharOperation.NO_CHAR_CHAR;
char[][] result = new char[len][];
for (int i = 0; i < len; ++i) {
result[i] = a[i].toCharArray();
@@ -1977,6 +2005,19 @@
}
return segs;
}
+ /*
+ * Converts the given URI to a local file. Use the existing file if the uri is on the local file system.
+ * Otherwise fetch it.
+ * Returns null if unable to fetch it.
+ */
+ public static File toLocalFile(URI uri, IProgressMonitor monitor) throws CoreException {
+ IFileStore fileStore = EFS.getStore(uri);
+ File localFile = fileStore.toLocalFile(EFS.NONE, monitor);
+ if (localFile ==null)
+ // non local file system
+ localFile= fileStore.toLocalFile(EFS.CACHE, monitor);
+ return localFile;
+ }
/**
* Converts a char[][] to String, where segments are separated by '.'.
*/
@@ -2021,7 +2062,7 @@
throw new IllegalArgumentException();
}
char c = string[start];
- if (c != Signature.C_ARRAY) { //$NON-NLS-1$
+ if (c != Signature.C_ARRAY) {
throw new IllegalArgumentException();
}
@@ -2174,7 +2215,6 @@
if (includeReturnType) {
char[] rts = Signature.getReturnType(methodSignature);
appendTypeSignature(rts, 0 , buffer, compact);
- buffer.append(' ');
}
}
return String.valueOf(buffer);
@@ -2194,7 +2234,7 @@
}
return signatures;
}
- return new String[0];
+ return CharOperation.NO_STRINGS;
}
/*
@@ -2235,59 +2275,6 @@
} while (start != 0);
printStream.println();
}
- /**
- * Writes a string to the given output stream using UTF-8
- * encoding in a machine-independent manner.
- * <p>
- * First, two bytes are written to the output stream as if by the
- * <code>writeShort</code> method giving the number of bytes to
- * follow. This value is the number of bytes actually written out,
- * not the length of the string. Following the length, each character
- * of the string is output, in sequence, using the UTF-8 encoding
- * for the character.
- *
- * @param str a string to be written.
- * @return the number of bytes written to the stream.
- * @exception IOException if an I/O error occurs.
- * @since JDK1.0
- */
- public static int writeUTF(OutputStream out, char[] str) throws IOException {
- int strlen= str.length;
- int utflen= 0;
- for (int i= 0; i < strlen; i++) {
- int c= str[i];
- if ((c >= 0x0001) && (c <= 0x007F)) {
- utflen++;
- } else if (c > 0x07FF) {
- utflen += 3;
- } else {
- utflen += 2;
- }
- }
- if (utflen > 65535)
- throw new UTFDataFormatException();
- out.write((utflen >>> 8) & 0xFF);
- out.write((utflen >>> 0) & 0xFF);
- if (strlen == utflen) {
- for (int i= 0; i < strlen; i++)
- out.write(str[i]);
- } else {
- for (int i= 0; i < strlen; i++) {
- int c= str[i];
- if ((c >= 0x0001) && (c <= 0x007F)) {
- out.write(c);
- } else if (c > 0x07FF) {
- out.write(0xE0 | ((c >> 12) & 0x0F));
- out.write(0x80 | ((c >> 6) & 0x3F));
- out.write(0x80 | ((c >> 0) & 0x3F));
- } else {
- out.write(0xC0 | ((c >> 6) & 0x1F));
- out.write(0x80 | ((c >> 0) & 0x3F));
- }
- }
- }
- return utflen + 2; // the number of bytes written to the stream
- }
/**
* Returns true if the given name ends with one of the known java like extension.
@@ -2310,7 +2297,8 @@
char[] extension = javaLikeExtensions[i];
int extensionLength = extension.length;
int extensionStart = fileNameLength - extensionLength;
- if (extensionStart < 0) continue;
+ if (extensionStart-1 < 0) continue;
+ if (fileName[extensionStart-1] != '.') continue;
for (int j = 0; j < extensionLength; j++) {
if (fileName[extensionStart + j] != extension[j])
continue extensions;
@@ -2421,7 +2409,7 @@
throw new IllegalArgumentException();
}
char c = string[start];
- if (c != Signature.C_ARRAY) { //$NON-NLS-1$
+ if (c != Signature.C_ARRAY) {
throw new IllegalArgumentException();
}
@@ -2455,7 +2443,7 @@
throw new IllegalArgumentException();
}
char c = string[start];
- if (c != Signature.C_CAPTURE) { //$NON-NLS-1$
+ if (c != Signature.C_CAPTURE) {
throw new IllegalArgumentException();
}
return scanTypeBoundSignature(string, start + 1);
@@ -2594,8 +2582,8 @@
return start;
case Signature.C_SUPER :
case Signature.C_EXTENDS :
- // need a minimum 4 chars "+Lx;"
- if (start >= string.length - 3) {
+ // need a minimum 3 chars "+[I"
+ if (start >= string.length - 2) {
throw new IllegalArgumentException();
}
break;
@@ -2763,7 +2751,7 @@
int paramOpening = 0;
// Scan each signature character
- scanUniqueKey: for (int idx=0, ln = source.length; idx < ln; idx++) {
+ for (int idx=0, ln = source.length; idx < ln; idx++) {
switch (source[idx]) {
case '>':
paramOpening--;
@@ -2809,4 +2797,256 @@
}
return typeSignatures;
}
+
+ /*
+ * Can throw IllegalArgumentException or ArrayIndexOutOfBoundsException
+ */
+ public static String toAnchor(char[] methodSignature, String methodName, boolean isVarArgs) {
+ try {
+ return new String(toAnchor(methodSignature, methodName.toCharArray(), isVarArgs));
+ } catch(IllegalArgumentException e) {
+ return null;
+ }
+ }
+ private static char[] toAnchor(char[] methodSignature, char[] methodName, boolean isVargArgs) {
+ int firstParen = CharOperation.indexOf(Signature.C_PARAM_START, methodSignature);
+ if (firstParen == -1) {
+ throw new IllegalArgumentException();
+ }
+
+ StringBuffer buffer = new StringBuffer(methodSignature.length + 10);
+
+ // selector
+ if (methodName != null) {
+ buffer.append(methodName);
+ }
+
+ // parameters
+ buffer.append('(');
+ char[][] pts = Signature.getParameterTypes(methodSignature);
+ for (int i = 0, max = pts.length; i < max; i++) {
+ if (i == max - 1) {
+ appendTypeSignatureForAnchor(pts[i], 0 , buffer, isVargArgs);
+ } else {
+ appendTypeSignatureForAnchor(pts[i], 0 , buffer, false);
+ }
+ if (i != pts.length - 1) {
+ buffer.append(',');
+ buffer.append(' ');
+ }
+ }
+ buffer.append(')');
+ char[] result = new char[buffer.length()];
+ buffer.getChars(0, buffer.length(), result, 0);
+ return result;
+ }
+
+ private static int appendTypeSignatureForAnchor(char[] string, int start, StringBuffer buffer, boolean isVarArgs) {
+ // need a minimum 1 char
+ if (start >= string.length) {
+ throw new IllegalArgumentException();
+ }
+ char c = string[start];
+ if (isVarArgs) {
+ switch (c) {
+ case Signature.C_ARRAY :
+ return appendArrayTypeSignatureForAnchor(string, start, buffer, true);
+ case Signature.C_RESOLVED :
+ case Signature.C_TYPE_VARIABLE :
+ case Signature.C_BOOLEAN :
+ case Signature.C_BYTE :
+ case Signature.C_CHAR :
+ case Signature.C_DOUBLE :
+ case Signature.C_FLOAT :
+ case Signature.C_INT :
+ case Signature.C_LONG :
+ case Signature.C_SHORT :
+ case Signature.C_VOID :
+ case Signature.C_STAR:
+ case Signature.C_EXTENDS:
+ case Signature.C_SUPER:
+ case Signature.C_CAPTURE:
+ default:
+ throw new IllegalArgumentException(); // a var args is an array type
+ }
+ } else {
+ switch (c) {
+ case Signature.C_ARRAY :
+ return appendArrayTypeSignatureForAnchor(string, start, buffer, false);
+ case Signature.C_RESOLVED :
+ return appendClassTypeSignatureForAnchor(string, start, buffer);
+ case Signature.C_TYPE_VARIABLE :
+ int e = Util.scanTypeVariableSignature(string, start);
+ buffer.append(string, start + 1, e - start - 1);
+ return e;
+ case Signature.C_BOOLEAN :
+ buffer.append(BOOLEAN);
+ return start;
+ case Signature.C_BYTE :
+ buffer.append(BYTE);
+ return start;
+ case Signature.C_CHAR :
+ buffer.append(CHAR);
+ return start;
+ case Signature.C_DOUBLE :
+ buffer.append(DOUBLE);
+ return start;
+ case Signature.C_FLOAT :
+ buffer.append(FLOAT);
+ return start;
+ case Signature.C_INT :
+ buffer.append(INT);
+ return start;
+ case Signature.C_LONG :
+ buffer.append(LONG);
+ return start;
+ case Signature.C_SHORT :
+ buffer.append(SHORT);
+ return start;
+ case Signature.C_VOID :
+ buffer.append(VOID);
+ return start;
+ case Signature.C_CAPTURE :
+ return appendCaptureTypeSignatureForAnchor(string, start, buffer);
+ case Signature.C_STAR:
+ case Signature.C_EXTENDS:
+ case Signature.C_SUPER:
+ return appendTypeArgumentSignatureForAnchor(string, start, buffer);
+ default :
+ throw new IllegalArgumentException();
+ }
+ }
+ }
+ private static int appendTypeArgumentSignatureForAnchor(char[] string, int start, StringBuffer buffer) {
+ // need a minimum 1 char
+ if (start >= string.length) {
+ throw new IllegalArgumentException();
+ }
+ char c = string[start];
+ switch(c) {
+ case Signature.C_STAR :
+ return start;
+ case Signature.C_EXTENDS :
+ return appendTypeSignatureForAnchor(string, start + 1, buffer, false);
+ case Signature.C_SUPER :
+ return appendTypeSignatureForAnchor(string, start + 1, buffer, false);
+ default :
+ return appendTypeSignatureForAnchor(string, start, buffer, false);
+ }
+ }
+ private static int appendCaptureTypeSignatureForAnchor(char[] string, int start, StringBuffer buffer) {
+ // need a minimum 2 char
+ if (start >= string.length - 1) {
+ throw new IllegalArgumentException();
+ }
+ char c = string[start];
+ if (c != Signature.C_CAPTURE) {
+ throw new IllegalArgumentException();
+ }
+ return appendTypeArgumentSignatureForAnchor(string, start + 1, buffer);
+ }
+ private static int appendArrayTypeSignatureForAnchor(char[] string, int start, StringBuffer buffer, boolean isVarArgs) {
+ int length = string.length;
+ // need a minimum 2 char
+ if (start >= length - 1) {
+ throw new IllegalArgumentException();
+ }
+ char c = string[start];
+ if (c != Signature.C_ARRAY) {
+ throw new IllegalArgumentException();
+ }
+
+ int index = start;
+ c = string[++index];
+ while(c == Signature.C_ARRAY) {
+ // need a minimum 2 char
+ if (index >= length - 1) {
+ throw new IllegalArgumentException();
+ }
+ c = string[++index];
+ }
+
+ int e = appendTypeSignatureForAnchor(string, index, buffer, false);
+
+ for(int i = 1, dims = index - start; i < dims; i++) {
+ buffer.append('[').append(']');
+ }
+
+ if (isVarArgs) {
+ buffer.append('.').append('.').append('.');
+ } else {
+ buffer.append('[').append(']');
+ }
+ return e;
+ }
+ private static int appendClassTypeSignatureForAnchor(char[] string, int start, StringBuffer buffer) {
+ // need a minimum 3 chars "Lx;"
+ if (start >= string.length - 2) {
+ throw new IllegalArgumentException();
+ }
+ // must start in "L" or "Q"
+ char c = string[start];
+ if (c != Signature.C_RESOLVED && c != Signature.C_UNRESOLVED) {
+ throw new IllegalArgumentException();
+ }
+ int p = start + 1;
+ while (true) {
+ if (p >= string.length) {
+ throw new IllegalArgumentException();
+ }
+ c = string[p];
+ switch(c) {
+ case Signature.C_SEMICOLON :
+ // all done
+ return p;
+ case Signature.C_GENERIC_START :
+ int e = scanGenericEnd(string, p + 1);
+ // once we hit type arguments there are no more package prefixes
+ p = e;
+ break;
+ case Signature.C_DOT :
+ buffer.append('.');
+ break;
+ case '/' :
+ buffer.append('/');
+ break;
+ case Signature.C_DOLLAR :
+ // once we hit "$" there are no more package prefixes
+ /**
+ * Convert '$' in resolved type signatures into '.'.
+ * 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 '$'.
+ */
+ buffer.append('.');
+ break;
+ default :
+ buffer.append(c);
+ }
+ p++;
+ }
+ }
+ private static int scanGenericEnd(char[] string, int start) {
+ if (string[start] == Signature.C_GENERIC_END) {
+ return start;
+ }
+ int length = string.length;
+ int balance = 1;
+ start++;
+ while (start <= length) {
+ switch(string[start]) {
+ case Signature.C_GENERIC_END :
+ balance--;
+ if (balance == 0) {
+ return start;
+ }
+ break;
+ case Signature.C_GENERIC_START :
+ balance++;
+ break;
+ }
+ start++;
+ }
+ return start;
+ }
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/VerificationInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/VerificationInfo.java
new file mode 100755
index 0000000..62ab95b
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/VerificationInfo.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.util;
+
+import org.eclipse.jdt.core.util.ClassFormatException;
+import org.eclipse.jdt.core.util.IConstantPool;
+import org.eclipse.jdt.core.util.IConstantPoolConstant;
+import org.eclipse.jdt.core.util.IConstantPoolEntry;
+import org.eclipse.jdt.core.util.IVerificationTypeInfo;
+
+public class VerificationInfo extends ClassFileStruct implements IVerificationTypeInfo {
+
+ private int tag;
+ private int offset;
+ private int constantPoolIndex;
+ private char[] classTypeName;
+ private int readOffset;
+
+ public VerificationInfo(
+ byte[] classFileBytes,
+ IConstantPool constantPool,
+ int offset) throws ClassFormatException {
+ final int t = u1At(classFileBytes, 0, offset);
+ this.tag = t;
+ this.readOffset = 1;
+ switch(t) {
+ case IVerificationTypeInfo.ITEM_OBJECT :
+ final int constantIndex = u2At(classFileBytes, 1, offset);
+ this.constantPoolIndex = constantIndex;
+ if (constantIndex != 0) {
+ IConstantPoolEntry constantPoolEntry = constantPool.decodeEntry(constantIndex);
+ if (constantPoolEntry.getKind() != IConstantPoolConstant.CONSTANT_Class) {
+ throw new ClassFormatException(ClassFormatException.INVALID_CONSTANT_POOL_ENTRY);
+ }
+ this.classTypeName = constantPoolEntry.getClassInfoName();
+ }
+ this.readOffset += 2;
+ break;
+ case IVerificationTypeInfo.ITEM_UNINITIALIZED :
+ this.offset = u2At(classFileBytes, 1, offset);
+ this.readOffset += 2;
+ }
+ }
+
+ public int getTag() {
+ return this.tag;
+ }
+
+ public int getOffset() {
+ return this.offset;
+ }
+
+ public int getConstantPoolIndex() {
+ return this.constantPoolIndex;
+ }
+
+ public char[] getClassTypeName() {
+ return this.classTypeName;
+ }
+
+ public int sizeInBytes() {
+ return this.readOffset;
+ }
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/WeakHashSet.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/WeakHashSet.java
new file mode 100755
index 0000000..8eb19b7
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/WeakHashSet.java
@@ -0,0 +1,217 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.util;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+
+/**
+ * A hashset whose values can be garbage collected.
+ */
+public class WeakHashSet {
+
+ public static class HashableWeakReference extends WeakReference {
+ public int hashCode;
+ public HashableWeakReference(Object referent, ReferenceQueue queue) {
+ super(referent, queue);
+ this.hashCode = referent.hashCode();
+ }
+ public boolean equals(Object obj) {
+ if (!(obj instanceof HashableWeakReference)) return false;
+ Object referent = get();
+ Object other = ((HashableWeakReference) obj).get();
+ if (referent == null) return other == null;
+ return referent.equals(other);
+ }
+ public int hashCode() {
+ return this.hashCode;
+ }
+ public String toString() {
+ Object referent = get();
+ if (referent == null) return "[hashCode=" + this.hashCode + "] <referent was garbage collected>"; //$NON-NLS-1$ //$NON-NLS-2$
+ return "[hashCode=" + this.hashCode + "] " + referent.toString(); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+
+ HashableWeakReference[] values;
+ public int elementSize; // number of elements in the table
+ int threshold;
+ ReferenceQueue referenceQueue = new ReferenceQueue();
+
+ public WeakHashSet() {
+ this(5);
+ }
+
+ public WeakHashSet(int size) {
+ this.elementSize = 0;
+ this.threshold = size; // size represents the expected number of elements
+ int extraRoom = (int) (size * 1.75f);
+ if (this.threshold == extraRoom)
+ extraRoom++;
+ this.values = new HashableWeakReference[extraRoom];
+ }
+
+ /*
+ * Adds the given object to this set.
+ * If an object that is equals to the given object already exists, do nothing.
+ * Returns the existing object or the new object if not found.
+ */
+ public Object add(Object obj) {
+ cleanupGarbageCollectedValues();
+ int valuesLength = this.values.length,
+ index = (obj.hashCode() & 0x7FFFFFFF) % valuesLength;
+ HashableWeakReference currentValue;
+ while ((currentValue = this.values[index]) != null) {
+ Object referent;
+ if (obj.equals(referent = currentValue.get())) {
+ return referent;
+ }
+ if (++index == valuesLength) {
+ index = 0;
+ }
+ }
+ this.values[index] = new HashableWeakReference(obj, this.referenceQueue);
+
+ // assumes the threshold is never equal to the size of the table
+ if (++this.elementSize > this.threshold)
+ rehash();
+
+ return obj;
+ }
+
+ private void addValue(HashableWeakReference value) {
+ Object obj = value.get();
+ if (obj == null) return;
+ int valuesLength = this.values.length;
+ int index = (value.hashCode & 0x7FFFFFFF) % valuesLength;
+ HashableWeakReference currentValue;
+ while ((currentValue = this.values[index]) != null) {
+ if (obj.equals(currentValue.get())) {
+ return;
+ }
+ if (++index == valuesLength) {
+ index = 0;
+ }
+ }
+ this.values[index] = value;
+
+ // assumes the threshold is never equal to the size of the table
+ if (++this.elementSize > this.threshold)
+ rehash();
+ }
+
+ private void cleanupGarbageCollectedValues() {
+ HashableWeakReference toBeRemoved;
+ while ((toBeRemoved = (HashableWeakReference) this.referenceQueue.poll()) != null) {
+ int hashCode = toBeRemoved.hashCode;
+ int valuesLength = this.values.length;
+ int index = (hashCode & 0x7FFFFFFF) % valuesLength;
+ HashableWeakReference currentValue;
+ while ((currentValue = this.values[index]) != null) {
+ if (currentValue == toBeRemoved) {
+ // replace the value at index with the last value with the same hash
+ int sameHash = index;
+ int current;
+ while ((currentValue = this.values[current = (sameHash + 1) % valuesLength]) != null && currentValue.hashCode == hashCode)
+ sameHash = current;
+ this.values[index] = this.values[sameHash];
+ this.values[sameHash] = null;
+ this.elementSize--;
+ break;
+ }
+ if (++index == valuesLength) {
+ index = 0;
+ }
+ }
+ }
+ }
+
+ public boolean contains(Object obj) {
+ return get(obj) != null;
+ }
+
+ /*
+ * Return the object that is in this set and that is equals to the given object.
+ * Return null if not found.
+ */
+ public Object get(Object obj) {
+ cleanupGarbageCollectedValues();
+ int valuesLength = this.values.length;
+ int index = (obj.hashCode() & 0x7FFFFFFF) % valuesLength;
+ HashableWeakReference currentValue;
+ while ((currentValue = this.values[index]) != null) {
+ Object referent;
+ if (obj.equals(referent = currentValue.get())) {
+ return referent;
+ }
+ if (++index == valuesLength) {
+ index = 0;
+ }
+ }
+ return null;
+ }
+
+ private void rehash() {
+ WeakHashSet newHashSet = new WeakHashSet(this.elementSize * 2); // double the number of expected elements
+ newHashSet.referenceQueue = this.referenceQueue;
+ HashableWeakReference currentValue;
+ for (int i = 0, length = this.values.length; i < length; i++)
+ if ((currentValue = this.values[i]) != null)
+ newHashSet.addValue(currentValue);
+
+ this.values = newHashSet.values;
+ this.threshold = newHashSet.threshold;
+ this.elementSize = newHashSet.elementSize;
+ }
+
+ /*
+ * Removes the object that is in this set and that is equals to the given object.
+ * Return the object that was in the set, or null if not found.
+ */
+ public Object remove(Object obj) {
+ cleanupGarbageCollectedValues();
+ int valuesLength = this.values.length;
+ int index = (obj.hashCode() & 0x7FFFFFFF) % valuesLength;
+ HashableWeakReference currentValue;
+ while ((currentValue = this.values[index]) != null) {
+ Object referent;
+ if (obj.equals(referent = currentValue.get())) {
+ this.elementSize--;
+ this.values[index] = null;
+ rehash();
+ return referent;
+ }
+ if (++index == valuesLength) {
+ index = 0;
+ }
+ }
+ return null;
+ }
+
+ public int size() {
+ return this.elementSize;
+ }
+
+ public String toString() {
+ StringBuffer buffer = new StringBuffer("{"); //$NON-NLS-1$
+ for (int i = 0, length = this.values.length; i < length; i++) {
+ HashableWeakReference value = this.values[i];
+ if (value != null) {
+ Object ref = value.get();
+ if (ref != null) {
+ buffer.append(ref.toString());
+ buffer.append(", "); //$NON-NLS-1$
+ }
+ }
+ }
+ buffer.append("}"); //$NON-NLS-1$
+ return buffer.toString();
+ }
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/WeakHashSetOfCharArray.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/WeakHashSetOfCharArray.java
new file mode 100755
index 0000000..790f8f8
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/WeakHashSetOfCharArray.java
@@ -0,0 +1,220 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.util;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+
+/**
+ * A hashset of char[] whose values can be garbage collected.
+ */
+public class WeakHashSetOfCharArray {
+
+ public static class HashableWeakReference extends WeakReference {
+ public int hashCode;
+ public HashableWeakReference(char[] referent, ReferenceQueue queue) {
+ super(referent, queue);
+ this.hashCode = CharOperation.hashCode(referent);
+ }
+ public boolean equals(Object obj) {
+ if (!(obj instanceof HashableWeakReference)) return false;
+ char[] referent = (char[]) get();
+ char[] other = (char[]) ((HashableWeakReference) obj).get();
+ if (referent == null) return other == null;
+ return CharOperation.equals(referent, other);
+ }
+ public int hashCode() {
+ return this.hashCode;
+ }
+ public String toString() {
+ char[] referent = (char[]) get();
+ if (referent == null) return "[hashCode=" + this.hashCode + "] <referent was garbage collected>"; //$NON-NLS-1$ //$NON-NLS-2$
+ return "[hashCode=" + this.hashCode + "] \"" + new String(referent) + '\"'; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+
+ HashableWeakReference[] values;
+ public int elementSize; // number of elements in the table
+ int threshold;
+ ReferenceQueue referenceQueue = new ReferenceQueue();
+
+ public WeakHashSetOfCharArray() {
+ this(5);
+ }
+
+ public WeakHashSetOfCharArray(int size) {
+ this.elementSize = 0;
+ this.threshold = size; // size represents the expected number of elements
+ int extraRoom = (int) (size * 1.75f);
+ if (this.threshold == extraRoom)
+ extraRoom++;
+ this.values = new HashableWeakReference[extraRoom];
+ }
+
+ /*
+ * Adds the given char array to this set.
+ * If a char array that is equals to the given char array already exists, do nothing.
+ * Returns the existing char array or the new char array if not found.
+ */
+ public char[] add(char[] array) {
+ cleanupGarbageCollectedValues();
+ int valuesLength = this.values.length,
+ index = (CharOperation.hashCode(array) & 0x7FFFFFFF) % valuesLength;
+ HashableWeakReference currentValue;
+ while ((currentValue = this.values[index]) != null) {
+ char[] referent;
+ if (CharOperation.equals(array, referent = (char[]) currentValue.get())) {
+ return referent;
+ }
+ if (++index == valuesLength) {
+ index = 0;
+ }
+ }
+ this.values[index] = new HashableWeakReference(array, this.referenceQueue);
+
+ // assumes the threshold is never equal to the size of the table
+ if (++this.elementSize > this.threshold)
+ rehash();
+
+ return array;
+ }
+
+ private void addValue(HashableWeakReference value) {
+ char[] array = (char[]) value.get();
+ if (array == null) return;
+ int valuesLength = this.values.length;
+ int index = (value.hashCode & 0x7FFFFFFF) % valuesLength;
+ HashableWeakReference currentValue;
+ while ((currentValue = this.values[index]) != null) {
+ if (CharOperation.equals(array, (char[]) currentValue.get())) {
+ return;
+ }
+ if (++index == valuesLength) {
+ index = 0;
+ }
+ }
+ this.values[index] = value;
+
+ // assumes the threshold is never equal to the size of the table
+ if (++this.elementSize > this.threshold)
+ rehash();
+ }
+
+ private void cleanupGarbageCollectedValues() {
+ HashableWeakReference toBeRemoved;
+ while ((toBeRemoved = (HashableWeakReference) this.referenceQueue.poll()) != null) {
+ int hashCode = toBeRemoved.hashCode;
+ int valuesLength = this.values.length;
+ int index = (hashCode & 0x7FFFFFFF) % valuesLength;
+ HashableWeakReference currentValue;
+ while ((currentValue = this.values[index]) != null) {
+ if (currentValue == toBeRemoved) {
+ // replace the value at index with the last value with the same hash
+ int sameHash = index;
+ int current;
+ while ((currentValue = this.values[current = (sameHash + 1) % valuesLength]) != null && currentValue.hashCode == hashCode)
+ sameHash = current;
+ this.values[index] = this.values[sameHash];
+ this.values[sameHash] = null;
+ this.elementSize--;
+ break;
+ }
+ if (++index == valuesLength) {
+ index = 0;
+ }
+ }
+ }
+ }
+
+ public boolean contains(char[] array) {
+ return get(array) != null;
+ }
+
+ /*
+ * Return the char array that is in this set and that is equals to the given char array.
+ * Return null if not found.
+ */
+ public char[] get(char[] array) {
+ cleanupGarbageCollectedValues();
+ int valuesLength = this.values.length;
+ int index = (CharOperation.hashCode(array) & 0x7FFFFFFF) % valuesLength;
+ HashableWeakReference currentValue;
+ while ((currentValue = this.values[index]) != null) {
+ char[] referent;
+ if (CharOperation.equals(array, referent = (char[]) currentValue.get())) {
+ return referent;
+ }
+ if (++index == valuesLength) {
+ index = 0;
+ }
+ }
+ return null;
+ }
+
+ private void rehash() {
+ WeakHashSetOfCharArray newHashSet = new WeakHashSetOfCharArray(this.elementSize * 2); // double the number of expected elements
+ newHashSet.referenceQueue = this.referenceQueue;
+ HashableWeakReference currentValue;
+ for (int i = 0, length = this.values.length; i < length; i++)
+ if ((currentValue = this.values[i]) != null)
+ newHashSet.addValue(currentValue);
+
+ this.values = newHashSet.values;
+ this.threshold = newHashSet.threshold;
+ this.elementSize = newHashSet.elementSize;
+ }
+
+ /*
+ * Removes the char array that is in this set and that is equals to the given char array.
+ * Return the char array that was in the set, or null if not found.
+ */
+ public char[] remove(char[] array) {
+ cleanupGarbageCollectedValues();
+ int valuesLength = this.values.length;
+ int index = (CharOperation.hashCode(array) & 0x7FFFFFFF) % valuesLength;
+ HashableWeakReference currentValue;
+ while ((currentValue = this.values[index]) != null) {
+ char[] referent;
+ if (CharOperation.equals(array, referent = (char[]) currentValue.get())) {
+ this.elementSize--;
+ this.values[index] = null;
+ rehash();
+ return referent;
+ }
+ if (++index == valuesLength) {
+ index = 0;
+ }
+ }
+ return null;
+ }
+
+ public int size() {
+ return this.elementSize;
+ }
+
+ public String toString() {
+ StringBuffer buffer = new StringBuffer("{"); //$NON-NLS-1$
+ for (int i = 0, length = this.values.length; i < length; i++) {
+ HashableWeakReference value = this.values[i];
+ if (value != null) {
+ char[] ref = (char[]) value.get();
+ if (ref != null) {
+ buffer.append('\"');
+ buffer.append(ref);
+ buffer.append("\", "); //$NON-NLS-1$
+ }
+ }
+ }
+ buffer.append("}"); //$NON-NLS-1$
+ return buffer.toString();
+ }
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/messages.properties b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/messages.properties
index b271672..cd45c04 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/messages.properties
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/messages.properties
@@ -1,5 +1,5 @@
###############################################################################
-# Copyright (c) 2000, 2005 IBM Corporation and others.
+# Copyright (c) 2000, 2007 IBM Corporation and others.
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
@@ -28,7 +28,6 @@
element_nullName = Name cannot be null
element_nullType = Type cannot be null
element_illegalParent = Illegal parent argument
-sourcetype_invalidName = The source type has an invalid name: {0}
### java model operations
operation_needElements = Operation requires one or more elements
@@ -57,21 +56,21 @@
operation_deleteElementProgress = Deleting elements...
operation_deleteResourceProgress = Deleting resources...
operation_cannotRenameDefaultPackage = Default package cannot be renamed
-operation_pathOutsideProject = Path ''{0}'' must denote location inside project {1}
+operation_pathOutsideProject = Path ''{0}'' must denote location inside project ''{1}''
operation_sortelements = Sorting elements...
### working copy
workingCopy_commit = Committing working copy...
### build status messages
-build_preparingBuild = Preparing for build
-build_readStateProgress = Reading saved built state for project {0}
-build_saveStateProgress = Saving built state for project {0}
+build_preparingBuild = Preparing to build {0}
+build_readStateProgress = Reading saved build state for project {0}
+build_saveStateProgress = Saving build state for project {0}
build_saveStateComplete = Saved in {0} ms
build_readingDelta = Reading resource change information for {0}
build_analyzingDeltas = Analyzing deltas
build_analyzingSources = Analyzing sources
-build_cleaningOutput = Cleaning output folder
+build_cleaningOutput = Cleaning output folder for {0}
build_copyingResources = Copying resources to the output folder
build_compiling = Compiling {0}
build_foundHeader = Found
@@ -124,47 +123,51 @@
status_readOnly = {0} is read-only
status_targetException = Target exception
status_updateConflict = Update conflict
+status_cannot_retrieve_attached_javadoc = Cannot retrieve the attached javadoc for {0}{1}
+status_unknown_javadoc_format = Unknown javadoc format for {0}
### classpath
classpath_buildPath = Build path
classpath_cannotNestEntryInEntry = Cannot nest ''{0}'' inside ''{1}''. To enable the nesting exclude ''{2}'' from ''{1}''
+classpath_cannotNestEntryInEntryNoExclusion= Cannot nest ''{0}'' inside ''{1}''. To allow the nesting enable use of exclusion patterns in the preferences of project ''{1}'' and exclude ''{2}'' from ''{1}''
classpath_cannotNestEntryInLibrary = Cannot nest ''{0}'' inside library ''{1}''
classpath_cannotNestEntryInOutput = Cannot nest ''{0}'' inside output folder ''{1}''
classpath_cannotNestOutputInEntry = Cannot nest output folder ''{0}'' inside ''{1}''
classpath_cannotNestOutputInOutput = Cannot nest output folder ''{0}'' inside output folder ''{1}''
-classpath_cannotReadClasspathFile = Unable to read ''.classpath'' file of project {0}
-classpath_cannotReferToItself = Project cannot reference itself: {0}
-classpath_cannotUseDistinctSourceFolderAsOutput = Source folder ''{0}'' in project {2} cannot output to distinct source folder ''{1}''
-classpath_cannotUseLibraryAsOutput = Source folder ''{0}'' in project {2} cannot output to library ''{1}''
-classpath_closedProject = Required project: {0} needs to be open
-classpath_couldNotWriteClasspathFile = Could not write ''.classpath'' file of project {0}: {1}
-classpath_cycle = A cycle was detected in the build path of project: {0}
-classpath_duplicateEntryPath = Build path contains duplicate entry: ''{0}'' for project {1}
-classpath_illegalContainerPath = Illegal classpath container path: ''{0}'' in project {1}, must have at least one segment (containerID+hints)
-classpath_illegalEntryInClasspathFile = Illegal entry in ''.classpath'' of project {0} file: {1}
-classpath_illegalLibraryPath = Illegal path for required library: ''{0}'' in project {1}
-classpath_illegalLibraryArchive = Illegal type of archive for required library: ''{0}'' in project {1}
-classpath_illegalExternalFolder = Required library cannot denote external folder: ''{0}'' for project {1}
-classpath_illegalProjectPath = Illegal path for required project: ''{0}'' in project {1}
-classpath_illegalSourceFolderPath = Illegal path for required source folder: ''{0}'' in project {1}
-classpath_illegalVariablePath = Illegal classpath variable path: ''{0}'' in project {1}, must have at least one segment
-classpath_invalidClasspathInClasspathFile = Invalid build path in ''.classpath'' file of project {0}: {1}
-classpath_invalidContainer = Invalid classpath container: ''{0}'' in project {1}
+classpath_cannotReadClasspathFile = Unable to read ''.classpath'' file of project ''{0}''
+classpath_cannotReferToItself = Project ''{0}'' cannot reference itself
+classpath_cannotUseDistinctSourceFolderAsOutput = Source folder ''{0}'' in project ''{2}'' cannot output to distinct source folder ''{1}''
+classpath_cannotUseLibraryAsOutput = Source folder ''{0}'' in project ''{2}'' cannot output to library ''{1}''
+classpath_closedProject = Required project ''{0}'' needs to be open
+classpath_couldNotWriteClasspathFile = Could not write ''.classpath'' file of project ''{0}'': {1}
+classpath_cycle = A cycle was detected in the build path of project ''{0}''
+classpath_duplicateEntryPath = Build path contains duplicate entry: ''{0}'' for project ''{1}''
+classpath_illegalContainerPath = Illegal classpath container path: ''{0}'' in project ''{1}'', must have at least one segment (containerID+hints)
+classpath_illegalEntryInClasspathFile = Illegal entry in ''.classpath'' of project ''{0}'' file: {1}
+classpath_illegalLibraryPath = Illegal path for required library: ''{0}'' in project ''{1}''
+classpath_illegalLibraryArchive = Illegal type of archive for required library: ''{0}'' in project ''{1}''
+classpath_illegalExternalFolder = Required library cannot denote external folder: ''{0}'' for project ''{1}''
+classpath_illegalProjectPath = Illegal path for required project: ''{0}'' in project ''{1}''
+classpath_illegalSourceFolderPath = Illegal path for required source folder: ''{0}'' in project ''{1}''
+classpath_illegalVariablePath = Illegal classpath variable path: ''{0}'' in project ''{1}'', must have at least one segment
+classpath_invalidClasspathInClasspathFile = Invalid build path in ''.classpath'' file of project ''{0}'': {1}
+classpath_invalidContainer = Invalid classpath container: ''{0}'' in project ''{1}''
classpath_mustEndWithSlash = End exclusion filter ''{0}'' with / to fully exclude ''{1}''
-classpath_unboundContainerPath = Unbound classpath container: ''{0}'' in project {1}
-classpath_unboundLibrary = Project {1} is missing required library: ''{0}''
-classpath_unboundProject = Project {1} is missing required Java project: ''{0}''
+classpath_unboundContainerPath = Unbound classpath container: ''{0}'' in project ''{1}''
+classpath_unboundLibrary = Project ''{1}'' is missing required library: ''{0}''
+classpath_unboundProject = Project ''{1}'' is missing required Java project: ''{0}''
classpath_settingOutputLocationProgress = Setting output location for: ''{0}''
classpath_settingProgress = Setting classpath for: {0}
-classpath_unboundSourceAttachment = Invalid source attachment: ''{0}'' for required library ''{1}'' in project {1}
-classpath_unboundSourceFolder = Project {1} is missing required source folder: ''{0}''
-classpath_unboundVariablePath = Unbound classpath variable: ''{0}'' in project {1}
+classpath_unboundSourceAttachment = Invalid source attachment: ''{0}'' for required library ''{1}'' in project ''{1}''
+classpath_unboundSourceFolder = Project ''{1}'' is missing required source folder: ''{0}''
+classpath_unboundVariablePath = Unbound classpath variable: ''{0}'' in project ''{1}''
classpath_unknownKind = Unknown kind: ''{0}''
-classpath_xmlFormatError = XML format error in ''.classpath'' file of project {0}: {1}
-classpath_disabledInclusionExclusionPatterns = Inclusion or exclusion patterns are disabled in project {1}, cannot selectively include or exclude from entry: ''{0}''
-classpath_disabledMultipleOutputLocations = Multiple output locations are disabled in project {1}, cannot associate entry: ''{0}'' with a specific output
+classpath_xmlFormatError = XML format error in ''.classpath'' file of project ''{0}'': {1}
+classpath_disabledInclusionExclusionPatterns = Inclusion or exclusion patterns are disabled in project ''{1}'', cannot selectively include or exclude from entry: ''{0}''
+classpath_disabledMultipleOutputLocations = Multiple output locations are disabled in project ''{1}'', cannot associate entry: ''{0}'' with a specific output
classpath_incompatibleLibraryJDKLevel = Incompatible .class files version in required binaries. Project ''{0}'' is targeting a {1} runtime, but is compiled against ''{2}'' which requires a {3} runtime
-classpath_duplicateEntryExtraAttribute = Duplicate extra attribute: ''{0}'' in classpath entry ''{1}'' for project {2}
+classpath_duplicateEntryExtraAttribute = Duplicate extra attribute: ''{0}'' in classpath entry ''{1}'' for project ''{2}''
+classpath_deprecated_variable = Classpath variable ''{0}'' in project ''{1}'' is deprecated: {2}
### miscellaneous
file_notFound = File not found: ''{0}''
@@ -173,15 +176,29 @@
path_mustBeAbsolute = Path must be absolute
cache_invalidLoadFactor = Incorrect load factor
savedState_jobName = Processing Java changes since last activation
+
+## java model initialization
javamodel_initialization = Initializing Java tooling
+javamodel_configuring_searchengine=Configuring search engine
+javamodel_configuring_classpath_containers=Configuring classpath containers
+javamodel_getting_build_state_number=Getting build state version number
+javamodel_configuring=Configuring {0}
+javamodel_building_after_upgrade=Triggering build after upgrade
+javamodel_refreshing_external_jars=Refreshing external archives
### access restrictions
restrictedAccess_project = The type {0} is not accessible due to restriction on required project {1}
restrictedAccess_library = The type {0} is not accessible due to restriction on required library {1}
+restrictedAccess_constructor_project = The constructor {0} is not accessible due to restriction on required project {1}
+restrictedAccess_constructor_library = The constructor {0} is not accessible due to restriction on required library {1}
+restrictedAccess_field_project = The field {0} from the type {1} is not accessible due to restriction on required project {2}
+restrictedAccess_field_library = The field {0} from the type {1} is not accessible due to restriction on required library {2}
+restrictedAccess_method_project = The method {0} from the type {1} is not accessible due to restriction on required project {2}
+restrictedAccess_method_library = The method {0} from the type {1} is not accessible due to restriction on required library {2}
### java conventions
convention_unit_nullName = Compilation unit name must not be null
-convention_unit_notJavaName = Compilation unit name must end with .java
+convention_unit_notJavaName = Compilation unit name must end with .java, or one of the registered Java-like extensions
convention_classFile_nullName = .class file name must not be null
convention_classFile_notClassFileName = .class file name must end with .class
convention_illegalIdentifier = ''{0}'' is not a valid Java identifier
@@ -219,6 +236,9 @@
dom_addNullInterface = Cannot add null interface
dom_nullInterfaces = Illegal to set super interfaces to null
+### import rewrite
+importRewrite_processDescription = Updating imports
+
### correction
correction_nullRequestor = Requestor cannot be null
correction_nullUnit = Compilation unit cannot be null
@@ -226,8 +246,8 @@
### Eclipse Java Core Search messages.
engine_searching = Searching...
-engine_searching_indexing = {0}: lookup indexes...
-engine_searching_matching = {0}: locate matches...
+engine_searching_indexing = Looking through {0} indexes...
+engine_searching_matching = Locating {0} matches...
exception_wrongFormat = Wrong format
process_name = Java indexing
manager_filesToIndex = {0} files to index
@@ -257,7 +277,9 @@
disassembler_outer_class_info_name = outer class info:
disassembler_inner_name = inner name:
disassembler_inner_accessflags = accessflags:\
-disassembler_genericattributeheader = Attribute: Name: {0} Length: {1}
+disassembler_genericattributeheader = Attribute: {0} Length: {1}
+disassembler_stackmaptableattributeheader = Stack map table: number of frames {0}
+disassembler_stackmapattributeheader = Stack map : number of frames {0}
disassembler_signatureattributeheader = // Signature: {0}
disassembler_indentation = \
disassembler_constantpoolindex =\ #
@@ -272,12 +294,12 @@
disassembler_constantpool_float = constant #{0} float: {1}
disassembler_constantpool_integer = constant #{0} integer: {1}
disassembler_constantpool_long = constant #{0} long: {1}
-disassembler_constantpool_string = constant #{0} string: #{1} {2}
+disassembler_constantpool_string = constant #{0} string: #{1} "{2}"
disassembler_constantpool_fieldref = constant #{0} field_ref: #{1}.#{2} {3}.{4} {5}
disassembler_constantpool_interfacemethodref = constant #{0} interface_method_ref: #{1}.#{2} {3}.{4} {5}
disassembler_constantpool_methodref = constant #{0} method_ref: #{1}.#{2} {3}.{4} {5}
disassembler_constantpool_name_and_type = constant #{0} name_and_type: #{1}.#{2} {3} {4}
-disassembler_constantpool_utf8 = constant #{0} utf8: {1}
+disassembler_constantpool_utf8 = constant #{0} utf8: "{1}"
disassembler_annotationdefaultheader = Annotation Default:\
disassembler_annotationdefaultvalue= {0} (constant type)
disassembler_annotationenumvalue = {2}.{3}(enum type #{0}.#{1})
@@ -293,7 +315,19 @@
disassembler_runtimevisibleparameterannotationsattributeheader= RuntimeVisibleParameterAnnotations:\
disassembler_runtimeinvisibleparameterannotationsattributeheader= RuntimeInvisibleParameterAnnotations:\
disassembler_parameterannotationentrystart=Number of annotations for parameter {0}: {1}
-
+disassembler_frame_same_locals_1_stack_item_extended=[pc: {0}, same_locals_1_stack_item_extended, stack: {1}]
+disassembler_frame_chop=[pc: {0}, chop {1} local(s)]
+disassembler_frame_same_frame_extended=[pc: {0}, same_extended]
+disassembler_frame_append=[pc: {0}, append: {1}]
+# {0} = offset delta
+# {1} = number of locals
+# {2} = locals
+# {3} = number of stack items
+# {4} = stack items
+# {5} = line separator + tabs
+disassembler_frame_full_frame=[pc: {0}, full, stack: {4}, locals: {2}]
+disassembler_frame_same_frame=[pc: {0}, same]
+disassembler_frame_same_locals_1_stack_item=[pc: {0}, same_locals_1_stack_item, stack: {1}]
### classfileformat decoding
classfileformat_versiondetails =\ (version {0} : {1}.{2}, {3})
classfileformat_methoddescriptor = // Method descriptor #{0} {1}
@@ -303,6 +337,7 @@
classfileformat_superflagisset = super bit
classfileformat_clinitname = '{'}
classformat_classformatexception = Class Format Exception
+classfileformat_versionUnknown = unknown
### string displayed for each opcode
classformat_anewarray = {0} {2} [{1}]
@@ -314,7 +349,7 @@
classformat_ldc_w_string = {0} <String "{2}"> [{1}]
classformat_ldc2_w_long = {0} <Long {2}> [{1}]
classformat_ldc2_w_double = {0} <Double {2}> [{1}]
-classformat_multianewarray = {0} {2}{3} [{1}]
+classformat_multianewarray = {0} {2} [{1}]
classformat_new = {0} {2} [{1}]
classformat_iinc = {0} {1} {2}{3}
classformat_invokespecial ={0} {2} [{1}]