X-Git-Url: http://secure.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/SetClasspathOperation.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/SetClasspathOperation.java index ac51e61..0329e7e 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/SetClasspathOperation.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/SetClasspathOperation.java @@ -11,8 +11,10 @@ package net.sourceforge.phpdt.internal.core; import java.util.ArrayList; +import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.Map; import net.sourceforge.phpdt.core.IClasspathEntry; import net.sourceforge.phpdt.core.IJavaElement; @@ -22,6 +24,7 @@ import net.sourceforge.phpdt.core.IJavaModelStatus; import net.sourceforge.phpdt.core.IJavaProject; import net.sourceforge.phpdt.core.IPackageFragmentRoot; import net.sourceforge.phpdt.core.JavaModelException; +import net.sourceforge.phpdt.internal.compiler.util.ObjectVector; import net.sourceforge.phpdt.internal.core.util.Util; import org.eclipse.core.resources.IFolder; @@ -43,6 +46,7 @@ public class SetClasspathOperation extends JavaModelOperation { IClasspathEntry[] oldResolvedPath, newResolvedPath; IClasspathEntry[] newRawPath; boolean canChangeResources; + boolean classpathWasSaved; boolean needCycleCheck; boolean needValidation; boolean needSave; @@ -273,109 +277,112 @@ public class SetClasspathOperation extends JavaModelOperation { * 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( -// IClasspathEntry[] oldResolvedPath, -// IClasspathEntry[] newResolvedPath, -// final JavaProject project) { -// -// JavaModelManager manager = JavaModelManager.getJavaModelManager(); -// boolean needToUpdateDependents = false; -// JavaElementDelta delta = new JavaElementDelta(getJavaModel()); -// boolean hasDelta = false; -// int oldLength = oldResolvedPath.length; -// int newLength = newResolvedPath.length; -// + 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; + // final IndexManager indexManager = manager.getIndexManager(); -// Map oldRoots = null; -// IPackageFragmentRoot[] roots = null; -// if (project.isOpen()) { -// try { -// roots = project.getPackageFragmentRoots(); -// } catch (JavaModelException e) { -// } -// } else { -// Map allRemovedRoots ; -// if ((allRemovedRoots = manager.deltaProcessor.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++) { -// -// 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, -// true, // inside original project -// false, // don't check existency -// false); // don't retrieve exported roots -// 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. + 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++) { + + 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, + true, // inside original project + false, // don't check existency + false); // don't retrieve exported roots + 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 = null; //((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, exclusionPatterns); +// public void run() /* throws JavaModelException */ { +// indexManager.removeSourceFolderFromIndex(project, path, inclusionPatterns, exclusionPatterns); // } // }, // REMOVEALL_APPEND); // break; // case IClasspathEntry.CPE_LIBRARY: -// final DeltaProcessor deltaProcessor = manager.deltaProcessor; +// final DeltaProcessingState deltaState = manager.deltaState; // postAction(new IPostAction() { // public String getID() { // return path.toString(); // } -// public void run() throws JavaModelException { -// if (deltaProcessor.otherRoots.get(path) == null) { // if root was not shared +// public void run() /* throws JavaModelException */ { +// if (deltaState.otherRoots.get(path) == null) { // if root was not shared // indexManager.discardJobs(path.toString()); // indexManager.removeIndex(path); -// // TODO: we could just remove the in-memory index and have the indexing check for timestamps +// // TODO (kent) we could just remove the in-memory index and have the indexing check for timestamps // } // } // }, @@ -383,66 +390,76 @@ public class SetClasspathOperation extends JavaModelOperation { // break; // } // } -// hasDelta = true; -// -// } else { -// // do not notify remote project changes -// if (oldResolvedPath[i].getEntryKind() == IClasspathEntry.CPE_PROJECT){ -// this.needCycleCheck |= (oldResolvedPath[i].isExported() != newResolvedPath[index].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, -// null/*not a source root path*/); -// int sourceAttachmentRootFlags = -// this.getSourceAttachmentDeltaFlag( -// oldResolvedPath[i].getSourceAttachmentRootPath(), -// newResolvedPath[index].getSourceAttachmentRootPath(), -// newSourcePath/*in case both root paths are null*/); -// int flags = sourceAttachmentFlags | sourceAttachmentRootFlags; -// if (flags != 0) { -// addClasspathDeltas( -// project.computePackageFragmentRoots(oldResolvedPath[i]), -// flags, -// delta); -// hasDelta = true; -// } -// } -// } -// -// 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 + hasDelta = true; + + } else { + // do not notify remote project changes + if (oldResolvedPath[i].getEntryKind() == IClasspathEntry.CPE_PROJECT){ + this.needCycleCheck |= (oldResolvedPath[i].isExported() != newResolvedPath[index].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: @@ -460,7 +477,7 @@ public class SetClasspathOperation extends JavaModelOperation { // public String getID() { // return newPath.toString(); // } -// public void run() throws JavaModelException { +// public void run() /* throws JavaModelException */ { // indexManager.indexLibrary(newPath, project.getProject()); // } // }, @@ -470,34 +487,58 @@ public class SetClasspathOperation extends JavaModelOperation { // case IClasspathEntry.CPE_SOURCE: // IClasspathEntry entry = newResolvedPath[i]; // final IPath path = entry.getPath(); +// final char[][] inclusionPatterns = null; //((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, exclusionPatterns); +// 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); -// } -// if (needToUpdateDependents){ -// updateAffectedProjects(project.getProject().getFullPath()); -// } -// } + + 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()); + } + } + protected void saveClasspathIfNecessary() throws JavaModelException { + + if (!this.canChangeResources || !this.needSave) return; + + IClasspathEntry[] classpathForSave; + if (this.newRawPath == ReuseClasspath || this.newRawPath == UpdateClasspath){ + classpathForSave = project.getRawClasspath(); + } else { + classpathForSave = this.newRawPath; + } + IPath outputLocationForSave; + if (this.newOutputLocation == ReuseOutputLocation){ + 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); + } + } protected JavaProject getProject() { return ((JavaProject) getElementsToProcess()[0]); } @@ -528,6 +569,27 @@ public class SetClasspathOperation extends JavaModelOperation { } } + /* + * 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; + } + } + /** * Returns true if this operation performs no resource modifications, * otherwise false. Subclasses must override. @@ -536,28 +598,28 @@ public class SetClasspathOperation extends JavaModelOperation { return !this.canChangeResources; } - protected void saveClasspathIfNecessary() throws JavaModelException { - - if (!this.canChangeResources || !this.needSave) return; - - IClasspathEntry[] classpathForSave; - JavaProject project = getProject(); - if (this.newRawPath == ReuseClasspath || this.newRawPath == UpdateClasspath){ - classpathForSave = project.getRawClasspath(); - } else { - classpathForSave = this.newRawPath; - } - IPath outputLocationForSave; - if (this.newOutputLocation == ReuseOutputLocation){ - 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.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE); - } - } +// protected void saveClasspathIfNecessary() throws JavaModelException { +// +// if (!this.canChangeResources || !this.needSave) return; +// +// IClasspathEntry[] classpathForSave; +// JavaProject project = getProject(); +// if (this.newRawPath == ReuseClasspath || this.newRawPath == UpdateClasspath){ +// classpathForSave = project.getRawClasspath(); +// } else { +// classpathForSave = this.newRawPath; +// } +// IPath outputLocationForSave; +// if (this.newOutputLocation == ReuseOutputLocation){ +// 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.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE); +// } +// } public String toString(){ StringBuffer buffer = new StringBuffer(20); @@ -582,31 +644,52 @@ public class SetClasspathOperation extends JavaModelOperation { return buffer.toString(); } +// private void updateClasspath() throws JavaModelException { +// +// JavaProject project = ((JavaProject) getElementsToProcess()[0]); +// +// beginTask(Util.bind("classpath.settingProgress", project.getElementName()), 2); //$NON-NLS-1$ +// +// // SIDE-EFFECT: from thereon, the classpath got modified +// project.setRawClasspath0(this.newRawPath); +// +// // resolve new path (asking for marker creation if problems) +// if (this.newResolvedPath == null) { +// this.newResolvedPath = project.getResolvedClasspath(true, this.canChangeResources); +// } +// +//// if (this.oldResolvedPath != null) { +//// generateClasspathChangeDeltas( +//// this.oldResolvedPath, +//// this.newResolvedPath, +//// project); +//// } else { +// this.needCycleCheck = true; +// updateAffectedProjects(project.getProject().getFullPath()); +//// } +// +// updateCycleMarkersIfNecessary(newResolvedPath); +// } private void updateClasspath() throws JavaModelException { - JavaProject project = ((JavaProject) getElementsToProcess()[0]); - beginTask(Util.bind("classpath.settingProgress", project.getElementName()), 2); //$NON-NLS-1$ // SIDE-EFFECT: from thereon, the classpath got modified - project.setRawClasspath0(this.newRawPath); + 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); + this.newResolvedPath = project.getResolvedClasspath(true, this.canChangeResources, false/*don't returnResolutionInProgress*/); } -// if (this.oldResolvedPath != null) { -// generateClasspathChangeDeltas( -// this.oldResolvedPath, -// this.newResolvedPath, -// project); -// } else { + if (this.oldResolvedPath != null) { + generateClasspathChangeDeltas(); + } else { this.needCycleCheck = true; updateAffectedProjects(project.getProject().getFullPath()); -// } + } - updateCycleMarkersIfNecessary(newResolvedPath); + updateCycleMarkersIfNecessary(); } /** @@ -654,30 +737,53 @@ public class SetClasspathOperation extends JavaModelOperation { /** * Update cycle markers */ - protected void updateCycleMarkersIfNecessary(IClasspathEntry[] newResolvedPath) { + protected void updateCycleMarkersIfNecessary() { if (!this.needCycleCheck) return; if (!this.canChangeResources) return; - try { - JavaProject project = getProject(); - if (!project.hasCycleMarker() && !project.hasClasspathCycle(project.getResolvedClasspath(true))){ - return; - } - - postAction( - new IPostAction() { - public String getID() { - return "updateCycleMarkers"; //$NON-NLS-1$ - } - public void run() throws JavaModelException { - JavaProject.updateAllCycleMarkers(); - } - }, - REMOVEALL_APPEND); - } catch(JavaModelException e){ + 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(); + } + }, + REMOVEALL_APPEND); } +// /** +// * Update cycle markers +// */ +// protected void updateCycleMarkersIfNecessary(IClasspathEntry[] newResolvedPath) { +// +// if (!this.needCycleCheck) return; +// if (!this.canChangeResources) return; +// +// try { +// JavaProject project = getProject(); +// if (!project.hasCycleMarker() && !project.hasClasspathCycle(project.getResolvedClasspath(true))){ +// return; +// } +// +// postAction( +// new IPostAction() { +// public String getID() { +// return "updateCycleMarkers"; //$NON-NLS-1$ +// } +// public void run() throws JavaModelException { +// JavaProject.updateAllCycleMarkers(); +// } +// }, +// REMOVEALL_APPEND); +// } catch(JavaModelException e){ +// } +// } /** * Sets the output location of the pre-specified project.