### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core Index: search/org/eclipse/jdt/core/search/SearchDocument.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchDocument.java,v retrieving revision 1.16 diff -u -r1.16 SearchDocument.java --- search/org/eclipse/jdt/core/search/SearchDocument.java 20 Oct 2008 19:04:26 -0000 1.16 +++ search/org/eclipse/jdt/core/search/SearchDocument.java 4 Nov 2008 15:31:19 -0000 @@ -93,7 +93,11 @@ */ public abstract char[] getCharContents(); - private String getContainerRelativePath() { + /** + * @nooverride This method is not intended to be re-implemented or extended by clients. + * @noreference This method is not intended to be referenced by clients. + */ + protected String getContainerRelativePath() { if (this.containerRelativePath == null) this.containerRelativePath = this.index.containerRelativePath(getPath()); return this.containerRelativePath; Index: search/org/eclipse/jdt/internal/core/search/processing/JobManager.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/processing/JobManager.java,v retrieving revision 1.97 diff -u -r1.97 JobManager.java --- search/org/eclipse/jdt/internal/core/search/processing/JobManager.java 12 Sep 2008 13:17:49 -0000 1.97 +++ search/org/eclipse/jdt/internal/core/search/processing/JobManager.java 4 Nov 2008 15:31:20 -0000 @@ -17,10 +17,13 @@ public abstract class JobManager implements Runnable { - /* queue of jobs to execute */ - protected IJob[] awaitingJobs = new IJob[10]; - protected int jobStart = 0; - protected int jobEnd = -1; + /* queues of jobs to execute */ + public static final int HIGH_PRIORITY = 1; + public static final int LOW_PRIORITY = 0; + protected static final int MAX_PRIORITY = HIGH_PRIORITY; + protected IJob[][] awaitingJobs = new IJob[MAX_PRIORITY+1][10]; + protected int[] jobStart = new int[MAX_PRIORITY+1]; + protected int[] jobEnd = new int[MAX_PRIORITY+1]; protected boolean executing = false; /* background processing */ @@ -37,6 +40,13 @@ private int awaitingClients = 0; + public JobManager() { + for (int priorityIndex = 0; priorityIndex <= MAX_PRIORITY; priorityIndex++) { + this.jobStart[priorityIndex] = 0; + this.jobEnd[priorityIndex] = -1; + } + } + /** * Invoked exactly once, in background, before starting processing any job */ @@ -46,17 +56,52 @@ /** * Answer the amount of awaiting jobs. */ - public synchronized int awaitingJobsCount() { - // pretend busy in case concurrent job attempts performing before activated - return this.activated ? this.jobEnd - this.jobStart + 1 : 1; + public int awaitingJobsCount() { + return awaitingJobsCount(HIGH_PRIORITY); + } + + /** + * Answer the amount of awaiting jobs with a given priority (jobs with a lower priority are not considered). + */ + private synchronized int awaitingJobsCount(int maxPriority) { + if (!this.activated) { + // pretend busy in case concurrent job attempts performing before activated + return 1; + } + int count = 0; + for (int priorityIndex = 0; priorityIndex <= MAX_PRIORITY-maxPriority; priorityIndex++) { + int n = this.jobEnd[priorityIndex] - this.jobStart[priorityIndex] + 1; + if (VERBOSE) Util.verbose(" - jobs count for priority "+ (MAX_PRIORITY-priorityIndex) + " = " + n); //$NON-NLS-1$ //$NON-NLS-2$ + count += n; + } + return count; } /** * Answers the first job in the queue, or null if there is no job available * Until the job has completed, the job manager will keep answering the same job. */ - public synchronized IJob currentJob() { - if (this.enableCount > 0 && this.jobStart <= this.jobEnd) - return this.awaitingJobs[this.jobStart]; + public IJob currentJob() { + return currentJob(LOW_PRIORITY); + } + /** + * Answers the first job in the queue, or null if there is no job available + * Until the job has completed, the job manager will keep answering the same job. + */ + private synchronized IJob currentJob(int maxPriority) { + if (this.enableCount <= 0 || maxPriority < 0) + return null; + for (int priorityIndex = 0; priorityIndex <= MAX_PRIORITY-maxPriority; priorityIndex++) { + IJob job = currentJobForPriority(priorityIndex); + if (job != null) + return job; + } + return null; + } + + private IJob currentJobForPriority(int prorityIndex) { + int start = this.jobStart[prorityIndex]; + if (start <= this.jobEnd[prorityIndex]) + return this.awaitingJobs[prorityIndex][start]; return null; } public synchronized void disable() { @@ -65,86 +110,103 @@ Util.verbose("DISABLING background indexing"); //$NON-NLS-1$ } /** - * Remove the index from cache for a given project. + * Remove the jobs belonging to the given family. * Passing null as a job family discards them all. */ public void discardJobs(String jobFamily) { - if (VERBOSE) Util.verbose("DISCARD background job family - " + jobFamily); //$NON-NLS-1$ - - try { - IJob currentJob; - // cancel current job if it belongs to the given family - synchronized(this){ - currentJob = currentJob(); - disable(); - } - if (currentJob != null && (jobFamily == null || currentJob.belongsTo(jobFamily))) { - currentJob.cancel(); - - // wait until current active job has finished - while (this.processingThread != null && this.executing){ - try { - if (VERBOSE) - Util.verbose("-> waiting end of current background job - " + currentJob); //$NON-NLS-1$ - Thread.sleep(50); - } catch(InterruptedException e){ - // ignore - } + for (int priorityIndex = 0; priorityIndex <= MAX_PRIORITY; priorityIndex++) { + try { + IJob currentJob; + // cancel current job if it belongs to the given family + synchronized(this){ + currentJob = currentJobForPriority(priorityIndex); + disable(); } - } - - // flush and compact awaiting jobs - int loc = -1; - synchronized(this) { - for (int i = this.jobStart; i <= this.jobEnd; i++) { - currentJob = this.awaitingJobs[i]; - if (currentJob != null) { // sanity check - this.awaitingJobs[i] = null; - if (!(jobFamily == null || currentJob.belongsTo(jobFamily))) { // copy down, compacting - this.awaitingJobs[++loc] = currentJob; - } else { + if (currentJob != null && (jobFamily == null || currentJob.belongsTo(jobFamily))) { + currentJob.cancel(); + + // wait until current active job has finished + while (this.processingThread != null && this.executing){ + try { if (VERBOSE) - Util.verbose("-> discarding background job - " + currentJob); //$NON-NLS-1$ - currentJob.cancel(); + Util.verbose("-> waiting end of current background job - " + currentJob); //$NON-NLS-1$ + Thread.sleep(50); + } catch(InterruptedException e){ + // ignore + } + } + } + + // flush and compact awaiting jobs + int loc = -1; + synchronized(this) { + for (int i = this.jobStart[priorityIndex]; i <= this.jobEnd[priorityIndex]; i++) { + currentJob = this.awaitingJobs[priorityIndex][i]; + if (currentJob != null) { // sanity check + this.awaitingJobs[priorityIndex][i] = null; + if (!(jobFamily == null || currentJob.belongsTo(jobFamily))) { // copy down, compacting + this.awaitingJobs[priorityIndex][++loc] = currentJob; + } else { + if (VERBOSE) + Util.verbose("-> discarding background job - " + currentJob); //$NON-NLS-1$ + currentJob.cancel(); + } } } + this.jobStart[priorityIndex] = 0; + this.jobEnd[priorityIndex] = loc; } - this.jobStart = 0; - this.jobEnd = loc; + } finally { + enable(); } - } finally { - enable(); } if (VERBOSE) Util.verbose("DISCARD DONE with background job family - " + jobFamily); //$NON-NLS-1$ } + public synchronized void enable() { this.enableCount++; if (VERBOSE) Util.verbose("ENABLING background indexing"); //$NON-NLS-1$ notifyAll(); // wake up the background thread if it is waiting (context must be synchronized) } - protected synchronized boolean isJobWaiting(IJob request) { - for (int i = this.jobEnd; i > this.jobStart; i--) // don't check job at jobStart, as it may have already started - if (request.equals(this.awaitingJobs[i])) return true; + protected boolean isJobWaiting(IJob request) { + return isJobWaiting(request, HIGH_PRIORITY); + } + protected synchronized boolean isJobWaiting(IJob request, int maxPriority) { + for (int priorityIndex = 0; priorityIndex <= MAX_PRIORITY-maxPriority; priorityIndex++) { + for (int i = this.jobEnd[priorityIndex]; i > this.jobStart[priorityIndex]; i--) // don't check job at jobStart, as it may have already started + if (request.equals(this.awaitingJobs[priorityIndex][i])) + return true; + } return false; } /** * Advance to the next available job, once the current one has been completed. * Note: clients awaiting until the job count is zero are still waiting at this point. + * + * @return the priority of the moved job or a lower priority if there's no longer job in the queue */ - protected synchronized void moveToNextJob() { - //if (!enabled) return; - - if (this.jobStart <= this.jobEnd) { - this.awaitingJobs[this.jobStart++] = null; - if (this.jobStart > this.jobEnd) { - this.jobStart = 0; - this.jobEnd = -1; + protected synchronized int moveToNextJob() { + for (int priorityIndex=0; priorityIndex <= MAX_PRIORITY; priorityIndex++) { + if (this.jobStart[priorityIndex] <= this.jobEnd[priorityIndex]) { + int priority = MAX_PRIORITY - priorityIndex; + this.awaitingJobs[priorityIndex][this.jobStart[priorityIndex]++] = null; + if (this.jobStart[priorityIndex] > this.jobEnd[priorityIndex]) { + // no more job in this queue... + this.jobStart[priorityIndex] = 0; + this.jobEnd[priorityIndex] = -1; + // ... so, move to a lower priority + if (priority > LOW_PRIORITY) priority--; + } + if (VERBOSE) Util.verbose("Move to next job (priority="+(priority)+')'); //$NON-NLS-1$ + return priority; } } + // no job to move on, use the lowest priority + return LOW_PRIORITY; } /** * When idle, give chance to do something @@ -157,19 +219,25 @@ * Indeed since other jobs are performed in background, resource sharing might be * an issue.Therefore, this functionality allows a given job to be run without * colliding with background ones. + *
* Note: multiple thread might attempt to perform concurrent jobs at the same time, * and should synchronize (it is deliberately left to clients to decide whether * concurrent jobs might interfere or not. In general, multiple read jobs are ok). - * + *
* Waiting policy can be: - * IJobConstants.ForceImmediateSearch - * IJobConstants.CancelIfNotReadyToSearch - * IJobConstants.WaitUntilReadyToSearch - * + *
null
if source file
+ * cannot be found.
+ * The given simpleSourceFileName is the .java file name (without the enclosing
+ * folder) used to create the given type (e.g. "A.java" for x/y/A$Inner.class)
+ *
+ * @see #findSource(IType, String)
+ */
+ public String findSourceFilePath(IType type, String simpleSourceFileName) {
+ long time = 0;
+ if (VERBOSE) {
+ time = System.currentTimeMillis();
+ }
+ PackageFragment pkgFrag = (PackageFragment) type.getPackageFragment();
+ String name = org.eclipse.jdt.internal.core.util.Util.concatWith(pkgFrag.names, simpleSourceFileName, '/');
+
+ String sourceFilePath = null;
+
+ if (this.rootPath != null) {
+ sourceFilePath = findSourceFilePath(this.rootPath, name);
+ }
+
+ if (sourceFilePath == null) {
+ computeAllRootPaths(type);
+ if (this.rootPaths != null) {
+ loop: for (Iterator iterator = this.rootPaths.iterator(); iterator.hasNext(); ) {
+ String currentRootPath = (String) iterator.next();
+ if (!currentRootPath.equals(this.rootPath)) {
+ sourceFilePath = findSourceFilePath(currentRootPath, name);
+ if (sourceFilePath != null) {
+ // remember right root path
+ this.rootPath = currentRootPath;
+ break loop;
+ }
+ }
}
- } catch (CoreException e) {
- return null;
- } finally {
- manager.closeZipFile(zip); // handle null case
}
}
- return source;
+ if (VERBOSE) {
+ System.out.println("spent " + (System.currentTimeMillis() - time) + "ms for " + type.getElementName()); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ return sourceFilePath;
}
-
+ private String findSourceFilePath(String currentRootPath, String name) {
+ String newFullName;
+ if (!currentRootPath.equals(IPackageFragmentRoot.DEFAULT_PACKAGEROOT_PATH)) {
+ if (currentRootPath.endsWith("/")) { //$NON-NLS-1$
+ newFullName = currentRootPath + name;
+ } else {
+ newFullName = currentRootPath + '/' + name;
+ }
+ } else {
+ newFullName = name;
+ }
+ if (org.eclipse.jdt.internal.core.util.Util.findSource(this.sourcePath, newFullName, false/* do not get contents */) != null) {
+ return newFullName;
+ }
+ return null;
+ }
/**
* Returns the SourceRange for the name of the given element, or
@@ -1245,17 +1270,6 @@
this.typeDepth = -1;
}
}
- private char[] readSource(ZipEntry entry, ZipFile zip) {
- try {
- byte[] bytes = Util.getZipEntryByteContent(entry, zip);
- if (bytes != null) {
- return Util.bytesToChar(bytes, this.encoding);
- }
- } catch (IOException e) {
- // ignore
- }
- return null;
- }
/**
* Sets the mapping for this method to its parameter names.
Index: model/org/eclipse/jdt/internal/core/ClasspathChange.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathChange.java,v
retrieving revision 1.22
diff -u -r1.22 ClasspathChange.java
--- model/org/eclipse/jdt/internal/core/ClasspathChange.java 9 Oct 2008 08:13:07 -0000 1.22
+++ model/org/eclipse/jdt/internal/core/ClasspathChange.java 4 Nov 2008 15:31:18 -0000
@@ -457,6 +457,8 @@
int newLength = newResolvedClasspath.length;
int oldLength = this.oldResolvedClasspath.length;
+
+ // First, look at removed classpath entries
for (int i = 0; i < oldLength; i++) {
int index = classpathContains(newResolvedClasspath, this.oldResolvedClasspath[i]);
if (index == -1) {
@@ -487,20 +489,22 @@
}
}
+ // Then, look at created or changed classpath entries
for (int i = 0; i < newLength; i++) {
- int index = classpathContains(this.oldResolvedClasspath, newResolvedClasspath[i]);
+ IClasspathEntry entry = newResolvedClasspath[i];
+ int index = classpathContains(this.oldResolvedClasspath, entry);
if (index == -1) {
// remote projects are not indexed in this project
- if (newResolvedClasspath[i].getEntryKind() == IClasspathEntry.CPE_PROJECT){
+ if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT){
continue;
}
- // Request indexing
- int entryKind = newResolvedClasspath[i].getEntryKind();
+ // Request indexing for the removed classpath entry
+ int entryKind = entry.getEntryKind();
switch (entryKind) {
case IClasspathEntry.CPE_LIBRARY:
boolean pathHasChanged = true;
- IPath newPath = newResolvedClasspath[i].getPath();
+ IPath newPath = entry.getPath();
for (int j = 0; j < oldLength; j++) {
IClasspathEntry oldEntry = this.oldResolvedClasspath[j];
if (oldEntry.getPath().equals(newPath)) {
@@ -509,11 +513,10 @@
}
}
if (pathHasChanged) {
- indexManager.indexLibrary(newPath, this.project.getProject());
+ indexManager.indexLibrary(entry, this.project);
}
break;
case IClasspathEntry.CPE_SOURCE:
- IClasspathEntry entry = newResolvedClasspath[i];
IPath path = entry.getPath();
char[][] inclusionPatterns = ((ClasspathEntry)entry).fullInclusionPatternChars();
char[][] exclusionPatterns = ((ClasspathEntry)entry).fullExclusionPatternChars();
@@ -521,6 +524,18 @@
break;
}
}
+ // since bug 12044, source attached are indexed instead of class files
+ // hence needs to verify whether the source attachment has changed or not
+ else if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
+ IPath srcPath = entry.getSourceAttachmentPath();
+ IPath oldSrcPath = this.oldResolvedClasspath[index].getSourceAttachmentPath();
+ Util.verbose("Classpath entry src change from "+oldSrcPath+" to "+srcPath);
+ if (srcPath == null && oldSrcPath != null) {
+ indexManager.removeIndex(entry.getPath());
+ } else if (srcPath != null && !srcPath.equals(oldSrcPath)) {
+ indexManager.indexLibrary(entry, this.project);
+ }
+ }
}
}
Index: model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java,v
retrieving revision 1.133
diff -u -r1.133 PackageFragmentRoot.java
--- model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java 27 Jun 2008 16:03:50 -0000 1.133
+++ model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java 4 Nov 2008 15:31:18 -0000
@@ -573,7 +573,16 @@
*/
public IPath getSourceAttachmentPath() throws JavaModelException {
if (getKind() != K_BINARY) return null;
+ return sourceAttachmentPath();
+}
+/**
+ * @see IPackageFragmentRoot#getSourceAttachmentPath()
+ * Returns the same result but without opening the package fragment root.
+ * However, no verification is done on the package fragment root kind, hence
+ * provides an unpredictable result if it is not a {@link IPackageFragmentRoot#K_BINARY}.
+ */
+public IPath sourceAttachmentPath() throws JavaModelException {
// 1) look source attachment property (set iff attachSource(...) was called
IPath path = getPath();
String serverPathString= Util.getSourceAttachmentProperty(path);
@@ -618,7 +627,16 @@
*/
public IPath getSourceAttachmentRootPath() throws JavaModelException {
if (getKind() != K_BINARY) return null;
+ return sourceAttachmentRootPath();
+}
+/**
+ * @see IPackageFragmentRoot#getSourceAttachmentRootPath()
+ * Returns the same result but without opening the package fragment root.
+ * However, no verification is done on the package fragment root kind, hence
+ * provides an unpredictable result if it is not a {@link IPackageFragmentRoot#K_BINARY}.
+ */
+public IPath sourceAttachmentRootPath() throws JavaModelException {
// 1) look source attachment property (set iff attachSource(...) was called
IPath path = getPath();
String serverPathString= Util.getSourceAttachmentProperty(path);
Index: model/org/eclipse/jdt/internal/core/util/Util.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Util.java,v
retrieving revision 1.125
diff -u -r1.125 Util.java
--- model/org/eclipse/jdt/internal/core/util/Util.java 23 Oct 2008 13:56:41 -0000 1.125
+++ model/org/eclipse/jdt/internal/core/util/Util.java 4 Nov 2008 15:31:19 -0000
@@ -61,6 +61,7 @@
import org.eclipse.jdt.internal.core.Annotation;
import org.eclipse.jdt.internal.core.ClassFile;
import org.eclipse.jdt.internal.core.JavaElement;
+import org.eclipse.jdt.internal.core.JavaModel;
import org.eclipse.jdt.internal.core.JavaModelManager;
import org.eclipse.jdt.internal.core.Member;
import org.eclipse.jdt.internal.core.MemberValuePair;
@@ -725,6 +726,72 @@
return null;
}
+ /**
+ * Find source of the file name supposed to be located in the given source path or null
+ * if the corresponding file was not found.
+ *
+ * @param sourcePath The path of the container. May be a zip file or a folder
+ * @param fileName The full name of the file (e.g. java/lang/Object.java)
+ * @return The contents of the file or null
if the file was not found.
+ */
+ public static char[] findSource(IPath sourcePath, String fileName) {
+ return (char[]) findSource(sourcePath, fileName, true/*get contents*/);
+ }
+
+ /**
+ * Find the file supposed to be located in the given source path
+ * or null if the corresponding file was not found.
+ *
+ * @param sourcePath The path of the container. May be a zip file or a folder
+ * @param fileName The full name of the file (e.g. java/lang/Object.java)
+ * @param contents Indicates whether the method returns the file or its contents
+ * @return If the file was found then returns a {@link IResource} or a
+ * {@link ZipEntry} if no contents was required, char[]
otherwise.
+ * Returns null
if the file was not found.
+ */
+ public static Object findSource(IPath sourcePath, String fileName, boolean contents) {
+ Object target = JavaModel.getTarget(sourcePath, true);
+ if (target instanceof IContainer) {
+ IResource res = ((IContainer)target).findMember(fileName);
+ if (res instanceof IFile) {
+ if (contents) {
+ try {
+ return org.eclipse.jdt.internal.core.util.Util.getResourceContentsAsCharArray((IFile)res);
+ } catch (JavaModelException e) {
+ // skip
+ }
+ return null;
+ }
+ return res;
+ }
+ } else {
+ // try to get the entry
+ ZipEntry entry = null;
+ ZipFile zip = null;
+ JavaModelManager manager = JavaModelManager.getJavaModelManager();
+ try {
+ zip = manager.getZipFile(sourcePath);
+ entry = zip.getEntry(fileName);
+ if (entry != null) {
+ if (contents) {
+ try {
+ return org.eclipse.jdt.internal.compiler.util.Util.getZipEntryCharContent(entry, zip, null/*default charset encoding*/);
+ } catch (IOException e) {
+ // skip
+ }
+ return null;
+ }
+ return entry;
+ }
+ } catch (CoreException e) {
+ return null;
+ } finally {
+ manager.closeZipFile(zip); // handle null case
+ }
+ }
+ return null;
+ }
+
public static IClassFileAttribute getAttribute(IClassFileReader classFileReader, char[] attributeName) {
IClassFileAttribute[] attributes = classFileReader.getAttributes();
for (int i = 0, max = attributes.length; i < max; i++) {
Index: search/org/eclipse/jdt/internal/core/index/Index.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/Index.java,v
retrieving revision 1.31
diff -u -r1.31 Index.java
--- search/org/eclipse/jdt/internal/core/index/Index.java 27 Jun 2008 16:04:14 -0000 1.31
+++ search/org/eclipse/jdt/internal/core/index/Index.java 4 Nov 2008 15:31:19 -0000
@@ -172,6 +172,16 @@
public void remove(String containerRelativePath) {
this.memoryIndex.remove(containerRelativePath);
}
+/**
+ * Reset memory and disk indexes.
+ *
+ * @throws IOException
+ */
+public void reset(boolean reuseExistingFile) throws IOException {
+ this.memoryIndex = new MemoryIndex();
+ this.diskIndex = new DiskIndex(this.diskIndex.indexFile.getCanonicalPath());
+ this.diskIndex.initialize(reuseExistingFile);
+}
public void save() throws IOException {
// must own the write lock of the monitor
if (!hasChanged()) return;
Index: search/org/eclipse/jdt/internal/core/index/DiskIndex.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/DiskIndex.java,v
retrieving revision 1.67
diff -u -r1.67 DiskIndex.java
--- search/org/eclipse/jdt/internal/core/index/DiskIndex.java 27 Jun 2008 16:04:14 -0000 1.67
+++ search/org/eclipse/jdt/internal/core/index/DiskIndex.java 4 Nov 2008 15:31:19 -0000
@@ -46,7 +46,7 @@
private int streamEnd; // used when writing data from the streamBuffer to the file
char separator = Index.DEFAULT_SEPARATOR;
-public static final String SIGNATURE= "INDEX VERSION 1.125"; //$NON-NLS-1$
+public static final String SIGNATURE= "INDEX VERSION 1.126.1"; //$NON-NLS-1$
private static final char[] SIGNATURE_CHARS = SIGNATURE.toCharArray();
public static boolean DEBUG = false;
@@ -616,6 +616,7 @@
try {
if (size < 0) { // DEBUG
System.err.println("-------------------- DEBUG --------------------"); //$NON-NLS-1$
+ System.err.println("thread = "+Thread.currentThread()); //$NON-NLS-1$
System.err.println("file = "+this.indexFile); //$NON-NLS-1$
System.err.println("offset = "+offset); //$NON-NLS-1$
System.err.println("size = "+size); //$NON-NLS-1$
@@ -626,6 +627,7 @@
// DEBUG
oom.printStackTrace();
System.err.println("-------------------- DEBUG --------------------"); //$NON-NLS-1$
+ System.err.println("thread = "+Thread.currentThread()); //$NON-NLS-1$
System.err.println("file = "+this.indexFile); //$NON-NLS-1$
System.err.println("offset = "+offset); //$NON-NLS-1$
System.err.println("size = "+size); //$NON-NLS-1$
Index: search/org/eclipse/jdt/internal/core/search/JavaSearchDocument.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaSearchDocument.java,v
retrieving revision 1.16
diff -u -r1.16 JavaSearchDocument.java
--- search/org/eclipse/jdt/internal/core/search/JavaSearchDocument.java 27 Jun 2008 16:04:09 -0000 1.16
+++ search/org/eclipse/jdt/internal/core/search/JavaSearchDocument.java 4 Nov 2008 15:31:20 -0000
@@ -16,9 +16,13 @@
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.core.search.SearchDocument;
import org.eclipse.jdt.core.search.SearchParticipant;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
+import org.eclipse.jdt.internal.core.search.indexing.IIndexConstants;
import org.eclipse.jdt.internal.core.search.processing.JobManager;
import org.eclipse.jdt.internal.core.util.Util;
@@ -27,6 +31,10 @@
private IFile file;
protected byte[] byteContents;
protected char[] charContents;
+ public IPath sourcePath; // path of the folder or the zip file containing the attached source
+ private String relativeSourcePath; // relative path from the source path
+ private String containerRelativePath; // same as SearchDocument
+ public ClassFileReader classFileReader; // may be set by by the AddJarFileToIndex
public JavaSearchDocument(String documentPath, SearchParticipant participant) {
super(documentPath, participant);
@@ -35,9 +43,15 @@
super(zipFilePath + IJavaSearchScope.JAR_FILE_ENTRY_SEPARATOR + zipEntry.getName(), participant);
this.byteContents = contents;
}
+ public JavaSearchDocument(String documentPath, IPath sourcePath, String filePath, SearchParticipant participant) {
+ this(documentPath, participant);
+ this.relativeSourcePath = filePath;
+ this.sourcePath = sourcePath;
+ }
public byte[] getByteContents() {
if (this.byteContents != null) return this.byteContents;
+ if (this.sourcePath != null) return null;
try {
return Util.getResourceContentsAsByteArray(getFile());
} catch (JavaModelException e) {
@@ -49,14 +63,21 @@
}
public char[] getCharContents() {
if (this.charContents != null) return this.charContents;
+
+ // The source may be found through an attachment
+ if (this.sourcePath != null) {
+ return Util.findSource(this.sourcePath, this.relativeSourcePath);
+ }
+
+ // Get file contents
try {
return Util.getResourceContentsAsCharArray(getFile());
} catch (JavaModelException e) {
if (BasicSearchEngine.VERBOSE || JobManager.VERBOSE) { // used during search and during indexing
e.printStackTrace();
}
- return null;
}
+ return null;
}
public String getEncoding() {
// Return the encoding of the associated file
@@ -83,4 +104,90 @@
public String toString() {
return "SearchDocument for " + getPath(); //$NON-NLS-1$
}
+
+ /**
+ * Override the super implementation to change the document path
+ * if there's an attached source and the enclosing type names
+ *
+ * @see SearchDocument#addIndexEntry(char[], char[])
+ */
+ public void addIndexEntry(char[] category, char[] key) {
+ this.containerRelativePath = null;
+ if (this.sourcePath != null) {
+ switch (category[0]) {
+ case 's':
+ if (CharOperation.equals(IIndexConstants.SUPER_REF, category)) {
+ // decode the key to get enclosing type names (see SuperTypeReferencePattern.decodeIndexKey(char[])
+ int slash = CharOperation.indexOf(IIndexConstants.SEPARATOR, key);
+ slash = CharOperation.indexOf(IIndexConstants.SEPARATOR, key, slash+1);
+ slash = CharOperation.indexOf(IIndexConstants.SEPARATOR, key, slash+1);
+ if (key[slash+1] != IIndexConstants.SEPARATOR) {
+ // there's enclosing types
+ int end = CharOperation.indexOf(IIndexConstants.SEPARATOR, key, slash+1);
+ String relativePath = getContainerRelativePath();
+ char[] enclosingTypes = CharOperation.subarray(key, slash+1, end);
+ int length = enclosingTypes.length;
+ if (length != 1 || enclosingTypes[length-1] != '0') {
+ // neither an anonymous nor a local type
+ this.containerRelativePath = relativePath.substring(0, relativePath.length()-SuffixConstants.SUFFIX_STRING_class.length())
+ + '$' + new String(enclosingTypes) + SuffixConstants.SUFFIX_STRING_class;
+ }
+ }
+ }
+ break;
+ case 't':
+ if (CharOperation.equals(IIndexConstants.TYPE_DECL, category)) {
+ // decode the key to get enclosing type names (see TypeDeclarationPattern.decodeIndexKey(char[])
+ int end = key.length-1;
+ if (key[end] == 'S') {
+ end -= 2;
+ }
+ end -= 3;
+ if (key[end] != IIndexConstants.SEPARATOR) {
+ // there's enclosing types
+ int slash = CharOperation.lastIndexOf(IIndexConstants.SEPARATOR, key, 0, end);
+ String relativePath = getContainerRelativePath();
+ char[] enclosingTypes = CharOperation.subarray(key, slash+1, end);
+ int length = enclosingTypes.length;
+ if (length != 1 || enclosingTypes[length-1] != '0') {
+ // neither an anonymous nor a local type
+ this.containerRelativePath = relativePath.substring(0, relativePath.length()-SuffixConstants.SUFFIX_STRING_class.length())
+ + '$' + new String(enclosingTypes) + SuffixConstants.SUFFIX_STRING_class;
+ }
+ }
+ }
+ break;
+ }
+ }
+ super.addIndexEntry(category, key);
+ }
+
+ /**
+ * Override the super implementation to take the changed document relative path
+ * if any. Reset this relative path to avoid any unwanted side effect.
+ *
+ * @see SearchDocument#getContainerRelativePath()
+ */
+ protected String getContainerRelativePath() {
+ if (this.containerRelativePath == null) {
+ return super.getContainerRelativePath();
+ }
+ String path = this.containerRelativePath;
+ this.containerRelativePath = null;
+ return path;
+ }
+
+ /**
+ * Override the super implementation not to remove all entries when there's an
+ * attached source. Attached source indexing is not complete, hence previous
+ * entries set by the binary indexer need to be kept.
+ *
+ * @see SearchDocument#removeAllIndexEntries()
+ */
+ public void removeAllIndexEntries() {
+ if (this.sourcePath != null) {
+ return;
+ }
+ super.removeAllIndexEntries();
+ }
}
Index: search/org/eclipse/jdt/internal/core/search/BasicSearchEngine.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/BasicSearchEngine.java,v
retrieving revision 1.57
diff -u -r1.57 BasicSearchEngine.java
--- search/org/eclipse/jdt/internal/core/search/BasicSearchEngine.java 31 Oct 2008 16:53:33 -0000 1.57
+++ search/org/eclipse/jdt/internal/core/search/BasicSearchEngine.java 4 Nov 2008 15:31:20 -0000
@@ -30,6 +30,7 @@
import org.eclipse.jdt.internal.core.*;
import org.eclipse.jdt.internal.core.search.indexing.*;
import org.eclipse.jdt.internal.core.search.matching.*;
+import org.eclipse.jdt.internal.core.search.processing.JobManager;
import org.eclipse.jdt.internal.core.util.Messages;
import org.eclipse.jdt.internal.core.util.Util;
@@ -206,6 +207,7 @@
indexManager.performConcurrentJob(
new PatternSearchJob(pattern, participant, scope, pathCollector),
IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH,
+ JobManager.LOW_PRIORITY, // any search will wait for attached sources indexing to be finished
monitor==null ? null : new SubProgressMonitor(monitor, 50));
if (monitor != null && monitor.isCanceled()) throw new OperationCanceledException();
Index: compiler/org/eclipse/jdt/internal/compiler/util/Util.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Util.java,v
retrieving revision 1.68
diff -u -r1.68 Util.java
--- compiler/org/eclipse/jdt/internal/compiler/util/Util.java 27 Jun 2008 16:04:05 -0000 1.68
+++ compiler/org/eclipse/jdt/internal/compiler/util/Util.java 4 Nov 2008 15:31:18 -0000
@@ -22,6 +22,9 @@
import java.util.StringTokenizer;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
+
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ClassFile;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
@@ -450,10 +453,9 @@
}
/**
* Returns the contents of the given zip entry as a byte array.
- * @throws IOException if a problem occured reading the zip entry.
+ * @throws IOException if a problem occurred reading the zip entry.
*/
- public static byte[] getZipEntryByteContent(ZipEntry ze, ZipFile zip)
- throws IOException {
+ public static byte[] getZipEntryByteContent(ZipEntry ze, ZipFile zip) throws IOException {
InputStream stream = null;
try {
@@ -470,6 +472,26 @@
}
}
}
+ /**
+ * Returns the contents of the given zip entry as a char array.
+ * @throws IOException if a problem occurred reading the zip entry or while
+ * converting the bytes array to chars.
+ */
+ public static char[] getZipEntryCharContent(ZipEntry entry, ZipFile zip, String encoding) throws IOException {
+ byte[] bytes = getZipEntryByteContent(entry, zip);
+ if (bytes != null) {
+ String charEncoding = encoding;
+ try {
+ if (encoding == null) {
+ charEncoding = ResourcesPlugin.getWorkspace().getRoot().getDefaultCharset();
+ }
+ } catch (CoreException e) {
+ // use no encoding
+ }
+ return bytesToChar(bytes, charEncoding);
+ }
+ return null;
+ }
/**
* Returns whether the given name is potentially a zip archive file name
Index: search/org/eclipse/jdt/internal/core/search/indexing/AddSourceZipToIndex.java
===================================================================
RCS file: search/org/eclipse/jdt/internal/core/search/indexing/AddSourceZipToIndex.java
diff -N search/org/eclipse/jdt/internal/core/search/indexing/AddSourceZipToIndex.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ search/org/eclipse/jdt/internal/core/search/indexing/AddSourceZipToIndex.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,185 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and 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.search.indexing;
+
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Path;
+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.JavaModelException;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.search.IJavaSearchScope;
+import org.eclipse.jdt.core.search.SearchEngine;
+import org.eclipse.jdt.core.search.SearchParticipant;
+import org.eclipse.jdt.internal.compiler.SourceElementParser;
+import org.eclipse.jdt.internal.core.JavaModelManager;
+import org.eclipse.jdt.internal.core.PackageFragmentRoot;
+import org.eclipse.jdt.internal.core.SourceMapper;
+import org.eclipse.jdt.internal.core.index.Index;
+import org.eclipse.jdt.internal.core.search.JavaSearchDocument;
+import org.eclipse.jdt.internal.core.search.processing.JobManager;
+import org.eclipse.jdt.internal.core.util.HashtableOfArrayToObject;
+
+class AddSourceZipToIndex extends IndexRequest {
+
+ private static final char JAR_SEPARATOR = IJavaSearchScope.JAR_FILE_ENTRY_SEPARATOR.charAt(0);
+ SourceMapper sourceMapper;
+ IPath sourcePath;
+ Map sources;
+ IPackageFragmentRoot packageFragmentRoot;
+ private HashtableOfArrayToObject packageHandles = new HashtableOfArrayToObject();
+ IPath zipFilePath;
+ private IJavaProject javaProject;
+
+public AddSourceZipToIndex(AddJarFileToIndex jarFileToIndex, IPath zipPath, Map sources) {
+ // external JAR scenario - no resource
+ super(jarFileToIndex.containerPath, jarFileToIndex.manager);
+ this.sourcePath = jarFileToIndex.sourcePath;
+ this.sources = sources;
+ this.zipFilePath = zipPath;
+ this.sourceMapper = jarFileToIndex.sourceMapper;
+ this.packageFragmentRoot = jarFileToIndex.packageFragmentRoot;
+ this.javaProject = jarFileToIndex.javaProject;
+}
+
+private IType createType(String classFilePath) throws JavaModelException {
+ String[] simpleNames = new Path(classFilePath).segments();
+ String[] pkgName;
+ int length = simpleNames.length-1;
+ if (length > 0) {
+ pkgName = new String[length];
+ System.arraycopy(simpleNames, 0, pkgName, 0, length);
+ } else {
+ pkgName = CharOperation.NO_STRINGS;
+ }
+ IPackageFragment pkgFragment= (IPackageFragment) this.packageHandles.get(pkgName);
+ if (pkgFragment == null) {
+ pkgFragment= ((PackageFragmentRoot)this.packageFragmentRoot).getPackageFragment(pkgName);
+ this.packageHandles.put(pkgName, pkgFragment);
+ }
+ return pkgFragment.getClassFile(simpleNames[length]).getType();
+}
+
+public boolean equals(Object o) {
+ if (o instanceof AddSourceZipToIndex) {
+ if (this.sourcePath != null) {
+ return this.sourcePath.toOSString().equals(((AddSourceZipToIndex) o).sourcePath.toOSString());
+ }
+ }
+ return false;
+}
+public int hashCode() {
+ if (this.sourcePath != null)
+ return this.sourcePath.hashCode();
+ return -1;
+}
+public boolean execute(IProgressMonitor progressMonitor) {
+
+ if (this.isCancelled || progressMonitor != null && progressMonitor.isCanceled()) return true;
+ boolean verbose = true; //JobManager.VERBOSE;
+
+ try {
+ // always reuse existing index as there's no way to know whether sources has changed or not...
+ Index index = this.manager.getIndexForUpdate(this.containerPath, true, /*reuse index file*/ true /*create if none*/);
+ if (index == null) {
+ if (verbose)
+ org.eclipse.jdt.internal.core.util.Util.verbose("-> index could not be created for sources in " + this.containerPath); //$NON-NLS-1$
+ return true;
+ }
+ ReadWriteMonitor monitor = index.monitor;
+ if (monitor == null) {
+ if (verbose)
+ org.eclipse.jdt.internal.core.util.Util.verbose("-> index for sources in " + this.containerPath + " just got deleted"); //$NON-NLS-1$//$NON-NLS-2$
+ return true; // index got deleted since acquired
+ }
+ index.separator = JAR_SEPARATOR;
+
+ JavaModelManager modelManager = JavaModelManager.getJavaModelManager();
+ SourceElementParser parser = this.manager.getSourceElementParser(this.javaProject, null/*requestor will be set by indexer*/);
+ modelManager.cacheZipFiles();
+ try {
+ monitor.enterWrite(); // ask permission to write (TODO see if this lock is necessary)
+ if (this.isCancelled) {
+ if (verbose)
+ org.eclipse.jdt.internal.core.util.Util.verbose("-> indexing source files in " + this.sourcePath.toString() + " has been cancelled"); //$NON-NLS-1$ //$NON-NLS-2$
+ return false;
+ }
+
+ if (verbose)
+ org.eclipse.jdt.internal.core.util.Util.verbose("-> indexing source files in " + this.sourcePath.toString()); //$NON-NLS-1$
+ long initialTime = System.currentTimeMillis();
+
+ // Index the jar for the first time or reindex the jar in case the previous index file has been corrupted
+ // index already existed: recreate it so that we forget about previous entries
+ SearchParticipant participant = SearchEngine.getDefaultSearchParticipant();
+ index.separator = JAR_SEPARATOR;
+
+ // Index each attached source of the list
+ Iterator classFileNames = this.sources.keySet().iterator();
+ String documentPrefix = this.zipFilePath.toString() + IJavaSearchScope.JAR_FILE_ENTRY_SEPARATOR;
+ while (classFileNames.hasNext()) {
+ String classFileName = (String) classFileNames.next();
+ String sourceName = (String) this.sources.get(classFileName);
+
+ // first get type
+ IType type = null;
+ try {
+ if (this.packageFragmentRoot != null) {
+ type = createType(classFileName);
+ }
+ } catch (JavaModelException jme) {
+ // ignore
+ }
+ if (type != null) {
+ // get path of the attached source file
+ String sourceFilePath = this.sourceMapper.findSourceFilePath(type, sourceName);
+ if (sourceFilePath != null) {
+ // index the document using the top level class file for its name
+ String documentPath = documentPrefix + classFileName;
+ JavaSearchDocument searchDocument = new JavaSearchDocument(documentPath, this.sourcePath, sourceFilePath, participant);
+ searchDocument.setParser(parser);
+ this.manager.indexDocument(searchDocument, participant, index, this.containerPath);
+ }
+ }
+ }
+ this.manager.saveIndex(index);
+ if (verbose)
+ org.eclipse.jdt.internal.core.util.Util.verbose("-> done indexing source files of " //$NON-NLS-1$
+ + this.sourcePath.toString() + " (" //$NON-NLS-1$
+ + (System.currentTimeMillis() - initialTime) + "ms)"); //$NON-NLS-1$
+ } finally {
+ modelManager.flushZipFiles();
+ monitor.exitWrite(); // free write lock
+ }
+ } catch (IOException e) {
+ if (verbose) {
+ org.eclipse.jdt.internal.core.util.Util.verbose("-> failed to index sources in " + this.containerPath + " because of the following exception:"); //$NON-NLS-1$ //$NON-NLS-2$
+ e.printStackTrace();
+ }
+ this.manager.removeIndex(this.containerPath);
+ return false;
+ }
+ return true;
+}
+protected Integer updatedIndexState() {
+ return IndexManager.REBUILDING_STATE;
+}
+public String toString() {
+ return "indexing " + this.sourcePath.toString(); //$NON-NLS-1$
+}
+}
Index: search/org/eclipse/jdt/internal/core/search/indexing/AttachedSourceIndexerRequestor.java
===================================================================
RCS file: search/org/eclipse/jdt/internal/core/search/indexing/AttachedSourceIndexerRequestor.java
diff -N search/org/eclipse/jdt/internal/core/search/indexing/AttachedSourceIndexerRequestor.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ search/org/eclipse/jdt/internal/core/search/indexing/AttachedSourceIndexerRequestor.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,144 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and 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.search.indexing;
+
+import org.eclipse.jdt.core.compiler.CategorizedProblem;
+import org.eclipse.jdt.internal.compiler.ISourceElementRequestor;
+import org.eclipse.jdt.internal.compiler.ast.Expression;
+import org.eclipse.jdt.internal.compiler.ast.ImportReference;
+
+/**
+ * This class is used by the JavaParserIndexer. When parsing the java file, the requestor
+ * recognizes the java elements (methods, fields, ...) and add them to an index.
+ */
+public class AttachedSourceIndexerRequestor implements ISourceElementRequestor, IIndexConstants {
+ SourceIndexer indexer;
+
+public AttachedSourceIndexerRequestor(SourceIndexer indexer) {
+ this.indexer = indexer;
+}
+/**
+ * @see ISourceElementRequestor#acceptAnnotationTypeReference(char[][], int, int)
+ */
+public void acceptAnnotationTypeReference(char[][] typeName, int sourceStart, int sourceEnd) {
+ // already done while indexing the associated class file
+}
+/**
+ * @see ISourceElementRequestor#acceptAnnotationTypeReference(char[], int)
+ */
+public void acceptAnnotationTypeReference(char[] simpleTypeName, int sourcePosition) {
+ // already done while indexing the associated class file
+}
+/**
+ * @see ISourceElementRequestor#acceptConstructorReference(char[], int, int)
+ */
+public void acceptConstructorReference(char[] typeName, int argCount, int sourcePosition) {
+ // already done while indexing the associated class file
+}
+/**
+ * @see ISourceElementRequestor#acceptFieldReference(char[], int)
+ */
+public void acceptFieldReference(char[] fieldName, int sourcePosition) {
+ this.indexer.addFieldReference(fieldName);
+}
+/**
+ * @see ISourceElementRequestor#acceptImport(int, int, char[][], boolean, int)
+ */
+public void acceptImport(int declarationStart, int declarationEnd, char[][] tokens, boolean onDemand, int modifiers) {
+ // already done while indexing the associated class file
+}
+/**
+ * @see ISourceElementRequestor#acceptLineSeparatorPositions(int[])
+ */
+public void acceptLineSeparatorPositions(int[] positions) {
+ // already done while indexing the associated class file
+}
+/**
+ * @see ISourceElementRequestor#acceptMethodReference(char[], int, int)
+ */
+public void acceptMethodReference(char[] methodName, int argCount, int sourcePosition) {
+ // already done while indexing the associated class file
+}
+/**
+ * @see ISourceElementRequestor#acceptPackage(ImportReference)
+ */
+public void acceptPackage(ImportReference importReference) {
+ // already done while indexing the associated class file
+}
+/**
+ * @see ISourceElementRequestor#acceptProblem(CategorizedProblem)
+ */
+public void acceptProblem(CategorizedProblem problem) {
+ // already done while indexing the associated class file
+}
+/**
+ * @see ISourceElementRequestor#acceptTypeReference(char[][], int, int)
+ */
+public void acceptTypeReference(char[][] typeName, int sourceStart, int sourceEnd) {
+ // already done while indexing the associated class file
+}
+/**
+ * @see ISourceElementRequestor#acceptTypeReference(char[], int)
+ */
+public void acceptTypeReference(char[] simpleTypeName, int sourcePosition) {
+ // already done while indexing the associated class file
+}
+/**
+ * @see ISourceElementRequestor#acceptUnknownReference(char[][], int, int)
+ */
+public void acceptUnknownReference(char[][] name, int sourceStart, int sourceEnd) {
+ for (int i = 0; i < name.length; i++) {
+ this.indexer.addNameReference(name[i]);
+ }
+}
+/**
+ * @see ISourceElementRequestor#acceptUnknownReference(char[], int)
+ */
+public void acceptUnknownReference(char[] name, int sourcePosition) {
+ this.indexer.addNameReference(name);
+}
+public void enterCompilationUnit() {
+ // do nothing
+}
+public void enterConstructor(MethodInfo methodInfo) {
+ // do nothing
+}
+public void enterField(FieldInfo fieldInfo) {
+ // do nothing
+}
+public void enterInitializer(int declarationStart, int modifiers) {
+ // do nothing
+}
+public void enterMethod(MethodInfo methodInfo) {
+ // do nothing
+}
+public void enterType(TypeInfo typeInfo) {
+ // do nothing
+}
+public void exitCompilationUnit(int declarationEnd) {
+ // do nothing
+}
+public void exitConstructor(int declarationEnd) {
+ // do nothing
+}
+public void exitField(int initializationStart, int declarationEnd, int declarationSourceEnd) {
+ // do nothing
+}
+public void exitInitializer(int declarationEnd) {
+ // do nothing
+}
+public void exitMethod(int declarationEnd, Expression defaultValue) {
+ // do nothing
+}
+public void exitType(int declarationEnd) {
+ // do nothing
+}
+}
#P org.eclipse.jdt.core.tests.model
Index: src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java,v
retrieving revision 1.227
diff -u -r1.227 AbstractJavaModelTests.java
--- src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java 23 Oct 2008 13:56:38 -0000 1.227
+++ src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java 4 Nov 2008 15:31:22 -0000
@@ -436,8 +436,11 @@
protected void addLibraryEntry(String path, boolean exported) throws JavaModelException {
addLibraryEntry(this.currentProject, new Path(path), null, null, null, null, exported);
}
+ protected void addLibraryEntry(IJavaProject project, String path) throws JavaModelException {
+ addLibraryEntry(project, new Path(path), null, null, null, null, false);
+ }
protected void addLibraryEntry(IJavaProject project, String path, boolean exported) throws JavaModelException {
- addLibraryEntry(project, new Path(path), exported);
+ addLibraryEntry(project, new Path(path), null, null, null, null, exported);
}
protected void addLibraryEntry(IJavaProject project, IPath path, boolean exported) throws JavaModelException {
addLibraryEntry(project, path, null, null, null, null, exported);
@@ -2872,4 +2875,24 @@
} catch (CoreException e) {
}
}
+
+ /**
+ * Following method might be carefully used while debugging tests when it's necessary
+ * to be sure that all indexing jobs are finished (including low priority ones)
+ * @deprecated To get a warning when used...
+ */
+ public static void waitUntilAllIndexesReady() {
+ // dummy query for waiting until the indexes are ready
+ SearchEngine engine = new SearchEngine();
+ IJavaSearchScope scope = SearchEngine.createWorkspaceScope();
+ try {
+ SearchPattern pattern = SearchPattern.createPattern("!@$#!@", IJavaSearchConstants.FIELD, IJavaSearchConstants.REFERENCES, SearchPattern.R_EXACT_MATCH);
+ SearchRequestor requestor = new SearchRequestor() {
+ public void acceptSearchMatch(SearchMatch match) throws CoreException {
+ }
+ };
+ engine.search(pattern, new SearchParticipant[] { SearchEngine.getDefaultSearchParticipant() }, scope, requestor, null);
+ } catch (CoreException e) {
+ }
+ }
}
Index: src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests.java
===================================================================
RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests.java,v
retrieving revision 1.162
diff -u -r1.162 JavaSearchBugsTests.java
--- src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests.java 23 Oct 2008 17:39:32 -0000 1.162
+++ src/org/eclipse/jdt/core/tests/model/JavaSearchBugsTests.java 4 Nov 2008 15:31:23 -0000
@@ -130,6 +130,191 @@
}
/**
+ * @bug 12044: [search] Reference to package is not found in qualified annotation
+ * @test Ensure that references to package are also found in qualified annotation
+ * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=12044"
+ */
+private String[] sourcesBug12044() throws CoreException {
+ return new String[] {
+ "Def.java",
+ "public class Def {\n" +
+ " public static final int ONE = 1;\n" +
+ " public static final int TWO = 2;\n" +
+ " public static final int THREE = 3;\n" +
+ "}\n",
+ "Ref.java",
+ "public class Ref {\n" +
+ " class Sub {\n" +
+ " int x = Def.ONE;\n" +
+ " int getX() {\n" +
+ " return x;\n" +
+ " }\n" +
+ " }\n" +
+ " void foo(Sub sub) {\n" +
+ " switch (sub.getX()) {\n" +
+ " case Def.ONE:\n" +
+ " break;\n" +
+ " case Def.TWO:\n" +
+ " break;\n" +
+ " case Def.THREE:\n" +
+ " break;\n" +
+ " }\n" +
+ " }\n" +
+ "}\n"
+ };
+}
+//static { TESTS_PREFIX = "testBug12044"; }
+public void testBug12044_no_src() throws CoreException, IOException {
+ IJavaProject javaProject = null;
+ try {
+ javaProject = createJavaProject("b012044", new String[] { "src" }, new String[] {"JCL15_LIB" }, "bin", "1.5");
+ String jarPath = getWorkspacePath()+"b012044"+File.separator+"b012044.jar";
+ createJar(sourcesBug12044(), jarPath);
+ refresh(javaProject);
+ String resourcePath = "/b012044/b012044.jar";
+ addLibraryEntry(javaProject, resourcePath);
+ IClassFile classFile = getClassFile("b012044", resourcePath, "", "Def.class");
+ IField field = classFile.getType().getField("ONE");
+ IJavaSearchScope scope = SearchEngine.createJavaSearchScope(new IJavaElement[] { javaProject } );
+ this.resultCollector.showJarFile();
+ search(field, ALL_OCCURRENCES, scope);
+ assertSearchResults(
+ "b012044.jar|Def.class Def.ONE [No source] EXACT_MATCH"
+ );
+ }
+ finally {
+ if (javaProject != null) {
+ deleteProject(javaProject);
+ }
+ }
+}
+// jar with sources inside
+public void testBug12044_src_in_jar() throws CoreException, IOException {
+ IJavaProject javaProject = null;
+ try {
+ javaProject = createJavaProject("b012044", new String[] { "src" }, new String[] {"JCL15_LIB" }, "bin", "1.5");
+ String path = getWorkspacePath()+"b012044"+File.separator+"b012044";
+ String jarPath = path+".jar";
+ Util.createJar(sourcesBug12044(), null, jarPath, null/*no classpath*/, "1.4", true/*include sources*/);
+ refresh(javaProject);
+ String resourcePath = "/b012044/b012044.jar";
+ addLibraryEntry(javaProject, resourcePath);
+ IClassFile classFile = getClassFile("b012044", resourcePath, "", "Def.class");
+ IField field = classFile.getType().getField("ONE");
+ IJavaSearchScope scope = SearchEngine.createJavaSearchScope(new IJavaElement[] { javaProject } );
+ this.resultCollector.showJarFile();
+ search(field, ALL_OCCURRENCES, scope);
+ assertSearchResults(
+ "b012044.jar|Def.class Def.ONE EXACT_MATCH\n" +
+ "b012044.jar|Ref.class void Ref.foo(Ref.Sub) EXACT_MATCH\n" +
+ "b012044.jar|Ref$Sub.class Ref$Sub.x EXACT_MATCH"
+ );
+ }
+ finally {
+ if (javaProject != null) {
+ deleteProject(javaProject);
+ }
+ }
+}
+// jar with sources in another zip file
+public void testBug12044_src_in_zip() throws CoreException, IOException {
+ IJavaProject javaProject = null;
+ try {
+ javaProject = createJavaProject("b012044", new String[] { "src" }, new String[] {"JCL15_LIB" }, "bin", "1.5");
+ String path = getWorkspacePath()+"b012044"+File.separator+"b012044";
+ String jarPath = path+".jar";
+ createJar(sourcesBug12044(), jarPath);
+ String zipPath = path+".zip";
+ Util.createSourceZip(sourcesBug12044(), zipPath);
+ refresh(javaProject);
+ String resourcePath = "/b012044/b012044.jar";
+ String resourceZipPath = "/b012044/b012044.zip";
+ addLibraryEntry(javaProject, resourcePath, resourceZipPath);
+ IClassFile classFile = getClassFile("b012044", resourcePath, "", "Def.class");
+ IField field = classFile.getType().getField("ONE");
+ IJavaSearchScope scope = SearchEngine.createJavaSearchScope(new IJavaElement[] { javaProject } );
+ this.resultCollector.showJarFile();
+ search(field, ALL_OCCURRENCES, scope);
+ assertSearchResults(
+ "b012044.jar|Def.class Def.ONE EXACT_MATCH\n" +
+ "b012044.jar|Ref.class void Ref.foo(Ref.Sub) EXACT_MATCH\n" +
+ "b012044.jar|Ref$Sub.class Ref$Sub.x EXACT_MATCH"
+ );
+ }
+ finally {
+ if (javaProject != null) {
+ deleteProject(javaProject);
+ }
+ }
+}
+public void testBug12044_src_in_zip_string_pattern() throws CoreException, IOException {
+ IJavaProject javaProject = null;
+ try {
+ javaProject = createJavaProject("b012044", new String[] { "src" }, new String[] {"JCL15_LIB" }, "bin", "1.5");
+ String path = getWorkspacePath()+"b012044"+File.separator+"b012044";
+ String jarPath = path+".jar";
+ createJar(sourcesBug12044(), jarPath);
+ String zipPath = path+".zip";
+ Util.createSourceZip(sourcesBug12044(), zipPath);
+ refresh(javaProject);
+ String resourcePath = "/b012044/b012044.jar";
+ String resourceZipPath = "/b012044/b012044.zip";
+ addLibraryEntry(javaProject, resourcePath, resourceZipPath);
+ IJavaSearchScope scope = SearchEngine.createJavaSearchScope(new IJavaElement[] { javaProject } );
+ this.resultCollector.showJarFile();
+ search("ONE", FIELD, ALL_OCCURRENCES, scope);
+ assertSearchResults(
+ "b012044.jar|Def.class Def.ONE EXACT_MATCH\n" +
+ "b012044.jar|Ref.class void Ref.foo(Ref.Sub) EXACT_MATCH\n" +
+ "b012044.jar|Ref$Sub.class Ref$Sub.x EXACT_MATCH"
+ );
+ }
+ finally {
+ if (javaProject != null) {
+ deleteProject(javaProject);
+ }
+ }
+}
+// jar with sources in a folder
+public void testBug12044_src_in_folder() throws CoreException, IOException {
+ IJavaProject javaProject = null, javaProjectBis = null;
+ try {
+ javaProject = createJavaProject("b012044", new String[] { "src" }, new String[] {"JCL15_LIB" }, "bin", "1.5");
+ String[] sources = sourcesBug12044();
+ for (int i=0; i