mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-25 18:05:33 +02:00
Support for IResourceChangeListener providers
This commit is contained in:
parent
6a200bcbce
commit
d581c14367
4 changed files with 238 additions and 16 deletions
|
@ -24,6 +24,7 @@ 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.ICProjectDescriptionManager;
|
||||
import org.eclipse.cdt.core.settings.model.ILanguageSettingsEditableProvider;
|
||||
import org.eclipse.cdt.core.settings.model.WriteAccessException;
|
||||
import org.eclipse.cdt.core.testplugin.CModelMock;
|
||||
import org.eclipse.cdt.core.testplugin.ResourceHelper;
|
||||
|
@ -103,13 +104,20 @@ public class LanguageSettingsPersistenceProjectTests extends TestCase {
|
|||
}
|
||||
}
|
||||
|
||||
private class MockProvider extends LanguageSettingsSerializable {
|
||||
public MockProvider(String id, String name) {
|
||||
private class MockEditableProvider extends LanguageSettingsSerializable implements ILanguageSettingsEditableProvider {
|
||||
public MockEditableProvider(String id, String name) {
|
||||
super(id, name);
|
||||
}
|
||||
@Override
|
||||
public MockEditableProvider cloneShallow() throws CloneNotSupportedException {
|
||||
return (MockEditableProvider) super.cloneShallow();
|
||||
}
|
||||
@Override
|
||||
public MockEditableProvider clone() throws CloneNotSupportedException {
|
||||
return (MockEditableProvider) super.clone();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param name - name of the test.
|
||||
|
@ -178,21 +186,88 @@ public class LanguageSettingsPersistenceProjectTests extends TestCase {
|
|||
|
||||
/**
|
||||
*/
|
||||
public void testReadOnlyDescription() throws Exception {
|
||||
public void testProjectDescription_ReadWriteProviders() throws Exception {
|
||||
// create a project
|
||||
IProject project = ResourceHelper.createCDTProjectWithConfig(getName());
|
||||
// get read-only description
|
||||
ICProjectDescription prjDescription = CProjectDescriptionManager.getInstance().getProjectDescription(project, false);
|
||||
assertNotNull(prjDescription);
|
||||
ICConfigurationDescription cfgDescription = prjDescription.getDefaultSettingConfiguration();
|
||||
assertNotNull(cfgDescription);
|
||||
|
||||
{
|
||||
// get read-only description
|
||||
ICProjectDescription prjDescription = CProjectDescriptionManager.getInstance().getProjectDescription(project, false);
|
||||
assertNotNull(prjDescription);
|
||||
ICConfigurationDescription cfgDescription = prjDescription.getDefaultSettingConfiguration();
|
||||
assertNotNull(cfgDescription);
|
||||
|
||||
// try to write to it
|
||||
try {
|
||||
List<ILanguageSettingsProvider> providers = new ArrayList<ILanguageSettingsProvider>();
|
||||
cfgDescription.setLanguageSettingProviders(providers);
|
||||
fail("WriteAccessException was expected but it was not throw.");
|
||||
} catch (WriteAccessException e) {
|
||||
// exception is expected
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
List<ICLanguageSettingEntry> entries = new ArrayList<ICLanguageSettingEntry>();
|
||||
entries.add(new CIncludePathEntry("path0", 0));
|
||||
|
||||
{
|
||||
// get project descriptions
|
||||
ICProjectDescription writableProjDescription = coreModel.getProjectDescription(project);
|
||||
assertNotNull(writableProjDescription);
|
||||
ICConfigurationDescription[] cfgDescriptions = writableProjDescription.getConfigurations();
|
||||
assertEquals(1, cfgDescriptions.length);
|
||||
ICConfigurationDescription cfgDescription = cfgDescriptions[0];
|
||||
|
||||
// create a provider
|
||||
LanguageSettingsSerializable mockProvider = new MockEditableProvider(PROVIDER_0, PROVIDER_NAME_0);
|
||||
mockProvider.setStoringEntriesInProjectArea(true);
|
||||
mockProvider.setSettingEntries(cfgDescription, null, null, entries);
|
||||
List<ILanguageSettingsProvider> providers = new ArrayList<ILanguageSettingsProvider>();
|
||||
providers.add(mockProvider);
|
||||
cfgDescription.setLanguageSettingProviders(providers);
|
||||
fail("WriteAccessException was expected but it was not throw.");
|
||||
} catch (WriteAccessException e) {
|
||||
// exception is expected
|
||||
List<ILanguageSettingsProvider> storedProviders = cfgDescription.getLanguageSettingProviders();
|
||||
assertEquals(1, storedProviders.size());
|
||||
|
||||
// apply new project description to the project model
|
||||
coreModel.setProjectDescription(project, writableProjDescription);
|
||||
}
|
||||
{
|
||||
// get read-only project descriptions
|
||||
ICProjectDescription readOnlyProjDescription = coreModel.getProjectDescription(project, false);
|
||||
assertNotNull(readOnlyProjDescription);
|
||||
ICConfigurationDescription[] cfgDescriptions = readOnlyProjDescription.getConfigurations();
|
||||
assertEquals(1, cfgDescriptions.length);
|
||||
ICConfigurationDescription cfgDescription = cfgDescriptions[0];
|
||||
|
||||
List<ILanguageSettingsProvider> providers = cfgDescription.getLanguageSettingProviders();
|
||||
assertEquals(1, providers.size());
|
||||
ILanguageSettingsProvider loadedProvider = providers.get(0);
|
||||
assertTrue(loadedProvider instanceof LanguageSettingsSerializable);
|
||||
assertEquals(PROVIDER_0, loadedProvider.getId());
|
||||
assertEquals(PROVIDER_NAME_0, loadedProvider.getName());
|
||||
|
||||
List<ICLanguageSettingEntry> actual = loadedProvider.getSettingEntries(cfgDescription, null, null);
|
||||
assertEquals(entries.get(0), actual.get(0));
|
||||
assertEquals(entries.size(), actual.size());
|
||||
}
|
||||
{
|
||||
// get writable project descriptions
|
||||
ICProjectDescription writableProjDescription = coreModel.getProjectDescription(project);
|
||||
assertNotNull(writableProjDescription);
|
||||
ICConfigurationDescription[] cfgDescriptions = writableProjDescription.getConfigurations();
|
||||
assertEquals(1, cfgDescriptions.length);
|
||||
ICConfigurationDescription cfgDescription = cfgDescriptions[0];
|
||||
|
||||
List<ILanguageSettingsProvider> providers = cfgDescription.getLanguageSettingProviders();
|
||||
assertEquals(1, providers.size());
|
||||
ILanguageSettingsProvider loadedProvider = providers.get(0);
|
||||
assertTrue(loadedProvider instanceof LanguageSettingsSerializable);
|
||||
assertEquals(PROVIDER_0, loadedProvider.getId());
|
||||
assertEquals(PROVIDER_NAME_0, loadedProvider.getName());
|
||||
|
||||
List<ICLanguageSettingEntry> actual = loadedProvider.getSettingEntries(cfgDescription, null, null);
|
||||
assertEquals(entries.get(0), actual.get(0));
|
||||
assertEquals(entries.size(), actual.size());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
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;
|
||||
|
@ -24,11 +25,13 @@ 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;
|
||||
|
@ -37,7 +40,10 @@ 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;
|
||||
|
@ -613,5 +619,141 @@ public class LanguageSettingsExtensionManager {
|
|||
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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ 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;
|
||||
|
@ -188,7 +189,7 @@ public class CConfigurationSpecSettings implements ICSettingsStorage{
|
|||
|
||||
copyExtensionInfo(base);
|
||||
|
||||
fLanguageSettingsProviders = new ArrayList<ILanguageSettingsProvider>(base.getLanguageSettingProviders());
|
||||
fLanguageSettingsProviders = LanguageSettingsExtensionManager.cloneProviders(base.getLanguageSettingProviders());
|
||||
}
|
||||
|
||||
// private void copyRefInfos(Map infosMap){
|
||||
|
|
|
@ -34,7 +34,6 @@ import javax.xml.transform.dom.DOMSource;
|
|||
import javax.xml.transform.stream.StreamResult;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsManager_TBD;
|
||||
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
|
||||
import org.eclipse.cdt.core.settings.model.ICProjectDescriptionManager;
|
||||
import org.eclipse.cdt.core.settings.model.ICSettingsStorage;
|
||||
|
@ -43,6 +42,7 @@ 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;
|
||||
|
@ -365,6 +365,7 @@ public class XmlProjectDescriptionStorage extends AbstractCProjectDescriptionSto
|
|||
if (!overwriteIfExists && fProjectDescription.get() != null)
|
||||
return false;
|
||||
|
||||
ICProjectDescription oldDes = fProjectDescription.get();
|
||||
if (des != null) {
|
||||
if (project.exists() && project.isOpen()) {
|
||||
fProjectDescription = new SoftReference<ICProjectDescription>(des);
|
||||
|
@ -375,6 +376,8 @@ public class XmlProjectDescriptionStorage extends AbstractCProjectDescriptionSto
|
|||
} else {
|
||||
fProjectDescription = new SoftReference<ICProjectDescription>(null);
|
||||
}
|
||||
|
||||
LanguageSettingsExtensionManager.reRegisterListeners(oldDes, fProjectDescription.get());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -484,10 +487,11 @@ public class XmlProjectDescriptionStorage extends AbstractCProjectDescriptionSto
|
|||
// Update the modification stamp
|
||||
projectModificaitonStamp = getModificationStamp(project.getFile(ICProjectDescriptionStorageType.STORAGE_FILE_NAME));
|
||||
CProjectDescription des = new CProjectDescription(project, new XmlStorage(storage), storage, true, false);
|
||||
LanguageSettingsProvidersSerializer.loadLanguageSettings(des);
|
||||
try {
|
||||
setThreadLocalProjectDesc(des);
|
||||
des.loadDatas();
|
||||
|
||||
LanguageSettingsProvidersSerializer.loadLanguageSettings(des);
|
||||
des.doneLoading();
|
||||
} finally {
|
||||
setThreadLocalProjectDesc(null);
|
||||
|
|
Loading…
Add table
Reference in a new issue