### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core Index: model/org/eclipse/jdt/internal/core/ChangeClasspathOperation.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ChangeClasspathOperation.java,v retrieving revision 1.5 diff -u -r1.5 ChangeClasspathOperation.java --- model/org/eclipse/jdt/internal/core/ChangeClasspathOperation.java 28 Aug 2007 10:03:39 -0000 1.5 +++ model/org/eclipse/jdt/internal/core/ChangeClasspathOperation.java 14 Dec 2007 14:39:54 -0000 @@ -40,6 +40,10 @@ * - create resolved classpath markers */ protected void classpathChanged(JavaProject project) throws JavaModelException { + // reset the project's caches early since some clients rely on the project's caches being up-to-date when run inside an IWorkspaceRunnable + // (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=212769#c5 ) + project.resetCaches(); + DeltaProcessingState state = JavaModelManager.getDeltaState(); DeltaProcessor deltaProcessor = state.getDeltaProcessor(); ClasspathChange change = (ClasspathChange) deltaProcessor.classpathChanges.get(project.getProject()); @@ -55,6 +59,7 @@ // 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); Index: model/org/eclipse/jdt/internal/core/DeltaProcessor.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java,v retrieving revision 1.309 diff -u -r1.309 DeltaProcessor.java --- model/org/eclipse/jdt/internal/core/DeltaProcessor.java 29 Nov 2007 14:10:09 -0000 1.309 +++ model/org/eclipse/jdt/internal/core/DeltaProcessor.java 14 Dec 2007 14:39:54 -0000 @@ -1849,6 +1849,12 @@ this.currentDelta = null; } + // add late coming elements to refresh (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=212769 ) + if (elementsToRefresh == null) + elementsToRefresh = this.state.removeExternalElementsToRefresh(); + else + elementsToRefresh.addAll(this.state.removeExternalElementsToRefresh()); + // generate external archive change deltas if (elementsToRefresh != null) { createExternalArchiveDelta(elementsToRefresh, null); 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.9 diff -u -r1.9 ClasspathChange.java --- model/org/eclipse/jdt/internal/core/ClasspathChange.java 29 Nov 2007 12:59:06 -0000 1.9 +++ model/org/eclipse/jdt/internal/core/ClasspathChange.java 14 Dec 2007 14:39:54 -0000 @@ -10,12 +10,16 @@ *******************************************************************************/ package org.eclipse.jdt.internal.core; +import java.io.File; +import java.net.URI; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; +import org.eclipse.core.filesystem.EFS; +import org.eclipse.core.filesystem.IFileStore; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspace; @@ -261,6 +265,8 @@ delta.changed(this.project, IJavaElementDelta.F_RESOLVED_CLASSPATH_CHANGED); result |= HAS_DELTA; + + state.addForRefresh(this.project); // ensure external jars are refreshed for this project (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=212769 ) Map removedRoots = null; IPackageFragmentRoot[] roots = null; @@ -314,6 +320,26 @@ } } addClasspathDeltas(delta, pkgFragmentRoots, IJavaElementDelta.F_REMOVED_FROM_CLASSPATH); + + // remember timestamp of jars that were removed (in case they are added as external jar in the same operation) + for (int j = 0, length = pkgFragmentRoots.length; j < length; j++) { + IPackageFragmentRoot root = pkgFragmentRoots[j]; + if (root.isArchive() && !root.isExternal()) { + URI location = root.getResource().getLocationURI(); + File file = null; + try { + IFileStore fileStore = EFS.getStore(location); + file = fileStore.toLocalFile(EFS.NONE, null); + } catch (CoreException e) { + // continue + } + if (file == null) + continue; + long timeStamp = DeltaProcessor.getTimeStamp(file); + IPath externalPath = new org.eclipse.core.runtime.Path(file.getAbsolutePath()); + state.getExternalLibTimeStamps().put(externalPath, new Long(timeStamp)); + } + } } else { // remote project changes if (this.oldResolvedClasspath[i].getEntryKind() == IClasspathEntry.CPE_PROJECT) { #P org.eclipse.jdt.core.tests.model Index: src/org/eclipse/jdt/core/tests/model/ExternalJarDeltaTests.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalJarDeltaTests.java,v retrieving revision 1.31 diff -u -r1.31 ExternalJarDeltaTests.java --- src/org/eclipse/jdt/core/tests/model/ExternalJarDeltaTests.java 25 Sep 2007 15:33:38 -0000 1.31 +++ src/org/eclipse/jdt/core/tests/model/ExternalJarDeltaTests.java 14 Dec 2007 14:39:55 -0000 @@ -270,6 +270,42 @@ this.stopDeltas(); } } +/* + * Ensures that the correct delta is reported after a setRawClasspath and after a modification of an external jar. + * (regression test for https://bugs.eclipse.org/bugs/show_bug.cgi?id=212769 ) + */ +public void testExternalJarChanged6() throws CoreException, IOException { + File f = null; + try { + IJavaProject project = this.createJavaProject("P", new String[] {""}, ""); + + String pPath = getExternalPath() + "p.jar"; + setClasspath(project, new IClasspathEntry[]{JavaCore.newLibraryEntry(new Path(pPath), null, null)}); + + f = new File(pPath); + f.createNewFile(); + getJavaModel().refreshExternalArchives(null,null); + waitUntilIndexesReady(); + startDeltas(); + + touch(f); + setClasspath(project, new IClasspathEntry[]{JavaCore.newLibraryEntry(new Path(pPath), null, null), JavaCore.newSourceEntry(new Path("/P"))}); + + assertDeltas( + "Unexpected delta", + "P[*]: {CHILDREN | CONTENT | RAW CLASSPATH CHANGED | RESOLVED CLASSPATH CHANGED}\n" + + " [*]: {ADDED TO CLASSPATH}\n" + + " "+f.getCanonicalPath()+"[*]: {CONTENT | ARCHIVE CONTENT CHANGED}\n" + + " ResourceDelta(/P/.classpath)[*]" + ); + } finally { + if(f != null) { + deleteFile(f); + } + this.deleteProject("P"); + this.stopDeltas(); + } +} /** * Refresh the JavaModel after an addition of an external jar. */ Index: src/org/eclipse/jdt/core/tests/model/JavaProjectTests.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaProjectTests.java,v retrieving revision 1.89 diff -u -r1.89 JavaProjectTests.java --- src/org/eclipse/jdt/core/tests/model/JavaProjectTests.java 25 Sep 2007 15:33:37 -0000 1.89 +++ src/org/eclipse/jdt/core/tests/model/JavaProjectTests.java 14 Dec 2007 14:39:56 -0000 @@ -389,6 +389,33 @@ assertEquals("Unexpected number of roots for non existing entry", 0, roots.length); } +/* + * Ensures that a type can be found if run after setting the classpath in a runnable + * (regression test for https://bugs.eclipse.org/bugs/show_bug.cgi?id=212769 ) + */ +public void testFindTypeAfterSetClasspath() throws CoreException { + try { + final IJavaProject project = createJavaProject("P", new String[] {"src1"}, "bin"); + createFolder("/P/src2/p"); + createFile("/P/src2/p/X.java", "package p; public class X {}"); + project.findType("p.X"); // populate project's cache + final IType[] result = new IType[1]; + ResourcesPlugin.getWorkspace().run( + new IWorkspaceRunnable() { + public void run(IProgressMonitor monitor) throws CoreException { + addClasspathEntry(project, JavaCore.newSourceEntry(new Path("/P/src2"))); + result[0] = project.findType("p.X"); + } + }, + null); + assertElementsEqual( + "Unexpected type found", + "X [in X.java [in p [in src2 [in P]]]]", + result); + } finally { + deleteProject("P"); + } +} /** * Test that a folder with a dot name does not relate to a package fragment */