1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-07 09:46:02 +02:00

Bug 133881 - Make refreshing after building optional

- changed scheduling rule to be null so that the platform handles the locking on individual resources
- fixed it so only the given project's settings are serialized in its project description
- fixed it so projects/folders/files can be refreshed even if they were removed from the resource tree but not the filesystem
- optimized resource delta processing
This commit is contained in:
Chris Recoskie 2011-05-16 18:18:34 +00:00
parent f1d6b49708
commit 6a8b930ea6
5 changed files with 149 additions and 78 deletions

View file

@ -301,7 +301,7 @@ public class MakeBuilder extends ACBuilder {
// use the refresh scope manager to refresh // use the refresh scope manager to refresh
RefreshScopeManager refreshManager = RefreshScopeManager.getInstance(); RefreshScopeManager refreshManager = RefreshScopeManager.getInstance();
IWorkspaceRunnable runnable = refreshManager.getRefreshRunnable(project); IWorkspaceRunnable runnable = refreshManager.getRefreshRunnable(project);
ResourcesPlugin.getWorkspace().run(runnable, refreshManager.getRefreshSchedulingRule(project), IWorkspace.AVOID_UPDATE, null); ResourcesPlugin.getWorkspace().run(runnable, null, IWorkspace.AVOID_UPDATE, null);
} catch (CoreException e) { } catch (CoreException e) {
MakeCorePlugin.log(e); MakeCorePlugin.log(e);
} }

View file

@ -204,7 +204,7 @@ public class ExternalBuildRunner extends AbstractBuildRunner {
// use the refresh scope manager to refresh // use the refresh scope manager to refresh
RefreshScopeManager refreshManager = RefreshScopeManager.getInstance(); RefreshScopeManager refreshManager = RefreshScopeManager.getInstance();
IWorkspaceRunnable runnable = refreshManager.getRefreshRunnable(project); IWorkspaceRunnable runnable = refreshManager.getRefreshRunnable(project);
ResourcesPlugin.getWorkspace().run(runnable, refreshManager.getRefreshSchedulingRule(project), IWorkspace.AVOID_UPDATE, null); ResourcesPlugin.getWorkspace().run(runnable, null, IWorkspace.AVOID_UPDATE, null);
} catch (CoreException e) { } catch (CoreException e) {
} }
} else { } else {

View file

@ -1112,7 +1112,7 @@ public class GeneratedMakefileBuilder extends ACBuilder {
// use the refresh scope manager to refresh // use the refresh scope manager to refresh
RefreshScopeManager refreshManager = RefreshScopeManager.getInstance(); RefreshScopeManager refreshManager = RefreshScopeManager.getInstance();
IWorkspaceRunnable runnable = refreshManager.getRefreshRunnable(currentProject); IWorkspaceRunnable runnable = refreshManager.getRefreshRunnable(currentProject);
ResourcesPlugin.getWorkspace().run(runnable, refreshManager.getRefreshSchedulingRule(currentProject), IWorkspace.AVOID_UPDATE, null); ResourcesPlugin.getWorkspace().run(runnable, null, IWorkspace.AVOID_UPDATE, null);
} catch (CoreException e) { } catch (CoreException e) {
monitor.subTask(ManagedMakeMessages monitor.subTask(ManagedMakeMessages
.getResourceString(REFRESH_ERROR)); .getResourceString(REFRESH_ERROR));

View file

@ -368,7 +368,7 @@ public class RefreshScopeTests extends TestCase {
// now refresh // now refresh
IWorkspaceRunnable runnable = manager.getRefreshRunnable(fProject); IWorkspaceRunnable runnable = manager.getRefreshRunnable(fProject);
try { try {
ResourcesPlugin.getWorkspace().run(runnable, manager.getRefreshSchedulingRule(fProject), IWorkspace.AVOID_UPDATE, null); ResourcesPlugin.getWorkspace().run(runnable, null, IWorkspace.AVOID_UPDATE, null);
} catch (CoreException e) { } catch (CoreException e) {
fail(); fail();
} }

View file

@ -21,6 +21,8 @@ import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.core.settings.model.ICStorageElement; import org.eclipse.cdt.core.settings.model.ICStorageElement;
import org.eclipse.cdt.internal.core.settings.model.CProjectDescriptionManager; import org.eclipse.cdt.internal.core.settings.model.CProjectDescriptionManager;
import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent; import org.eclipse.core.resources.IResourceChangeEvent;
@ -35,12 +37,11 @@ import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension; import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint; import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.jobs.ISchedulingRule; import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.MultiRule; import org.eclipse.core.runtime.jobs.MultiRule;
import com.ibm.icu.text.MessageFormat;
/** /**
* The RefreshScopeManager provides access to settings pertaining to refreshes performed during * The RefreshScopeManager provides access to settings pertaining to refreshes performed during
* a build. Each project may have a set of resources associated with it that are the set of resources * a build. Each project may have a set of resources associated with it that are the set of resources
@ -59,6 +60,10 @@ import com.ibm.icu.text.MessageFormat;
*/ */
public class RefreshScopeManager { public class RefreshScopeManager {
public static final String PROJECT_VALUE = "PROJECT"; //$NON-NLS-1$
public static final String FOLDER_VALUE = "FOLDER"; //$NON-NLS-1$
public static final String FILE_VALUE = "FILE"; //$NON-NLS-1$
public static final String RESOURCE_TYPE_ATTRIBUTE_NAME = "resourceType"; //$NON-NLS-1$
public static final String WORKSPACE_PATH_ATTRIBUTE_NAME = "workspacePath"; //$NON-NLS-1$ public static final String WORKSPACE_PATH_ATTRIBUTE_NAME = "workspacePath"; //$NON-NLS-1$
public static final String RESOURCE_ELEMENT_NAME = "resource"; //$NON-NLS-1$ public static final String RESOURCE_ELEMENT_NAME = "resource"; //$NON-NLS-1$
public static final String VERSION_NUMBER_ATTRIBUTE_NAME = "versionNumber"; //$NON-NLS-1$ public static final String VERSION_NUMBER_ATTRIBUTE_NAME = "versionNumber"; //$NON-NLS-1$
@ -69,6 +74,7 @@ public class RefreshScopeManager {
public static final String EXCLUSION_CLASS = "exclusionClass"; //$NON-NLS-1$ public static final String EXCLUSION_CLASS = "exclusionClass"; //$NON-NLS-1$
public static final String FACTORY_CLASS = "factoryClass"; //$NON-NLS-1$ public static final String FACTORY_CLASS = "factoryClass"; //$NON-NLS-1$
public static final String INSTANCE_CLASS = "instanceClass"; //$NON-NLS-1$ public static final String INSTANCE_CLASS = "instanceClass"; //$NON-NLS-1$
public static final String OTHER_VALUE = "OTHER"; //$NON-NLS-1$
private int fVersion = 1; private int fVersion = 1;
private HashMap<IProject, LinkedHashSet<IResource>> fProjectToResourcesMap; private HashMap<IProject, LinkedHashSet<IResource>> fProjectToResourcesMap;
@ -79,7 +85,7 @@ public class RefreshScopeManager {
private boolean fIsLoading = false; private boolean fIsLoading = false;
private boolean fIsLoaded = false; private boolean fIsLoaded = false;
private RefreshScopeManager(){ private RefreshScopeManager() {
fClassnameToExclusionFactoryMap = new HashMap<String, RefreshExclusionFactory>(); fClassnameToExclusionFactoryMap = new HashMap<String, RefreshExclusionFactory>();
loadExtensions(); loadExtensions();
try { try {
@ -88,26 +94,30 @@ public class RefreshScopeManager {
CCorePlugin.log(e); CCorePlugin.log(e);
} }
// add a resource change listener that will try to load settings for projects when they open // Add a resource change listener that will try to load settings for projects when they open
ResourcesPlugin.getWorkspace().addResourceChangeListener(new IResourceChangeListener() { // and delete settings when projects are deleted or closed.
ResourcesPlugin.getWorkspace().addResourceChangeListener(
new IResourceChangeListener() {
public void resourceChanged(IResourceChangeEvent event) { public void resourceChanged(IResourceChangeEvent event) {
if(event.getType() == IResourceChangeEvent.PRE_CLOSE || event.getType() == IResourceChangeEvent.PRE_DELETE) { if (event.getType() == IResourceChangeEvent.PRE_CLOSE
IProject project = event.getResource().getProject(); || event.getType() == IResourceChangeEvent.PRE_DELETE) {
IProject project = event.getResource().getProject();
try { try {
if(project.exists() && project.isOpen() && project.hasNature(CProjectNature.C_NATURE_ID)) { if (project.exists() && project.isOpen()
clearDataForProject(project); && project.hasNature(CProjectNature.C_NATURE_ID)) {
clearDataForProject(project);
}
} catch (CoreException e) {
// should never happen due to checks above
}
return;
} }
} catch (CoreException e) {
// should never happen due to checks above
}
return; IResourceDelta delta = event.getDelta();
}
IResourceDelta delta = event.getDelta();
if (delta != null) { if (delta != null) {
try { try {
@ -118,16 +128,20 @@ public class RefreshScopeManager {
IProject project = (IProject) delta.getResource(); IProject project = (IProject) delta.getResource();
if (delta.getKind() == IResourceDelta.ADDED if (delta.getKind() == IResourceDelta.ADDED
|| (delta.getKind() == IResourceDelta.CHANGED && ((delta.getFlags() & IResourceDelta.OPEN) != 0) || (delta.getKind() == IResourceDelta.CHANGED && ((delta.getFlags() & IResourceDelta.OPEN) != 0) ) ) {
&& ((delta.getFlags() & IResourceDelta.REMOVED) != 0))) /* don't load for deleted projects */{
loadSettings(ResourcesPlugin.getWorkspace() loadSettings(ResourcesPlugin.getWorkspace().getRoot(), project);
.getRoot(), project);
return false; return false;
} }
} }
return true; else if (delta.getResource() instanceof IWorkspaceRoot) {
return true;
}
return false;
} }
}); });
@ -137,9 +151,11 @@ public class RefreshScopeManager {
} }
} }
} }
}, IResourceChangeEvent.POST_CHANGE | IResourceChangeEvent.PRE_CLOSE | IResourceChangeEvent.PRE_DELETE); },
IResourceChangeEvent.POST_CHANGE | IResourceChangeEvent.PRE_CLOSE
| IResourceChangeEvent.PRE_DELETE);
} }
public synchronized void loadExtensions() { public synchronized void loadExtensions() {
@ -221,10 +237,10 @@ public class RefreshScopeManager {
LinkedHashSet<IResource> resources = fProjectToResourcesMap.get(project); LinkedHashSet<IResource> resources = fProjectToResourcesMap.get(project);
if (resources == null) { if (resources == null) {
// there are no settings yet for the project, setup the defaults
resources = new LinkedHashSet<IResource>(); resources = new LinkedHashSet<IResource>();
resources.add(project); resources.add(project);
fProjectToResourcesMap.put(project, resources); fProjectToResourcesMap.put(project, resources);
} }
return new LinkedList<IResource>(resources); return new LinkedList<IResource>(resources);
@ -264,16 +280,9 @@ public class RefreshScopeManager {
public synchronized void clearResourcesToRefresh(IProject project) { public synchronized void clearResourcesToRefresh(IProject project) {
getProjectToResourcesMap(); getProjectToResourcesMap();
LinkedHashSet<IResource> resourceSet = fProjectToResourcesMap.get(project); LinkedHashSet<IResource> resourceSet = null;
if(resourceSet == null) {
resourceSet = new LinkedHashSet<IResource>();
fProjectToResourcesMap.put(project, resourceSet);
return;
}
resourceSet.clear();
fProjectToResourcesMap.put(project, resourceSet);
} }
public synchronized void clearAllResourcesToRefresh() { public synchronized void clearAllResourcesToRefresh() {
@ -337,43 +346,67 @@ public class RefreshScopeManager {
exclusions.remove(exclusion); exclusions.remove(exclusion);
} }
public synchronized void persistSettings(ICProjectDescription projectDescription) throws CoreException { public synchronized void persistSettings(ICProjectDescription projectDescription)
throws CoreException {
getProjectToResourcesMap(); getProjectToResourcesMap();
getResourcesToExclusionsMap(); getResourcesToExclusionsMap();
for (IProject project : fProjectToResourcesMap.keySet()) { IProject project = projectDescription.getProject();
if (!project.exists()) {
continue;
}
// serialize all settings for the project to the C Project Description if (!project.exists()) {
if (project.isOpen()) { return;
if (project.hasNature(CProjectNature.C_NATURE_ID)) { }
ICStorageElement storageElement = projectDescription.getStorage(REFRESH_SCOPE_STORAGE_NAME, true); // serialize all settings for the project to the C Project Description
storageElement.clear(); if (project.isOpen()) {
if (project.hasNature(CProjectNature.C_NATURE_ID)) {
storageElement.setAttribute(VERSION_NUMBER_ATTRIBUTE_NAME, Integer.toString(fVersion)); ICStorageElement storageElement = projectDescription.getStorage(
REFRESH_SCOPE_STORAGE_NAME, true);
storageElement.clear();
for (IResource resource : fProjectToResourcesMap.get(project)) { storageElement.setAttribute(VERSION_NUMBER_ATTRIBUTE_NAME,
Integer.toString(fVersion));
// create a resource node for (IResource resource : fProjectToResourcesMap.get(project)) {
ICStorageElement resourceElement = storageElement.createChild(RESOURCE_ELEMENT_NAME);
resourceElement.setAttribute(WORKSPACE_PATH_ATTRIBUTE_NAME, resource
.getFullPath().toString());
// populate the node with any exclusions // create a resource node
List<RefreshExclusion> exclusions = fResourceToExclusionsMap.get(resource); ICStorageElement resourceElement = storageElement
if (exclusions != null) { .createChild(RESOURCE_ELEMENT_NAME);
for (RefreshExclusion exclusion : exclusions) { resourceElement.setAttribute(WORKSPACE_PATH_ATTRIBUTE_NAME, resource
exclusion.persistData(resourceElement); .getFullPath().toString());
}
String resourceTypeString = null;
if(resource instanceof IFile) {
resourceTypeString = FILE_VALUE;
}
else if(resource instanceof IFolder) {
resourceTypeString = FOLDER_VALUE;
}
else if(resource instanceof IProject) {
resourceTypeString = PROJECT_VALUE;
}
else {
resourceTypeString = OTHER_VALUE;
}
resourceElement.setAttribute(RESOURCE_TYPE_ATTRIBUTE_NAME, resourceTypeString);
// populate the node with any exclusions
List<RefreshExclusion> exclusions = fResourceToExclusionsMap.get(resource);
if (exclusions != null) {
for (RefreshExclusion exclusion : exclusions) {
exclusion.persistData(resourceElement);
} }
} }
} }
} }
} }
} }
public synchronized void loadSettings() throws CoreException { public synchronized void loadSettings() throws CoreException {
@ -397,15 +430,18 @@ public class RefreshScopeManager {
* @param project * @param project
* @throws CoreException * @throws CoreException
*/ */
private synchronized void loadSettings(IWorkspaceRoot workspaceRoot, IProject project) public synchronized void loadSettings(IWorkspaceRoot workspaceRoot, IProject project)
throws CoreException { throws CoreException {
if (project.isOpen()) { if (project.isOpen()) {
if (project.hasNature(CProjectNature.C_NATURE_ID)) { if (project.hasNature(CProjectNature.C_NATURE_ID)) {
ICProjectDescription projectDescription = CProjectDescriptionManager.getInstance() CProjectDescriptionManager descriptionManager = CProjectDescriptionManager.getInstance();
.getProjectDescription(project, false); ICProjectDescription projectDescription = descriptionManager.getProjectDescription(project, false);
if(projectDescription == null) { if (projectDescription == null) {
throw new CoreException(CCorePlugin.createStatus(MessageFormat.format(Messages.RefreshScopeManager_4, project.getName()))); // then there's nothing to load... could be an old project that pre-dates the project description's
// existence, or the project could have been just created but the project description hasn't been
// created yet. Either way, just do nothing, because there's nothing to load.
return;
} }
ICStorageElement storageElement = projectDescription.getStorage( ICStorageElement storageElement = projectDescription.getStorage(
@ -426,16 +462,51 @@ public class RefreshScopeManager {
String resourcePath = child.getAttribute(WORKSPACE_PATH_ATTRIBUTE_NAME); String resourcePath = child.getAttribute(WORKSPACE_PATH_ATTRIBUTE_NAME);
if (resourcePath == null) { if (resourcePath == null) {
// error // error... skip this resource
continue;
} }
else { else {
String resourceTypeString = child.getAttribute(RESOURCE_TYPE_ATTRIBUTE_NAME);
if(resourceTypeString == null) {
// we'll do our best, but we won't be able to create handles to non-existent resources
resourceTypeString = OTHER_VALUE;
}
// find the resource // find the resource
IResource resource = workspaceRoot.findMember(resourcePath); IResource resource = null;
if (resourceTypeString.equals(PROJECT_VALUE)) {
resource = workspaceRoot.getProject(resourcePath);
}
else if (resourceTypeString.equals(FILE_VALUE)) {
resource = workspaceRoot.getFile(new Path(resourcePath));
}
else if (resourceTypeString.equals(FOLDER_VALUE)) {
resource = workspaceRoot.getFolder(new Path(resourcePath));
}
else {
// Find arbitrary resource.
// The only way to do this is to ask the workspace root to find
// it, if it exists. If it doesn't exist, we have no way of
// creating a handle to the right type of object, so we must
// give up. In practice, this would likely happen if we had
// a virtual group resource that has been deleted somehow since
// the settings were created, and since the resource is virtual,
// it's impossible to refresh it if it doesn't exist anyway.
resource = workspaceRoot.findMember(resourcePath);
}
if (resource == null) { if (resource == null) {
// error // error.. skip this resource
continue;
} }
else { else {