1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-08-03 22:35:43 +02:00

Support for global (workspace level) IResourceChangeListener providers

This commit is contained in:
Andrew Gvozdev 2011-09-22 21:37:18 -04:00
parent d581c14367
commit 57afab135d
4 changed files with 186 additions and 150 deletions

View file

@ -12,7 +12,6 @@
package org.eclipse.cdt.internal.core.language.settings.providers;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
@ -25,13 +24,11 @@ import org.eclipse.cdt.core.AbstractExecutableExtensionBase;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsProvider;
import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsBaseProvider;
import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsManager;
import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsSerializable;
import org.eclipse.cdt.core.model.ILanguage;
import org.eclipse.cdt.core.model.LanguageManager;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.core.settings.model.ICSettingEntry;
import org.eclipse.cdt.core.settings.model.ILanguageSettingsEditableProvider;
import org.eclipse.cdt.core.settings.model.util.CDataUtil;
@ -40,10 +37,7 @@ import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
@ -618,142 +612,5 @@ public class LanguageSettingsExtensionManager {
ILanguageSettingsProvider extensionProvider = fExtensionProviders.get(id);
return provider.equals(extensionProvider);
}
/**
* TODO - remove me
* Temporary method to report inconsistency in log.
*/
@Deprecated
public static void assertConsistency(ICProjectDescription prjDescription) {
if (prjDescription != null) {
List<ILanguageSettingsProvider> prjProviders = new ArrayList<ILanguageSettingsProvider>();
for (ICConfigurationDescription cfgDescription : prjDescription.getConfigurations()) {
List<ILanguageSettingsProvider> providers = cfgDescription.getLanguageSettingProviders();
for (ILanguageSettingsProvider provider : providers) {
if (!LanguageSettingsManager.isWorkspaceProvider(provider)) {
if (isObjectInTheList(prjProviders, provider)) {
IStatus status = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, "Inconsistent state, duplicate LSP in project description "
+ "[" + System.identityHashCode(provider) + "] "
+ provider);
CoreException e = new CoreException(status);
CCorePlugin.log(e);
}
prjProviders.add(provider);
}
}
}
}
}
/**
* TODO - remove me
* Temporary method to report inconsistency in log.
*/
@Deprecated
public static void assertConsistency(ICConfigurationDescription cfgDescription) {
List<ILanguageSettingsProvider> listeners = new ArrayList<ILanguageSettingsProvider>();
List<ILanguageSettingsProvider> providers = cfgDescription.getLanguageSettingProviders();
for (ILanguageSettingsProvider provider : providers) {
if (isObjectInTheList(listeners, provider)) {
IStatus status = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, "Inconsistent state, duplicate LSP in project description " + provider);
CoreException e = new CoreException(status);
CCorePlugin.log(e);
}
listeners.add(provider);
}
}
/**
* Get a providers list including only providers of type IResourceChangeListener
* for a given project description - collecting from all configurations.
*/
private static List<IResourceChangeListener> getResourceChangeListeners(ICProjectDescription prjDescription) {
List<IResourceChangeListener> listeners = new ArrayList<IResourceChangeListener>();
if (prjDescription != null) {
for (ICConfigurationDescription cfgDescription : prjDescription.getConfigurations()) {
List<ILanguageSettingsProvider> providers = cfgDescription.getLanguageSettingProviders();
for (ILanguageSettingsProvider provider : providers) {
if (provider instanceof IResourceChangeListener) {
listeners.add((IResourceChangeListener) provider);
}
}
}
}
return listeners;
}
/**
* Unregister listeners which are not used anymore and register new listeners.
* The method is used when project description is applied to workspace.
* @param oldPrjDescription - old project descriptions being replaced in the workspace.
* @param newPrjDescription - new project description being applied to the workspace.
*/
public static void reRegisterListeners(ICProjectDescription oldPrjDescription, ICProjectDescription newPrjDescription) {
if (oldPrjDescription == newPrjDescription) {
assertConsistency(oldPrjDescription); // TODO - remove me
return;
}
assertConsistency(oldPrjDescription); // TODO - remove me
assertConsistency(newPrjDescription); // TODO - remove me
IWorkspace workspace = ResourcesPlugin.getWorkspace();
List<IResourceChangeListener> oldListeners = getResourceChangeListeners(oldPrjDescription);
List<IResourceChangeListener> newListeners = getResourceChangeListeners(newPrjDescription);
for (IResourceChangeListener listener : oldListeners) {
if (!isObjectInTheList(newListeners, listener)) {
workspace.removeResourceChangeListener(listener);
// TODO - remove me
CCorePlugin.log(new Status(IStatus.WARNING,CCorePlugin.PLUGIN_ID, oldPrjDescription.getProject() + ": Removed IResourceChangeListener "
+ "[" + System.identityHashCode(listener) + "] "
+ listener));
}
}
for (IResourceChangeListener listener : newListeners) {
if (!isObjectInTheList(oldListeners, listener)) {
workspace.addResourceChangeListener(listener);
// TODO - remove me
CCorePlugin.log(new Status(IStatus.WARNING,CCorePlugin.PLUGIN_ID, newPrjDescription.getProject() + ": Added IResourceChangeListener "
+ "[" + System.identityHashCode(listener) + "] "
+ listener));
}
}
}
private static <T> boolean isObjectInTheList(Collection<T> list, T element) {
// list.contains(element) won't do it as we are interested in exact object, not in equal object
for (T elem : list) {
if (elem == element)
return true;
}
return false;
}
/**
* Deep clone of a list of language settings providers.
*
* @param baseProviders - list of providers to clone.
* @return newly cloned list.
*/
public static List<ILanguageSettingsProvider> cloneProviders(List<ILanguageSettingsProvider> baseProviders) {
List<ILanguageSettingsProvider> newProviders = new ArrayList<ILanguageSettingsProvider>();
for (ILanguageSettingsProvider provider : baseProviders) {
if (provider instanceof ILanguageSettingsEditableProvider) {
try {
provider = ((ILanguageSettingsEditableProvider) provider).clone();
} catch (CloneNotSupportedException e) {
IStatus status = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, "Not able to clone provider " + provider.getClass());
CCorePlugin.log(new CoreException(status));
}
}
newProviders.add(provider);
}
return new ArrayList<ILanguageSettingsProvider>(newProviders);
}
}

View file

@ -13,12 +13,14 @@ package org.eclipse.cdt.internal.core.language.settings.providers;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsProvider;
import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsManager;
import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsSerializable;
import org.eclipse.cdt.core.language.settings.providers.ScannerDiscoveryLegacySupport;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
@ -31,6 +33,10 @@ import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
@ -58,9 +64,11 @@ public class LanguageSettingsProvidersSerializer {
private static ILock serializingLock = Job.getJobManager().newLock();
/** Cache of globally available providers to be consumed by calling clients */
private static Map<String, ILanguageSettingsProvider> rawGlobalWorkspaceProviders = new HashMap<String, ILanguageSettingsProvider>();
private static Map<String, ILanguageSettingsProvider> globalWorkspaceProviders = new HashMap<String, ILanguageSettingsProvider>();
private static class LanguageSettingsWorkspaceProvider implements ILanguageSettingsProvider {
private static class LanguageSettingsWorkspaceProvider implements ILanguageSettingsProvider, IResourceChangeListener {
private String providerId;
private int registrationCount = 0;
public LanguageSettingsWorkspaceProvider(String id) {
Assert.isNotNull(id);
@ -107,6 +115,25 @@ public class LanguageSettingsProvidersSerializer {
public String toString() {
return "id="+getId()+", name="+getName();
}
/**
* {@inheritDoc}
*
* LanguageSettingsWorkspaceProvider delegates event handling to raw provider.
*
*/
public void resourceChanged(IResourceChangeEvent event) {
// keep in mind that type of rawProvider can change
ILanguageSettingsProvider rawProvider = getRawProvider();
if (rawProvider instanceof IResourceChangeListener) {
((IResourceChangeListener) rawProvider).resourceChanged(event);
}
}
synchronized int incrementListenerCount(int inc) {
registrationCount += inc;
return registrationCount;
}
}
@ -565,7 +592,12 @@ public class LanguageSettingsProvidersSerializer {
* @return the provider or {@code null} if provider is not defined.
*/
public static ILanguageSettingsProvider getWorkspaceProvider(String id) {
return new LanguageSettingsWorkspaceProvider(id);
ILanguageSettingsProvider provider = globalWorkspaceProviders.get(id);
if (provider == null) {
provider = new LanguageSettingsWorkspaceProvider(id);
globalWorkspaceProviders.put(id, provider);
}
return provider;
}
public static ILanguageSettingsProvider getRawWorkspaceProvider(String id) {
@ -580,7 +612,7 @@ public class LanguageSettingsProvidersSerializer {
public static List<ILanguageSettingsProvider> getWorkspaceProviders() {
ArrayList<ILanguageSettingsProvider> workspaceProviders = new ArrayList<ILanguageSettingsProvider>();
for (ILanguageSettingsProvider rawProvider : rawGlobalWorkspaceProviders.values()) {
workspaceProviders.add(new LanguageSettingsWorkspaceProvider(rawProvider.getId()));
workspaceProviders.add(getWorkspaceProvider(rawProvider.getId()));
}
return workspaceProviders;
}
@ -595,4 +627,153 @@ public class LanguageSettingsProvidersSerializer {
public static boolean isWorkspaceProvider(ILanguageSettingsProvider provider) {
return provider instanceof LanguageSettingsWorkspaceProvider;
}
/**
* TODO - remove me
* Temporary method to report inconsistency in log.
*/
@Deprecated
public static void assertConsistency(ICProjectDescription prjDescription) {
if (prjDescription != null) {
List<ILanguageSettingsProvider> prjProviders = new ArrayList<ILanguageSettingsProvider>();
for (ICConfigurationDescription cfgDescription : prjDescription.getConfigurations()) {
List<ILanguageSettingsProvider> providers = cfgDescription.getLanguageSettingProviders();
for (ILanguageSettingsProvider provider : providers) {
if (!LanguageSettingsManager.isWorkspaceProvider(provider)) {
if (isObjectInTheList(prjProviders, provider)) {
IStatus status = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, "Inconsistent state, duplicate LSP in project description "
+ "[" + System.identityHashCode(provider) + "] "
+ provider);
CoreException e = new CoreException(status);
CCorePlugin.log(e);
}
prjProviders.add(provider);
}
}
}
}
}
/**
* TODO - remove me
* Temporary method to report inconsistency in log.
*/
@Deprecated
public static void assertConsistency(ICConfigurationDescription cfgDescription) {
List<ILanguageSettingsProvider> listeners = new ArrayList<ILanguageSettingsProvider>();
List<ILanguageSettingsProvider> providers = cfgDescription.getLanguageSettingProviders();
for (ILanguageSettingsProvider provider : providers) {
if (isObjectInTheList(listeners, provider)) {
IStatus status = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, "Inconsistent state, duplicate LSP in project description " + provider);
CoreException e = new CoreException(status);
CCorePlugin.log(e);
}
listeners.add(provider);
}
}
/**
* Get a providers list including only providers of type IResourceChangeListener
* for a given project description - collecting from all configurations.
*/
private static List<IResourceChangeListener> getResourceChangeListeners(ICProjectDescription prjDescription) {
List<IResourceChangeListener> listeners = new ArrayList<IResourceChangeListener>();
if (prjDescription != null) {
for (ICConfigurationDescription cfgDescription : prjDescription.getConfigurations()) {
List<ILanguageSettingsProvider> providers = cfgDescription.getLanguageSettingProviders();
for (ILanguageSettingsProvider provider : providers) {
if (provider instanceof IResourceChangeListener) {
listeners.add((IResourceChangeListener) provider);
}
}
}
}
return listeners;
}
/**
* Unregister listeners which are not used anymore and register new listeners.
* The method is used when project description is applied to workspace.
* @param oldPrjDescription - old project descriptions being replaced in the workspace.
* @param newPrjDescription - new project description being applied to the workspace.
*/
public static void reRegisterListeners(ICProjectDescription oldPrjDescription, ICProjectDescription newPrjDescription) {
if (oldPrjDescription == newPrjDescription) {
assertConsistency(oldPrjDescription); // TODO - remove me
return;
}
assertConsistency(oldPrjDescription); // TODO - remove me
assertConsistency(newPrjDescription); // TODO - remove me
IWorkspace workspace = ResourcesPlugin.getWorkspace();
List<IResourceChangeListener> oldListeners = getResourceChangeListeners(oldPrjDescription);
List<IResourceChangeListener> newListeners = getResourceChangeListeners(newPrjDescription);
for (IResourceChangeListener listener : oldListeners) {
if (!isObjectInTheList(newListeners, listener)) {
int count = 0;
if (listener instanceof LanguageSettingsWorkspaceProvider) {
count = ((LanguageSettingsWorkspaceProvider) listener).incrementListenerCount(-1);
}
if (count == 0) {
workspace.removeResourceChangeListener(listener);
// TODO - remove me
CCorePlugin.log(new Status(IStatus.WARNING,CCorePlugin.PLUGIN_ID, oldPrjDescription.getProject() + ": Removed IResourceChangeListener "
+ "[" + System.identityHashCode(listener) + "] "
+ listener));
}
}
}
for (IResourceChangeListener listener : newListeners) {
if (!isObjectInTheList(oldListeners, listener)) {
int count = 1;
if (listener instanceof LanguageSettingsWorkspaceProvider) {
count = ((LanguageSettingsWorkspaceProvider) listener).incrementListenerCount(1);
}
if (count == 1) {
workspace.addResourceChangeListener(listener);
// TODO - remove me
CCorePlugin.log(new Status(IStatus.WARNING,CCorePlugin.PLUGIN_ID, newPrjDescription.getProject() + ": Added IResourceChangeListener "
+ "[" + System.identityHashCode(listener) + "] "
+ listener));
}
}
}
}
private static <T> boolean isObjectInTheList(Collection<T> list, T element) {
// list.contains(element) won't do it as we are interested in exact object, not in equal object
for (T elem : list) {
if (elem == element)
return true;
}
return false;
}
/**
* Deep clone of a list of language settings providers.
*
* @param baseProviders - list of providers to clone.
* @return newly cloned list.
*/
public static List<ILanguageSettingsProvider> cloneProviders(List<ILanguageSettingsProvider> baseProviders) {
List<ILanguageSettingsProvider> newProviders = new ArrayList<ILanguageSettingsProvider>();
for (ILanguageSettingsProvider provider : baseProviders) {
if (provider instanceof ILanguageSettingsEditableProvider) {
try {
provider = ((ILanguageSettingsEditableProvider) provider).clone();
} catch (CloneNotSupportedException e) {
IStatus status = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, "Not able to clone provider " + provider.getClass());
CCorePlugin.log(new CoreException(status));
}
}
newProviders.add(provider);
}
return new ArrayList<ILanguageSettingsProvider>(newProviders);
}
}

View file

@ -41,7 +41,6 @@ import org.eclipse.cdt.internal.core.COwner;
import org.eclipse.cdt.internal.core.COwnerConfiguration;
import org.eclipse.cdt.internal.core.cdtvariables.StorableCdtVariables;
import org.eclipse.cdt.internal.core.envvar.EnvironmentVariableManager;
import org.eclipse.cdt.internal.core.language.settings.providers.LanguageSettingsExtensionManager;
import org.eclipse.cdt.internal.core.language.settings.providers.LanguageSettingsProvidersSerializer;
import org.eclipse.cdt.utils.envvar.StorableEnvironment;
import org.eclipse.core.runtime.CoreException;
@ -189,7 +188,7 @@ public class CConfigurationSpecSettings implements ICSettingsStorage{
copyExtensionInfo(base);
fLanguageSettingsProviders = LanguageSettingsExtensionManager.cloneProviders(base.getLanguageSettingProviders());
fLanguageSettingsProviders = LanguageSettingsProvidersSerializer.cloneProviders(base.getLanguageSettingProviders());
}
// private void copyRefInfos(Map infosMap){

View file

@ -42,7 +42,6 @@ import org.eclipse.cdt.core.settings.model.extension.ICProjectConverter;
import org.eclipse.cdt.core.settings.model.util.CDataUtil;
import org.eclipse.cdt.internal.core.XmlUtil;
import org.eclipse.cdt.internal.core.envvar.ContributedEnvironment;
import org.eclipse.cdt.internal.core.language.settings.providers.LanguageSettingsExtensionManager;
import org.eclipse.cdt.internal.core.language.settings.providers.LanguageSettingsProvidersSerializer;
import org.eclipse.cdt.internal.core.settings.model.AbstractCProjectDescriptionStorage;
import org.eclipse.cdt.internal.core.settings.model.CProjectDescription;
@ -377,7 +376,7 @@ public class XmlProjectDescriptionStorage extends AbstractCProjectDescriptionSto
fProjectDescription = new SoftReference<ICProjectDescription>(null);
}
LanguageSettingsExtensionManager.reRegisterListeners(oldDes, fProjectDescription.get());
LanguageSettingsProvidersSerializer.reRegisterListeners(oldDes, fProjectDescription.get());
return true;
}