diff --git a/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/language/settings/providers/LanguageSettingsListenersTests.java b/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/language/settings/providers/LanguageSettingsListenersTests.java index 7a527624432..b17b0351b8a 100644 --- a/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/language/settings/providers/LanguageSettingsListenersTests.java +++ b/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/language/settings/providers/LanguageSettingsListenersTests.java @@ -18,9 +18,14 @@ import junit.framework.TestCase; import junit.framework.TestSuite; import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.core.settings.model.CMacroEntry; 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.testplugin.ResourceHelper; +import org.eclipse.cdt.internal.core.language.settings.providers.ILanguageSettingsChangeEvent; +import org.eclipse.cdt.internal.core.language.settings.providers.ILanguageSettingsChangeListener; +import org.eclipse.cdt.internal.core.language.settings.providers.LanguageSettingsProvidersSerializer; import org.eclipse.core.resources.IProject; /** @@ -29,12 +34,38 @@ import org.eclipse.core.resources.IProject; public class LanguageSettingsListenersTests extends TestCase { // Must match provider id defined as extension point private static final String EXTENSION_REGISTERER_PROVIDER_ID = "org.eclipse.cdt.core.tests.language.settings.listener.registerer.provider"; + private static final String EXTENSION_EDITABLE_PROVIDER_ID = "org.eclipse.cdt.core.tests.custom.editable.language.settings.provider"; private static final String PROVIDER_1 = "test.provider.1.id"; private static final String PROVIDER_NAME_1 = "test.provider.1.name"; private static final String PROVIDER_CUSTOM_GLOBAL = "test.provider.custom.global.id"; private static final String PROVIDER_CUSTOM_GLOBAL_NAME = "test.provider.custom.global.name"; + private static final CMacroEntry SAMPLE_LSE = new CMacroEntry("MACRO", "value",0); + private class MockLanguageSettingsChangeListener implements ILanguageSettingsChangeListener { + private int count = 0; + private ILanguageSettingsChangeEvent lastEvent = null; + + public void handleEvent(ILanguageSettingsChangeEvent event) { + count++; + lastEvent = event; + } + + public int getCount() { + return count; + } + + public void resetCount() { + count = 0; + lastEvent = null; + } + + public ILanguageSettingsChangeEvent getLastEvent() { + return lastEvent; + } + } + private MockLanguageSettingsChangeListener mockLseListener = new MockLanguageSettingsChangeListener(); + /** * Constructor. * @param name - name of the test. @@ -50,6 +81,7 @@ public class LanguageSettingsListenersTests extends TestCase { @Override protected void tearDown() throws Exception { + LanguageSettingsProvidersSerializer.unregisterLanguageSettingsChangeListener(mockLseListener); LanguageSettingsManager.setWorkspaceProviders(null); ResourceHelper.cleanUp(); } @@ -489,6 +521,543 @@ public class LanguageSettingsListenersTests extends TestCase { } } + /** + */ + public void testNotification_cfgProvider_AddEmptyProvider() throws Exception { + IProject project = ResourceHelper.createCDTProjectWithConfig(this.getName()); + // First clear default providers + { + // get project descriptions + ICProjectDescription writableProjDescription = CoreModel.getDefault().getProjectDescription(project); + assertNotNull(writableProjDescription); + ICConfigurationDescription[] cfgDescriptions = writableProjDescription.getConfigurations(); + assertEquals(1, cfgDescriptions.length); + ICConfigurationDescription cfgDescription = cfgDescriptions[0]; + + // clear providers + List providers = new ArrayList(); + cfgDescription.setLanguageSettingProviders(providers); + List storedProviders = cfgDescription.getLanguageSettingProviders(); + assertEquals(0, storedProviders.size()); + + // write to project description + CoreModel.getDefault().setProjectDescription(project, writableProjDescription); + } + + // register mock listener to inspect the notifications + LanguageSettingsProvidersSerializer.registerLanguageSettingsChangeListener(mockLseListener); + assertEquals(0, mockLseListener.getCount()); + assertEquals(null, mockLseListener.getLastEvent()); + + // Add empty provider + { + // get project descriptions + ICProjectDescription writableProjDescription = CoreModel.getDefault().getProjectDescription(project); + assertNotNull(writableProjDescription); + ICConfigurationDescription[] cfgDescriptions = writableProjDescription.getConfigurations(); + assertEquals(1, cfgDescriptions.length); + ICConfigurationDescription cfgDescription = cfgDescriptions[0]; + + // create a provider and add to cfgDescription + ILanguageSettingsProvider mockProvider = new MockLanguageSettingsEditableProvider(PROVIDER_1, PROVIDER_NAME_1); + List providers = new ArrayList(); + providers.add(mockProvider); + cfgDescription.setLanguageSettingProviders(providers); + List storedProviders = cfgDescription.getLanguageSettingProviders(); + assertEquals(1, storedProviders.size()); + + // write to project description + CoreModel.getDefault().setProjectDescription(project, writableProjDescription); + } + + // No notifications expected + assertEquals(0, mockLseListener.getCount()); + assertEquals(null, mockLseListener.getLastEvent()); + } + + /** + */ + public void testNotification_cfgProvider_AddNonEmptyProvider() throws Exception { + IProject project = ResourceHelper.createCDTProjectWithConfig(this.getName()); + // First clear default providers + { + // get project descriptions + ICProjectDescription writableProjDescription = CoreModel.getDefault().getProjectDescription(project); + assertNotNull(writableProjDescription); + ICConfigurationDescription[] cfgDescriptions = writableProjDescription.getConfigurations(); + assertEquals(1, cfgDescriptions.length); + ICConfigurationDescription cfgDescription = cfgDescriptions[0]; + + // clear providers + List providers = new ArrayList(); + cfgDescription.setLanguageSettingProviders(providers); + List storedProviders = cfgDescription.getLanguageSettingProviders(); + assertEquals(0, storedProviders.size()); + + // write to project description + CoreModel.getDefault().setProjectDescription(project, writableProjDescription); + } + + // register mock listener to inspect the notifications + LanguageSettingsProvidersSerializer.registerLanguageSettingsChangeListener(mockLseListener); + assertEquals(0, mockLseListener.getCount()); + assertEquals(null, mockLseListener.getLastEvent()); + + // Add non-empty provider + { + // get project descriptions + ICProjectDescription writableProjDescription = CoreModel.getDefault().getProjectDescription(project); + assertNotNull(writableProjDescription); + ICConfigurationDescription[] cfgDescriptions = writableProjDescription.getConfigurations(); + assertEquals(1, cfgDescriptions.length); + ICConfigurationDescription cfgDescription = cfgDescriptions[0]; + String cfgDescriptionId = cfgDescription.getId(); + + // create a provider and add entries + MockLanguageSettingsEditableProvider mockProvider = new MockLanguageSettingsEditableProvider(PROVIDER_1, PROVIDER_NAME_1); + List entries = new ArrayList(); + entries.add(SAMPLE_LSE); + mockProvider.setSettingEntries(cfgDescription, project, null, entries); + List providers = new ArrayList(); + providers.add(mockProvider); + cfgDescription.setLanguageSettingProviders(providers); + List storedProviders = cfgDescription.getLanguageSettingProviders(); + assertEquals(1, storedProviders.size()); + + // write to project description + CoreModel.getDefault().setProjectDescription(project, writableProjDescription); + + // inspect notifications + assertEquals(1, mockLseListener.getCount()); + ILanguageSettingsChangeEvent event = mockLseListener.getLastEvent(); + assertNotNull(event); + + assertEquals(project.getName(), event.getProjectName()); + assertEquals(1, event.getConfigurationDescriptionIds().length); + assertEquals(cfgDescriptionId, event.getConfigurationDescriptionIds()[0]); + assertEquals(1, event.getResources(cfgDescriptionId).length); + assertEquals(project, event.getResources(cfgDescriptionId)[0]); + } + } + + /** + */ + public void testNotification_cfgProvider_SerializeEntries() throws Exception { + IProject project = ResourceHelper.createCDTProjectWithConfig(this.getName()); + + // add the mock provider + { + // get project descriptions + ICProjectDescription writableProjDescription = CoreModel.getDefault().getProjectDescription(project); + assertNotNull(writableProjDescription); + ICConfigurationDescription[] cfgDescriptions = writableProjDescription.getConfigurations(); + assertEquals(1, cfgDescriptions.length); + ICConfigurationDescription cfgDescription = cfgDescriptions[0]; + + // create a provider and add to cfgDescription + List providers = new ArrayList(); + providers.add(new MockLanguageSettingsEditableProvider(PROVIDER_1, PROVIDER_NAME_1)); + cfgDescription.setLanguageSettingProviders(providers); + List storedProviders = cfgDescription.getLanguageSettingProviders(); + assertEquals(1, storedProviders.size()); + + // write to project description + CoreModel.getDefault().setProjectDescription(project, writableProjDescription); + } + + // register mock listener to inspect the notifications + LanguageSettingsProvidersSerializer.registerLanguageSettingsChangeListener(mockLseListener); + assertEquals(0, mockLseListener.getCount()); + assertEquals(null, mockLseListener.getLastEvent()); + + // Change the provider's entries + { + // get project descriptions + ICProjectDescription prjDescription = CoreModel.getDefault().getProjectDescription(project, false); + assertNotNull(prjDescription); + ICConfigurationDescription[] cfgDescriptions = prjDescription.getConfigurations(); + assertEquals(1, cfgDescriptions.length); + ICConfigurationDescription cfgDescription = cfgDescriptions[0]; + String cfgDescriptionId = cfgDescription.getId(); + + // Add entries + List entries = new ArrayList(); + entries.add(SAMPLE_LSE); + List providers = cfgDescription.getLanguageSettingProviders(); + assertEquals(1, providers.size()); + assertTrue(providers.get(0) instanceof MockLanguageSettingsEditableProvider); + MockLanguageSettingsEditableProvider mockProvider = (MockLanguageSettingsEditableProvider) providers.get(0); + mockProvider.setSettingEntries(cfgDescription, project, null, entries); + assertEquals(0, mockLseListener.getCount()); + assertEquals(null, mockLseListener.getLastEvent()); + + // Serialize settings + LanguageSettingsProvidersSerializer.serializeLanguageSettings(prjDescription); + // inspect event + assertEquals(1, mockLseListener.getCount()); + ILanguageSettingsChangeEvent event = mockLseListener.getLastEvent(); + assertNotNull(event); + + assertEquals(project.getName(), event.getProjectName()); + assertEquals(1, event.getConfigurationDescriptionIds().length); + assertEquals(cfgDescriptionId, event.getConfigurationDescriptionIds()[0]); + assertEquals(1, event.getResources(cfgDescriptionId).length); + assertEquals(project, event.getResources(cfgDescriptionId)[0]); + // TODO - drill to the entries + } + } + + /** + */ + public void testNotification_cfgProvider_SerializeEntriesConcurrent() throws Exception { + IProject project = ResourceHelper.createCDTProjectWithConfig(this.getName()); + + // add the mock provider + { + // get project descriptions + ICProjectDescription writableProjDescription = CoreModel.getDefault().getProjectDescription(project); + assertNotNull(writableProjDescription); + ICConfigurationDescription[] cfgDescriptions = writableProjDescription.getConfigurations(); + assertEquals(1, cfgDescriptions.length); + ICConfigurationDescription cfgDescription = cfgDescriptions[0]; + + // create a provider and add to cfgDescription + List providers = new ArrayList(); + providers.add(new MockLanguageSettingsEditableProvider(PROVIDER_1, PROVIDER_NAME_1)); + cfgDescription.setLanguageSettingProviders(providers); + List storedProviders = cfgDescription.getLanguageSettingProviders(); + assertEquals(1, storedProviders.size()); + + // write to project description + CoreModel.getDefault().setProjectDescription(project, writableProjDescription); + } + + // register mock listener to inspect the notifications + LanguageSettingsProvidersSerializer.registerLanguageSettingsChangeListener(mockLseListener); + assertEquals(0, mockLseListener.getCount()); + assertEquals(null, mockLseListener.getLastEvent()); + + // Change the provider's entries concurrently + + // get project descriptions + ICProjectDescription prjDescription_1 = CoreModel.getDefault().getProjectDescription(project, false); + assertNotNull(prjDescription_1); + ICProjectDescription prjDescription_2 = CoreModel.getDefault().getProjectDescription(project, false); + assertNotNull(prjDescription_2); + { + ICConfigurationDescription[] cfgDescriptions = prjDescription_1.getConfigurations(); + assertEquals(1, cfgDescriptions.length); + ICConfigurationDescription cfgDescriptionWritable = cfgDescriptions[0]; + String cfgDescriptionId = cfgDescriptionWritable.getId(); + + // Add entries + List entries = new ArrayList(); + entries.add(SAMPLE_LSE); + List providers = cfgDescriptionWritable.getLanguageSettingProviders(); + assertEquals(1, providers.size()); + assertTrue(providers.get(0) instanceof MockLanguageSettingsEditableProvider); + MockLanguageSettingsEditableProvider mockProvider = (MockLanguageSettingsEditableProvider) providers.get(0); + mockProvider.setSettingEntries(cfgDescriptionWritable, project, null, entries); + + // reset count + mockLseListener.resetCount(); + assertEquals(0, mockLseListener.getCount()); + assertNull(mockLseListener.getLastEvent()); + + // Serialize settings + LanguageSettingsProvidersSerializer.serializeLanguageSettings(prjDescription_1); + // inspect event + assertEquals(1, mockLseListener.getCount()); + ILanguageSettingsChangeEvent event = mockLseListener.getLastEvent(); + assertNotNull(event); + + assertEquals(project.getName(), event.getProjectName()); + assertEquals(1, event.getConfigurationDescriptionIds().length); + assertEquals(cfgDescriptionId, event.getConfigurationDescriptionIds()[0]); + assertEquals(1, event.getResources(cfgDescriptionId).length); + assertEquals(project, event.getResources(cfgDescriptionId)[0]); + // TODO - drill to the entries + } + { + ICConfigurationDescription[] cfgDescriptions = prjDescription_2.getConfigurations(); + assertEquals(1, cfgDescriptions.length); + ICConfigurationDescription cfgDescriptionWritable = cfgDescriptions[0]; + String cfgDescriptionId = cfgDescriptionWritable.getId(); + + // Add same entries + List entries = new ArrayList(); + entries.add(SAMPLE_LSE); + List providers = cfgDescriptionWritable.getLanguageSettingProviders(); + assertEquals(1, providers.size()); + assertTrue(providers.get(0) instanceof MockLanguageSettingsEditableProvider); + MockLanguageSettingsEditableProvider mockProvider = (MockLanguageSettingsEditableProvider) providers.get(0); + mockProvider.setSettingEntries(cfgDescriptionWritable, project, null, entries); + + // reset count + mockLseListener.resetCount(); + assertEquals(0, mockLseListener.getCount()); + assertNull(mockLseListener.getLastEvent()); + + // Serialize settings + LanguageSettingsProvidersSerializer.serializeLanguageSettings(prjDescription_2); + // inspect event + assertEquals(0, mockLseListener.getCount()); + ILanguageSettingsChangeEvent event = mockLseListener.getLastEvent(); + assertNull(event); + } + } + + /** + */ + public void testNotification_globalProvider_AddEmptyProvider() throws Exception { + IProject project = ResourceHelper.createCDTProjectWithConfig(this.getName()); + // First clear default providers + { + // get project descriptions + ICProjectDescription writableProjDescription = CoreModel.getDefault().getProjectDescription(project); + assertNotNull(writableProjDescription); + ICConfigurationDescription[] cfgDescriptions = writableProjDescription.getConfigurations(); + assertEquals(1, cfgDescriptions.length); + ICConfigurationDescription cfgDescription = cfgDescriptions[0]; + + // clear providers + List providers = new ArrayList(); + cfgDescription.setLanguageSettingProviders(providers); + List storedProviders = cfgDescription.getLanguageSettingProviders(); + assertEquals(0, storedProviders.size()); + + // write to project description + CoreModel.getDefault().setProjectDescription(project, writableProjDescription); + } + + // register mock listener to inspect the notifications + LanguageSettingsProvidersSerializer.registerLanguageSettingsChangeListener(mockLseListener); + assertEquals(0, mockLseListener.getCount()); + assertEquals(null, mockLseListener.getLastEvent()); + + // Add empty global provider + { + // get project descriptions + ICProjectDescription writableProjDescription = CoreModel.getDefault().getProjectDescription(project); + assertNotNull(writableProjDescription); + ICConfigurationDescription[] cfgDescriptions = writableProjDescription.getConfigurations(); + assertEquals(1, cfgDescriptions.length); + ICConfigurationDescription cfgDescription = cfgDescriptions[0]; + + // retrieve a global provider + ILanguageSettingsProvider wspProvider = LanguageSettingsManager.getWorkspaceProvider(EXTENSION_EDITABLE_PROVIDER_ID); + assertNotNull(wspProvider); + ILanguageSettingsProvider rawProvider = LanguageSettingsManager.getRawProvider(wspProvider); + assertTrue(rawProvider instanceof MockLanguageSettingsEditableProvider); + // clear it + ((MockLanguageSettingsEditableProvider) rawProvider).clear(); + assertEquals(null, wspProvider.getSettingEntries(cfgDescription, project, null)); + // add the provider to cfgDescription + List providers = new ArrayList(); + providers.add(wspProvider); + cfgDescription.setLanguageSettingProviders(providers); + List storedProviders = cfgDescription.getLanguageSettingProviders(); + assertEquals(1, storedProviders.size()); + + // write to project description + CoreModel.getDefault().setProjectDescription(project, writableProjDescription); + } + + // No notifications expected + assertEquals(0, mockLseListener.getCount()); + assertEquals(null, mockLseListener.getLastEvent()); + } + + /** + */ + public void testNotification_globalProvider_AddNonEmptyProvider() throws Exception { + IProject project = ResourceHelper.createCDTProjectWithConfig(this.getName()); + // First clear default providers + { + // get project descriptions + ICProjectDescription writableProjDescription = CoreModel.getDefault().getProjectDescription(project); + assertNotNull(writableProjDescription); + ICConfigurationDescription[] cfgDescriptions = writableProjDescription.getConfigurations(); + assertEquals(1, cfgDescriptions.length); + ICConfigurationDescription cfgDescription = cfgDescriptions[0]; + + // clear providers + List providers = new ArrayList(); + cfgDescription.setLanguageSettingProviders(providers); + List storedProviders = cfgDescription.getLanguageSettingProviders(); + assertEquals(0, storedProviders.size()); + + // write to project description + CoreModel.getDefault().setProjectDescription(project, writableProjDescription); + } + + // register mock listener to inspect the notifications + LanguageSettingsProvidersSerializer.registerLanguageSettingsChangeListener(mockLseListener); + assertEquals(0, mockLseListener.getCount()); + assertEquals(null, mockLseListener.getLastEvent()); + + // Add non-empty provider + { + // get project descriptions + ICProjectDescription writableProjDescription = CoreModel.getDefault().getProjectDescription(project); + assertNotNull(writableProjDescription); + ICConfigurationDescription[] cfgDescriptions = writableProjDescription.getConfigurations(); + assertEquals(1, cfgDescriptions.length); + ICConfigurationDescription cfgDescription = cfgDescriptions[0]; + String cfgDescriptionId = cfgDescription.getId(); + + // retrieve a global provider + ILanguageSettingsProvider wspProvider = LanguageSettingsManager.getWorkspaceProvider(EXTENSION_EDITABLE_PROVIDER_ID); + assertNotNull(wspProvider); + ILanguageSettingsProvider rawProvider = LanguageSettingsManager.getRawProvider(wspProvider); + assertTrue(rawProvider instanceof MockLanguageSettingsEditableProvider); + ((MockLanguageSettingsEditableProvider) rawProvider).clear(); + // add entries + List entries = new ArrayList(); + entries.add(SAMPLE_LSE); + ((MockLanguageSettingsEditableProvider) rawProvider).setSettingEntries(cfgDescription, project, null, entries); + assertEquals(SAMPLE_LSE, wspProvider.getSettingEntries(cfgDescription, project, null).get(0)); + // add the provider to cfgDescription + List providers = new ArrayList(); + providers.add(wspProvider); + cfgDescription.setLanguageSettingProviders(providers); + List storedProviders = cfgDescription.getLanguageSettingProviders(); + assertEquals(1, storedProviders.size()); + + // write to project description + CoreModel.getDefault().setProjectDescription(project, writableProjDescription); + + // inspect notifications + assertEquals(1, mockLseListener.getCount()); + ILanguageSettingsChangeEvent event = mockLseListener.getLastEvent(); + assertNotNull(event); + + assertEquals(project.getName(), event.getProjectName()); + assertEquals(1, event.getConfigurationDescriptionIds().length); + assertEquals(cfgDescriptionId, event.getConfigurationDescriptionIds()[0]); + assertEquals(1, event.getResources(cfgDescriptionId).length); + assertEquals(project, event.getResources(cfgDescriptionId)[0]); + } + } + + /** + */ + public void testNotification_globalProvider_SerializeEntries() throws Exception { + IProject project = ResourceHelper.createCDTProjectWithConfig(this.getName()); + + // register mock listener to inspect the notifications + LanguageSettingsProvidersSerializer.registerLanguageSettingsChangeListener(mockLseListener); + + // Add empty global provider + { + // get project descriptions + ICProjectDescription writableProjDescription = CoreModel.getDefault().getProjectDescription(project); + assertNotNull(writableProjDescription); + ICConfigurationDescription[] cfgDescriptions = writableProjDescription.getConfigurations(); + assertEquals(1, cfgDescriptions.length); + ICConfigurationDescription cfgDescription = cfgDescriptions[0]; + + // retrieve a global provider + ILanguageSettingsProvider wspProvider = LanguageSettingsManager.getWorkspaceProvider(EXTENSION_EDITABLE_PROVIDER_ID); + assertNotNull(wspProvider); + ILanguageSettingsProvider rawProvider = LanguageSettingsManager.getRawProvider(wspProvider); + assertTrue(rawProvider instanceof MockLanguageSettingsEditableProvider); + // clear it + ((MockLanguageSettingsEditableProvider) rawProvider).clear(); + assertEquals(null, wspProvider.getSettingEntries(cfgDescription, project, null)); + // add the provider to cfgDescription + List providers = new ArrayList(); + providers.add(wspProvider); + cfgDescription.setLanguageSettingProviders(providers); + List storedProviders = cfgDescription.getLanguageSettingProviders(); + assertEquals(1, storedProviders.size()); + + // write to project description + CoreModel.getDefault().setProjectDescription(project, writableProjDescription); + } + + // Change the provider's entries + { + // retrieve a global provider + ILanguageSettingsProvider wspProvider = LanguageSettingsManager.getWorkspaceProvider(EXTENSION_EDITABLE_PROVIDER_ID); + assertNotNull(wspProvider); + ILanguageSettingsProvider rawProvider = LanguageSettingsManager.getRawProvider(wspProvider); + assertTrue(rawProvider instanceof MockLanguageSettingsEditableProvider); + ((MockLanguageSettingsEditableProvider) rawProvider).clear(); + // add entries + List entries = new ArrayList(); + entries.add(SAMPLE_LSE); + ((MockLanguageSettingsEditableProvider) rawProvider).setSettingEntries(null, project, null, entries); + assertEquals(SAMPLE_LSE, wspProvider.getSettingEntries(null, project, null).get(0)); + + // reset count + mockLseListener.resetCount(); + assertEquals(0, mockLseListener.getCount()); + assertEquals(null, mockLseListener.getLastEvent()); + + // Serialize settings + LanguageSettingsProvidersSerializer.serializeLanguageSettingsWorkspace(); + + // get cfgDescriptionId + ICProjectDescription prjDescription = CoreModel.getDefault().getProjectDescription(project, false); + assertNotNull(prjDescription); + ICConfigurationDescription[] cfgDescriptions = prjDescription.getConfigurations(); + assertEquals(1, cfgDescriptions.length); + ICConfigurationDescription cfgDescription = cfgDescriptions[0]; + String cfgDescriptionId = cfgDescription.getId(); + + // inspect event + assertEquals(1, mockLseListener.getCount()); + ILanguageSettingsChangeEvent event = mockLseListener.getLastEvent(); + assertNotNull(event); + + assertEquals(project.getName(), event.getProjectName()); + assertEquals(1, event.getConfigurationDescriptionIds().length); + assertEquals(cfgDescriptionId, event.getConfigurationDescriptionIds()[0]); + assertEquals(1, event.getResources(cfgDescriptionId).length); + assertEquals(project, event.getResources(cfgDescriptionId)[0]); + // TODO - drill to the entries + } + // Change the provider's entries back (bug was found for this case) + { + // retrieve a global provider + ILanguageSettingsProvider wspProvider = LanguageSettingsManager.getWorkspaceProvider(EXTENSION_EDITABLE_PROVIDER_ID); + assertNotNull(wspProvider); + ILanguageSettingsProvider rawProvider = LanguageSettingsManager.getRawProvider(wspProvider); + assertTrue(rawProvider instanceof MockLanguageSettingsEditableProvider); + // clear the provider again + ((MockLanguageSettingsEditableProvider) rawProvider).clear(); + + // reset count + mockLseListener.resetCount(); + assertEquals(0, mockLseListener.getCount()); + assertEquals(null, mockLseListener.getLastEvent()); + + // Serialize settings + LanguageSettingsProvidersSerializer.serializeLanguageSettingsWorkspace(); + + // get cfgDescriptionId + ICProjectDescription prjDescription = CoreModel.getDefault().getProjectDescription(project, false); + assertNotNull(prjDescription); + ICConfigurationDescription[] cfgDescriptions = prjDescription.getConfigurations(); + assertEquals(1, cfgDescriptions.length); + ICConfigurationDescription cfgDescription = cfgDescriptions[0]; + String cfgDescriptionId = cfgDescription.getId(); + + // inspect event + assertEquals(1, mockLseListener.getCount()); + ILanguageSettingsChangeEvent event = mockLseListener.getLastEvent(); + assertNotNull(event); + + assertEquals(project.getName(), event.getProjectName()); + assertEquals(1, event.getConfigurationDescriptionIds().length); + assertEquals(cfgDescriptionId, event.getConfigurationDescriptionIds()[0]); + assertEquals(1, event.getResources(cfgDescriptionId).length); + assertEquals(project, event.getResources(cfgDescriptionId)[0]); + // TODO - drill to the entries + } + } + } diff --git a/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/language/settings/providers/LanguageSettingsManagerTests.java b/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/language/settings/providers/LanguageSettingsManagerTests.java index d6732472b4b..243252ea99c 100644 --- a/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/language/settings/providers/LanguageSettingsManagerTests.java +++ b/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/language/settings/providers/LanguageSettingsManagerTests.java @@ -28,7 +28,7 @@ import org.eclipse.cdt.core.settings.model.ICProjectDescription; import org.eclipse.cdt.core.settings.model.ICSettingEntry; import org.eclipse.cdt.core.testplugin.CModelMock; import org.eclipse.cdt.core.testplugin.ResourceHelper; -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.CConfigurationDescription; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; @@ -561,7 +561,7 @@ public class LanguageSettingsManagerTests extends TestCase { { // retrieve local entries - List includes = LanguageSettingsExtensionManager + List includes = LanguageSettingsProvidersSerializer .getLocalSettingEntriesByKind(cfgDescription, FILE_0, LANG_ID, ICSettingEntry.INCLUDE_PATH); assertEquals(localIncludeEntry, includes.get(0)); assertEquals(1, includes.size()); @@ -569,7 +569,7 @@ public class LanguageSettingsManagerTests extends TestCase { { // retrieve system entries - List includes = LanguageSettingsExtensionManager + List includes = LanguageSettingsProvidersSerializer .getSystemSettingEntriesByKind(cfgDescription, FILE_0, LANG_ID, ICSettingEntry.INCLUDE_PATH); assertEquals(systemIncludeEntry, includes.get(0)); assertEquals(1, includes.size()); @@ -577,7 +577,7 @@ public class LanguageSettingsManagerTests extends TestCase { { // retrieve both local and system - List includes = LanguageSettingsExtensionManager + List includes = LanguageSettingsProvidersSerializer .getSettingEntriesByKind(cfgDescription, FILE_0, LANG_ID, ICSettingEntry.INCLUDE_PATH); assertEquals(entries.get(0), includes.get(0)); assertEquals(entries.get(1), includes.get(1)); @@ -799,7 +799,7 @@ public class LanguageSettingsManagerTests extends TestCase { LanguageSettingsSerializable provider = new LanguageSettingsSerializable(PROVIDER_1, PROVIDER_NAME_1); provider.setSettingEntries(null, file, null, entries); // build the hierarchy - LanguageSettingsExtensionManager.buildResourceTree(provider, null, null, project); + LanguageSettingsProvidersSerializer.buildResourceTree(provider, null, null, project); // check that entries go to highest possible level assertEquals(entries, LanguageSettingsManager.getSettingEntriesUpResourceTree(provider, null, file, null)); diff --git a/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/language/settings/providers/MockLanguageSettingsEditableProvider.java b/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/language/settings/providers/MockLanguageSettingsEditableProvider.java index 7c8c9eaf9dc..32b907c017b 100644 --- a/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/language/settings/providers/MockLanguageSettingsEditableProvider.java +++ b/core/org.eclipse.cdt.core.tests/model/org/eclipse/cdt/core/language/settings/providers/MockLanguageSettingsEditableProvider.java @@ -19,6 +19,10 @@ public class MockLanguageSettingsEditableProvider extends LanguageSettingsSerial super(); } + public MockLanguageSettingsEditableProvider(String id, String name) { + super(id, name); + } + public MockLanguageSettingsEditableProvider cloneShallow() throws CloneNotSupportedException { return (MockLanguageSettingsEditableProvider) super.cloneShallow(); } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/settings/providers/LanguageSettingsManager.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/settings/providers/LanguageSettingsManager.java index fd630a320d6..09d6bb1c910 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/settings/providers/LanguageSettingsManager.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/settings/providers/LanguageSettingsManager.java @@ -54,7 +54,7 @@ public class LanguageSettingsManager { * although individual providers return {@code null} if no settings defined. */ public static List getSettingEntriesUpResourceTree(ILanguageSettingsProvider provider, ICConfigurationDescription cfgDescription, IResource rc, String languageId) { - return LanguageSettingsExtensionManager.getSettingEntriesUpResourceTree(provider, cfgDescription, rc, languageId); + return LanguageSettingsProvidersSerializer.getSettingEntriesUpResourceTree(provider, cfgDescription, rc, languageId); } /** @@ -71,7 +71,7 @@ public class LanguageSettingsManager { * @param project - the project which is considered the root of the resource tree. */ public static void buildResourceTree(LanguageSettingsSerializable provider, ICConfigurationDescription cfgDescription, String languageId, IProject project) { - LanguageSettingsExtensionManager.buildResourceTree(provider, cfgDescription, languageId, project); + LanguageSettingsProvidersSerializer.buildResourceTree(provider, cfgDescription, languageId, project); } @@ -93,7 +93,7 @@ public class LanguageSettingsManager { */ // FIXME: get rid of callers PathEntryTranslator and DescriptionScannerInfoProvider public static List getSettingEntriesByKind(ICConfigurationDescription cfgDescription, IResource rc, String languageId, int kind) { - return LanguageSettingsExtensionManager.getSettingEntriesByKind(cfgDescription, rc, languageId, kind); + return LanguageSettingsProvidersSerializer.getSettingEntriesByKind(cfgDescription, rc, languageId, kind); } /** diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/settings/providers/LanguageSettingsManager_TBD.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/settings/providers/LanguageSettingsManager_TBD.java index b3ba4037be2..39edb52603b 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/settings/providers/LanguageSettingsManager_TBD.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/settings/providers/LanguageSettingsManager_TBD.java @@ -20,7 +20,6 @@ import org.eclipse.cdt.internal.core.language.settings.providers.LanguageSetting import org.eclipse.cdt.internal.core.language.settings.providers.LanguageSettingsProvidersSerializer; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; -import org.eclipse.core.runtime.CoreException; /** * This temporary class keeps the utility methods being looking for better home @@ -53,11 +52,6 @@ public class LanguageSettingsManager_TBD { return false; } - @Deprecated // Shouldn't be API - public static void serializeWorkspaceProviders() throws CoreException { - LanguageSettingsProvidersSerializer.serializeLanguageSettingsWorkspace(); - } - public static boolean isReconfigured(ILanguageSettingsProvider provider) { if (provider instanceof ILanguageSettingsEditableProvider) { try { diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/settings/providers/LanguageSettingsSerializable.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/settings/providers/LanguageSettingsSerializable.java index d9e92b444b4..5c5a31b25b6 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/settings/providers/LanguageSettingsSerializable.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/settings/providers/LanguageSettingsSerializable.java @@ -12,13 +12,9 @@ package org.eclipse.cdt.core.language.settings.providers; import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.Set; import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry; @@ -26,7 +22,7 @@ import org.eclipse.cdt.core.settings.model.ICSettingEntry; import org.eclipse.cdt.core.settings.model.util.CDataUtil; import org.eclipse.cdt.core.settings.model.util.LanguageSettingEntriesSerializer; import org.eclipse.cdt.internal.core.XmlUtil; -import org.eclipse.cdt.internal.core.parser.util.WeakHashSet; +import org.eclipse.cdt.internal.core.language.settings.providers.LanguageSettingsStorage; import org.eclipse.core.resources.IResource; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -45,45 +41,17 @@ public class LanguageSettingsSerializable extends LanguageSettingsBaseProvider { private static final String ATTR_ID = "id"; //$NON-NLS-1$ private static final String ELEM_LANGUAGE_SCOPE = "language-scope"; //$NON-NLS-1$ - private static final String ELEM_LANGUAGE = "language"; //$NON-NLS-1$ - private static final String ELEM_RESOURCE = "resource"; //$NON-NLS-1$ - private static final String ATTR_PROJECT_PATH = "project-relative-path"; //$NON-NLS-1$ - - private static final String ELEM_ENTRY = "entry"; //$NON-NLS-1$ - private static final String ATTR_KIND = "kind"; //$NON-NLS-1$ private static final String ATTR_NAME = "name"; //$NON-NLS-1$ - private static final String ATTR_VALUE = "value"; //$NON-NLS-1$ private static final String ATTR_CLASS = "class"; //$NON-NLS-1$ private static final String ATTR_PARAMETER = "parameter"; //$NON-NLS-1$ - private static final String ELEM_FLAG = "flag"; //$NON-NLS-1$ - private static final String ATTR_STORE_ENTRIES = "store-entries"; //$NON-NLS-1$ private static final String VALUE_WORKSPACE = "workspace"; //$NON-NLS-1$ private static final String VALUE_PROJECT = "project"; //$NON-NLS-1$ - /** - * Pool of LSE lists implemented as WeakHashSet. That allows to gain memory savings - * at the expense of CPU time. WeakHashSet handles garbage collection when a list is not - * referenced anywhere else. See JavaDoc {@link java.lang.ref.WeakReference} about weak reference objects. - */ - private static WeakHashSet> listPool = new WeakHashSet>() { - @Override - public synchronized List add(List list) { - return super.add(list); - } - - }; - /** Tells if language settings entries are persisted with the project or in workspace area while serializing. */ private boolean storeEntriesInProjectArea = false; - /** - * Storage to keep settings entries. Note that it is not necessary to keep configuration in the maps - * as the configuration is always the one provider belongs to. - */ - private Map>> fStorage = new HashMap>>(); + private LanguageSettingsStorage fStorage = new LanguageSettingsStorage(); /** * Default constructor. This constructor has to be always followed with setting id and name of the provider. @@ -185,57 +153,6 @@ public class LanguageSettingsSerializable extends LanguageSettingsBaseProvider { fStorage.clear(); } - /** - * Internal convenience method to set language settings entries. - */ - private void setSettingEntriesInternal(String rcProjectPath, String languageId, List entries) { - if (entries!=null) { - Map> langMap = fStorage.get(languageId); - if (langMap==null) { - langMap = new HashMap>(); - fStorage.put(languageId, langMap); - } - List sortedEntries = listPool.add(Collections.unmodifiableList(sortEntries(entries))); - langMap.put(rcProjectPath, sortedEntries); - } else { - // do not keep nulls in the tables - Map> langMap = fStorage.get(languageId); - if (langMap!=null) { - langMap.remove(rcProjectPath); - if (langMap.size()==0) { - fStorage.remove(languageId); - } - } - } - } - - /** - * Some providers may collect entries in pretty much random order. For the purposes of - * predictability, UI usability and efficient storage the entries are sorted by kinds - * and secondary by name for kinds where the secondary order is not significant. - * - * @param entries - list of entries to sort. - * @return - sorted entries. - */ - protected List sortEntries(List entries) { - List sortedEntries = new ArrayList(entries); - Collections.sort(sortedEntries, new Comparator(){ - /** - * This comparator sorts by kinds first and the macros are sorted additionally by name. - */ - public int compare(ICLanguageSettingEntry entry0, ICLanguageSettingEntry entry1) { - int kind0 = entry0.getKind(); - int kind1 = entry1.getKind(); - if (kind0==ICSettingEntry.MACRO && kind1==ICSettingEntry.MACRO) { - return entry0.getName().compareTo(entry1.getName()); - } - - return kind0 - kind1; - }}); - - return sortedEntries; - } - /** * Sets language settings entries for the provider. * Note that the entries are not persisted at that point. To persist use TODO @@ -248,36 +165,40 @@ public class LanguageSettingsSerializable extends LanguageSettingsBaseProvider { */ public void setSettingEntries(ICConfigurationDescription cfgDescription, IResource rc, String languageId, List entries) { String rcProjectPath = rc!=null ? rc.getProjectRelativePath().toString() : null; - setSettingEntriesInternal(rcProjectPath, languageId, entries); + fStorage.setSettingEntries(rcProjectPath, languageId, entries); + +// // TODO - not sure what is more efficient, to do that or not to do that? +// if (fStorage.equals(lastPersistedState)) { +// lastPersistedState = null; +// } } /** * {@inheritDoc} *
Note that this list is unmodifiable. To modify the list copy it, change and use * {@link #setSettingEntries(ICConfigurationDescription, IResource, String, List)}. - * + * + *
Note also that you can compare these lists with simple equality operator ==, + * as lists themselves are backed by WeakHashSet> where + * identical copies (deep comparison is used) are replaced with the same one instance. */ @Override public List getSettingEntries(ICConfigurationDescription cfgDescription, IResource rc, String languageId) { - Map> langMap = fStorage.get(languageId); - if (langMap!=null) { - String rcProjectPath = rc!=null ? rc.getProjectRelativePath().toString() : null; - List entries = langMap.get(rcProjectPath); - if (entries!=null) - return entries; + List entries = fStorage.getSettingEntries(cfgDescription, rc, languageId); + if (entries == null) { + if (languageId!=null && (languageScope==null || languageScope.contains(languageId))) { + entries = getSettingEntries(cfgDescription, rc, null); + } } - if (languageId!=null && (languageScope==null || languageScope.contains(languageId))) { - List entries = getSettingEntries(cfgDescription, rc, null); - return entries; - } - - return null; + return entries; } /** * Serialize the provider under parent XML element. * This is convenience method not intended to be overridden on purpose. + * Override {@link #serializeAttributes(Element)} or + * {@link #serializeEntries(Element)} instead. * * @param parentElement - element where to serialize. * @return - newly created element. That element will already be @@ -329,98 +250,18 @@ public class LanguageSettingsSerializable extends LanguageSettingsBaseProvider { * @param elementProvider - element where to serialize the entries. */ public void serializeEntries(Element elementProvider) { - for (Entry>> entryLang : fStorage.entrySet()) { - serializeLanguage(elementProvider, entryLang); - } + fStorage.serializeEntries(elementProvider); } - /** - * Serialize the provider entries for a given language list. - */ - private void serializeLanguage(Element parentElement, Entry>> entryLang) { - String langId = entryLang.getKey(); - if (langId!=null) { - Element elementLanguage = XmlUtil.appendElement(parentElement, ELEM_LANGUAGE, new String[] {ATTR_ID, langId}); - parentElement = elementLanguage; - } - for (Entry> entryRc : entryLang.getValue().entrySet()) { - serializeResource(parentElement, entryRc); - } - } - - /** - * Serialize the provider entries for a given resource list. - */ - private void serializeResource(Element parentElement, Entry> entryRc) { - String rcProjectPath = entryRc.getKey(); - if (rcProjectPath!=null) { - Element elementRc = XmlUtil.appendElement(parentElement, ELEM_RESOURCE, new String[] {ATTR_PROJECT_PATH, rcProjectPath}); - parentElement = elementRc; - } - serializeSettingEntries(parentElement, entryRc.getValue()); - } - - /** - * Serialize given settings entries. - */ - private void serializeSettingEntries(Element parentElement, List settingEntries) { - for (ICLanguageSettingEntry entry : settingEntries) { - Element elementSettingEntry = XmlUtil.appendElement(parentElement, ELEM_ENTRY, new String[] { - ATTR_KIND, LanguageSettingEntriesSerializer.kindToString(entry.getKind()), - ATTR_NAME, entry.getName(), - }); - switch(entry.getKind()) { - case ICSettingEntry.MACRO: - elementSettingEntry.setAttribute(ATTR_VALUE, entry.getValue()); - break; -// case ICLanguageSettingEntry.LIBRARY_FILE: -// // TODO: sourceAttachment fields may need to be covered -// break; - } - int flags = entry.getFlags(); - if (flags!=0) { - // Element elementFlag = - XmlUtil.appendElement(elementSettingEntry, ELEM_FLAG, new String[] { - ATTR_VALUE, LanguageSettingEntriesSerializer.composeFlagsString(entry.getFlags()) - }); - } - } - } - - /** - * Load a setting entry from XML element. - */ - private ICLanguageSettingEntry loadSettingEntry(Node parentElement) { - String settingKind = XmlUtil.determineAttributeValue(parentElement, ATTR_KIND); - String settingName = XmlUtil.determineAttributeValue(parentElement, ATTR_NAME); - - NodeList flagNodes = parentElement.getChildNodes(); - int flags = 0; - for (int i=0;i to load provider from. */ - public void load(Element providerNode) { + final public void load(Element providerNode) { fStorage.clear(); languageScope = null; @@ -431,6 +272,18 @@ public class LanguageSettingsSerializable extends LanguageSettingsBaseProvider { } } + /** + * Determine and set language scope from given XML node. + */ + private void loadLanguageScopeElement(Node parentNode) { + if (languageScope==null) { + languageScope = new ArrayList(); + } + String id = XmlUtil.determineAttributeValue(parentNode, ATTR_ID); + languageScope.add(id); + + } + /** * Load attributes from XML provider element. * @param providerNode - XML element to load attributes from. @@ -464,125 +317,9 @@ public class LanguageSettingsSerializable extends LanguageSettingsBaseProvider { * @param providerNode - parent XML element where entries are defined. */ public void loadEntries(Element providerNode) { - List settings = new ArrayList(); - NodeList nodes = providerNode.getChildNodes(); - for (int i=0;i0) { - setSettingEntriesInternal(null, null, settings); - } + fStorage.loadEntries(providerNode); } - - /** - * Determine and set language scope from given XML node. - */ - private void loadLanguageScopeElement(Node parentNode) { - if (languageScope==null) { - languageScope = new ArrayList(); - } - String id = XmlUtil.determineAttributeValue(parentNode, ATTR_ID); - languageScope.add(id); - - } - - /** - * Load entries defined in language element. - */ - private void loadLanguageElement(Node parentNode, String cfgId) { - String langId = XmlUtil.determineAttributeValue(parentNode, ATTR_ID); - if (langId.length()==0) { - langId=null; - } - - List settings = new ArrayList(); - NodeList nodes = parentNode.getChildNodes(); - for (int i=0;i0) { - setSettingEntriesInternal(null, langId, settings); - } - } - - /** - * Load entries defined in resource element. - */ - private void loadResourceElement(Node parentNode, String cfgId, String langId) { - String rcProjectPath = XmlUtil.determineAttributeValue(parentNode, ATTR_PROJECT_PATH); - - List settings = new ArrayList(); - NodeList nodes = parentNode.getChildNodes(); - for (int i=0;i0) { - setSettingEntriesInternal(rcProjectPath, langId, settings); - } - } - - /** - * Clone storage for the entries. Copies references for lists of entries as a whole. - * Note that is OK as the lists kept in storage are unmodifiable. - */ - private Map>> cloneStorage() { - Map>> storageClone = new HashMap>>(); - Set>>> entrySetLang = fStorage.entrySet(); - for (Entry>> entryLang : entrySetLang) { - String langId = entryLang.getKey(); - Map> mapRc = entryLang.getValue(); - Map> mapRcClone = new HashMap>(); - Set>> entrySetRc = mapRc.entrySet(); - for (Entry> entryRc : entrySetRc) { - String rcProjectPath = entryRc.getKey(); - List lsEntries = entryRc.getValue(); - // don't need to clone entries, they are from the LSE pool - mapRcClone.put(rcProjectPath, lsEntries); - } - storageClone.put(langId, mapRcClone); - } - return storageClone; - } - + /** * See {@link #cloneShallow()}. This method is extracted * to avoid expressing {@link #clone()} via {@link #cloneShallow()}. @@ -592,7 +329,7 @@ public class LanguageSettingsSerializable extends LanguageSettingsBaseProvider { if (languageScope!=null) clone.languageScope = new ArrayList(languageScope); - clone.fStorage = new HashMap>>(); + clone.fStorage = new LanguageSettingsStorage(); return clone; } @@ -610,7 +347,7 @@ public class LanguageSettingsSerializable extends LanguageSettingsBaseProvider { @Override protected LanguageSettingsSerializable clone() throws CloneNotSupportedException { LanguageSettingsSerializable clone = cloneShallowInternal(); - clone.fStorage = cloneStorage(); + clone.fStorage = fStorage.cloneStorage(); return clone; } @@ -680,4 +417,11 @@ public class LanguageSettingsSerializable extends LanguageSettingsBaseProvider { return false; return true; } + + /** + * @noreference This method is not intended to be referenced by clients. + */ + public LanguageSettingsStorage getStorageInternal() { + return fStorage; + } } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/settings/providers/LanguageSettingsSerializableEditable.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/settings/providers/LanguageSettingsSerializableEditable.java index 5454e7ea697..22465b7b6e4 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/settings/providers/LanguageSettingsSerializableEditable.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/settings/providers/LanguageSettingsSerializableEditable.java @@ -13,7 +13,8 @@ package org.eclipse.cdt.core.language.settings.providers; // TODO: move ILanguageSettingsEditableProvider here -public class LanguageSettingsSerializableEditable extends LanguageSettingsSerializable implements ILanguageSettingsEditableProvider { +// TODO this one is unused - remove +final public class LanguageSettingsSerializableEditable extends LanguageSettingsSerializable implements ILanguageSettingsEditableProvider { @Override public LanguageSettingsSerializableEditable clone() throws CloneNotSupportedException { return (LanguageSettingsSerializableEditable) super.clone(); diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/settings/model/ICConfigurationDescription.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/settings/model/ICConfigurationDescription.java index e58bc9ad55a..febe5a589ed 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/settings/model/ICConfigurationDescription.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/settings/model/ICConfigurationDescription.java @@ -395,6 +395,8 @@ public interface ICConfigurationDescription extends ICSettingContainer, ICSettin * or preprocessor macros. * * @param providers the list of providers to assign to the configuration description. + * Warning: the providers will be cloned before actual addition to the project model + * due to TODO - very important reason but I forgot why by now. * * @since 6.0 */ diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/settings/providers/ILanguageSettingsChangeEvent.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/settings/providers/ILanguageSettingsChangeEvent.java new file mode 100644 index 00000000000..c609aad9a07 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/settings/providers/ILanguageSettingsChangeEvent.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2011, 2011 Andrew Gvozdev and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrew Gvozdev - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.language.settings.providers; + +import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry; +import org.eclipse.core.resources.IResource; + +/** + * Contains the details of changes that occurred as a result of modifying + * language settings entries {@link ICLanguageSettingEntry}. + * + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ +public interface ILanguageSettingsChangeEvent { + public String getProjectName(); + + public String[] getConfigurationDescriptionIds(); + + public IResource[] getResources(String cfgDescriptionId); + +// // AG - YAGNI +// public List getSettingEntriesOld(ICConfigurationDescription cfgDescription, IResource rc, String languageId); +// public List getSettingEntriesNew(ICConfigurationDescription cfgDescription, IResource rc, String languageId); +// // AG - or maybe +// ILanguageSettingsDelta getDelta(ICConfigurationDescription cfgDescription); + +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/settings/providers/ILanguageSettingsChangeListener.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/settings/providers/ILanguageSettingsChangeListener.java new file mode 100644 index 00000000000..9b54debd6ef --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/settings/providers/ILanguageSettingsChangeListener.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2011, 2011 Andrew Gvozdev and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrew Gvozdev - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.language.settings.providers; + +/** + * Listens to changes in language settings. + */ +public interface ILanguageSettingsChangeListener { + /** + * Indicates that language settings have been changed. + * @param event + */ + public void handleEvent(ILanguageSettingsChangeEvent event); +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/settings/providers/LanguageSettingsDelta.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/settings/providers/LanguageSettingsDelta.java new file mode 100644 index 00000000000..3cc23505630 --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/settings/providers/LanguageSettingsDelta.java @@ -0,0 +1,155 @@ +/******************************************************************************* + * Copyright (c) 2011, 2011 Andrew Gvozdev and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrew Gvozdev - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.language.settings.providers; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; +import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry; +import org.eclipse.cdt.core.settings.model.ICSettingEntry; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.runtime.Assert; + + +// TODO possibly make an interface from that +public class LanguageSettingsDelta { + // maps need to be ordered by providers + private LinkedHashMap oldLanguageSettingsState; + private LinkedHashMap newLanguageSettingsState; + + public LanguageSettingsDelta(LinkedHashMap oldState, LinkedHashMap newState) { + oldLanguageSettingsState = oldState; + newLanguageSettingsState = newState; + } + + // FIXME - this API is no good + public Set getChangedResources(IProject project, ICConfigurationDescription cfgDescription) { + Set resources = new HashSet(); + + // Ordered collections + Collection oldStateStorages = oldLanguageSettingsState.values(); + Collection newStateStorages = newLanguageSettingsState.values(); + + for (LanguageSettingsStorage lss : oldStateStorages) { +// Map>> + Map>> mapInternal = lss.getMapInternal(); + synchronized (mapInternal) { + for (Entry>> entryLang : mapInternal.entrySet()) { + String langId = entryLang.getKey(); + for (Entry> entryRc : entryLang.getValue().entrySet()) { + String rcName = entryRc.getKey(); + IResource rc = (rcName != null) ? project.findMember(rcName) : project; + if (resources.contains(rc)) + continue; + + List lsEntriesOld = entryRc.getValue(); + List lsEntriesNew = getSettingEntries(newStateStorages, cfgDescription, rc, langId); + + if (!lsEntriesNew.equals(lsEntriesOld) && !(lsEntriesOld==null && lsEntriesNew.size()==0)) { + resources.add(rc); + } + } + } + } + } + for (LanguageSettingsStorage lss : newStateStorages) { +// Map>> + Map>> mapInternal = lss.getMapInternal(); + synchronized (mapInternal) { + for (Entry>> entryLang : mapInternal.entrySet()) { + String langId = entryLang.getKey(); + for (Entry> entryRc : entryLang.getValue().entrySet()) { + String rcName = entryRc.getKey(); + IResource rc = (rcName != null) ? project.findMember(rcName) : project; + if (resources.contains(rc)) + continue; + + List lsEntriesNew = entryRc.getValue(); + List lsEntriesOld = getSettingEntries(oldStateStorages, cfgDescription, rc, langId); + + if (!lsEntriesOld.equals(lsEntriesNew) && !(lsEntriesNew==null && lsEntriesOld.size()==0)) { + resources.add(rc); + } + } + } + } + } + + return resources; + } + + private static boolean checkBit(int flags, int bit) { + return (flags & bit) == bit; + } + + private static List getSettingEntries(Collection stores, ICConfigurationDescription cfgDescription, IResource rc, String languageId) { + List entries = new ArrayList(); + List alreadyAdded = new ArrayList(); + + for (LanguageSettingsStorage store: stores) { + List providerEntries = getSettingEntriesUpResourceTree(store, cfgDescription, rc, languageId); + for (ICLanguageSettingEntry entry : providerEntries) { + if (entry!=null) { + String entryName = entry.getName(); + // Only first entry is considered + // Entry flagged as "UNDEFINED" prevents adding entry with the same name down the line + if (!alreadyAdded.contains(entryName)) { + int flags = entry.getFlags(); + if (!checkBit(flags, ICSettingEntry.UNDEFINED)) { + entries.add(entry); + } + alreadyAdded.add(entryName); + } + } + } + } + + return entries; + } + + private static List getSettingEntriesUpResourceTree(LanguageSettingsStorage store, ICConfigurationDescription cfgDescription, IResource rc, String languageId) { + Assert.isTrue( !(rc instanceof IWorkspaceRoot) ); + if (store!=null) { + List entries = store.getSettingEntries(cfgDescription, rc, languageId); + if (entries!=null) { + return new ArrayList(entries); + } + if (rc!=null) { + IResource parentFolder = (rc instanceof IProject) ? null : rc.getParent(); + if (parentFolder!=null) { + return getSettingEntriesUpResourceTree(store, cfgDescription, parentFolder, languageId); + } + // if out of parent resources - get default entries for the applicable language scope + entries = store.getSettingEntries(null, null, languageId); + if (entries!=null) { + return new ArrayList(entries); + } + } + } + + return new ArrayList(0); + } +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/settings/providers/LanguageSettingsExtensionManager.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/settings/providers/LanguageSettingsExtensionManager.java index 900c062954e..9d7eff5361c 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/settings/providers/LanguageSettingsExtensionManager.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/settings/providers/LanguageSettingsExtensionManager.java @@ -13,10 +13,8 @@ package org.eclipse.cdt.internal.core.language.settings.providers; import java.util.ArrayList; import java.util.Comparator; -import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; -import java.util.Map; import java.util.Set; import java.util.TreeSet; @@ -26,19 +24,9 @@ import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsEditabl 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.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.ICSettingEntry; import org.eclipse.cdt.core.settings.model.util.CDataUtil; import org.eclipse.cdt.core.settings.model.util.LanguageSettingEntriesSerializer; -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.IWorkspaceRoot; -import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExtension; @@ -340,267 +328,6 @@ public class LanguageSettingsExtensionManager { return list; } - private static List safeGetSettingEntries(ILanguageSettingsProvider provider, - ICConfigurationDescription cfgDescription, IResource rc, String languageId) { - - try { - return provider.getSettingEntries(cfgDescription, rc, languageId); - } catch (Throwable e) { - String cfgId = cfgDescription!=null ? cfgDescription.getId() : null; - String msg = "Exception in provider "+provider.getId()+": getSettingEntries("+cfgId+", "+rc+", "+languageId+")"; - CCorePlugin.log(msg, e); - // return empty array to prevent climbing up the resource tree - return new ArrayList(0); - } - } - - /** - * Returns the list of setting entries of the given provider - * for the given configuration description, resource and language. - * This method reaches to the parent folder of the resource recursively - * in case the resource does not define the entries for the given provider. - * - * @param provider - language settings provider. - * @param cfgDescription - configuration description. - * @param rc - resource such as file or folder. - * @param languageId - language id. - * - * @return the list of setting entries. Never returns {@code null} - * although individual providers mandated to return {@code null} if no settings defined. - */ - public static List getSettingEntriesUpResourceTree(ILanguageSettingsProvider provider, ICConfigurationDescription cfgDescription, IResource rc, String languageId) { - Assert.isTrue( !(rc instanceof IWorkspaceRoot) ); - if (provider!=null) { - List entries = safeGetSettingEntries(provider, cfgDescription, rc, languageId); - if (entries!=null) { - return new ArrayList(entries); - } - if (rc!=null) { - IResource parentFolder = (rc instanceof IProject) ? null : rc.getParent(); - if (parentFolder!=null) { - return getSettingEntriesUpResourceTree(provider, cfgDescription, parentFolder, languageId); - } - // if out of parent resources - get default entries for the applicable language scope - entries = safeGetSettingEntries(provider, null, null, languageId); - if (entries!=null) { - return new ArrayList(entries); - } - } - } - - return new ArrayList(0); - } - - /** - * Builds for the provider a nice looking resource tree to present hierarchical view to the user. - * Note that it is not advisable to "compact" the tree because of potential loss of information - * which is especially important during partial or incremental builds. - * - * @param provider - language settings provider to build the tree for. - * @param cfgDescription - configuration description. - * @param languageId - language ID. - * @param folder - container where the tree roots. - */ - public static void buildResourceTree(LanguageSettingsSerializable provider, ICConfigurationDescription cfgDescription, String languageId, IContainer folder) { - IResource[] members = null; - try { - members = folder.members(); - } catch (Exception e) { - CCorePlugin.log(e); - } - if (members==null) - return; - - for (IResource rc : members) { - if (rc instanceof IContainer) { - buildResourceTree(provider, cfgDescription, languageId, (IContainer) rc); - } - } - - int rcNumber = members.length; - - Map, Integer> listMap = new HashMap, Integer>(); - - // on the first pass find majority entries - List majorityEntries = null; - List candidate = null; - int candidateCount = 0; - for (IResource rc : members) { - if (!isLanguageInScope(rc, cfgDescription, languageId)) { - rcNumber--; - } else { - List entries = provider.getSettingEntries(null, rc, languageId); - if (entries==null && rc instanceof IContainer) { - rcNumber--; - } else { - Integer count = listMap.get(entries); - if (count==null) { - count = 0; - } - count++; - - if (count>candidateCount) { - candidateCount = count; - candidate = entries; - } - - listMap.put(entries, count); - } - } - - if (candidateCount > rcNumber/2) { - majorityEntries = candidate; - break; - } - } - - if (majorityEntries!=null) { - provider.setSettingEntries(cfgDescription, folder, languageId, majorityEntries); - } - - // second pass - assign the entries to the folders - for (IResource rc : members) { - List entries = provider.getSettingEntries(null, rc, languageId); - if (entries!=null && entries==majorityEntries) { - if (!(rc instanceof IFile)) { // preserve information which files were collected - provider.setSettingEntries(cfgDescription, rc, languageId, null); - } - } - } - } - - private static boolean isLanguageInScope(IResource rc, ICConfigurationDescription cfgDescription, String languageId) { - if (rc instanceof IFile) { - ILanguage lang = null; - try { - lang = LanguageManager.getInstance().getLanguageForFile((IFile) rc, cfgDescription); - } catch (CoreException e) { - CCorePlugin.log("Error loading language settings providers extensions", e); //$NON-NLS-1$ - } - if (lang==null || (languageId!=null && !languageId.equals(lang.getId()))) { - return false; - } - } - return true; - } - - private static boolean checkBit(int flags, int bit) { - return (flags & bit) == bit; - } - - /** - * Returns the list of setting entries of a certain kind (such as include paths) - * for the given configuration description, resource and language. This is a - * combined list for all providers taking into account settings of parent folder - * if settings for the given resource are not defined. - * - * @param cfgDescription - configuration description. - * @param rc - resource such as file or folder. - * @param languageId - language id. - * @param kind - kind of language settings entries, such as - * {@link ICSettingEntry#INCLUDE_PATH} etc. This is a binary flag - * and it is possible to specify composite kind. - * Use {@link ICSettingEntry#ALL} to get all kinds. - * @param checkLocality - specifies if parameter {@code isLocal} should be considered. - * @param isLocal - {@code true} if "local" entries should be provided and - * {@code false} for "system" entries. This makes sense for include paths where - * [#include "..."] is "local" and [#include <...>] is system. - * - * @return the list of setting entries found. - */ - private static List getSettingEntriesByKind(ICConfigurationDescription cfgDescription, - IResource rc, String languageId, int kind, boolean checkLocality, boolean isLocal) { - - List entries = new ArrayList(); - List alreadyAdded = new ArrayList(); - - List providers = cfgDescription.getLanguageSettingProviders(); - for (ILanguageSettingsProvider provider: providers) { - List providerEntries = getSettingEntriesUpResourceTree(provider, cfgDescription, rc, languageId); - for (ICLanguageSettingEntry entry : providerEntries) { - if (entry!=null) { - String entryName = entry.getName(); - boolean isRightKind = (entry.getKind() & kind) != 0; - // Only first entry is considered - // Entry flagged as "UNDEFINED" prevents adding entry with the same name down the line - if (isRightKind && !alreadyAdded.contains(entryName)) { - int flags = entry.getFlags(); - boolean isRightLocal = !checkLocality || (checkBit(flags, ICSettingEntry.LOCAL) == isLocal); - if (isRightLocal) { - if (!checkBit(flags, ICSettingEntry.UNDEFINED)) { - entries.add(entry); - } - alreadyAdded.add(entryName); - } - } - } - } - } - - return entries; - } - - /** - * Returns the list of setting entries of a certain kind (such as include paths) - * for the given configuration description, resource and language. This is a - * combined list for all providers taking into account settings of parent folder - * if settings for the given resource are not defined. For include paths both - * local (#include "...") and system (#include <...>) entries are returned. - * - * @param cfgDescription - configuration description. - * @param rc - resource such as file or folder. - * @param languageId - language id. - * @param kind - kind of language settings entries, such as - * {@link ICSettingEntry#INCLUDE_PATH} etc. This is a binary flag - * and it is possible to specify composite kind. - * Use {@link ICSettingEntry#ALL} to get all kinds. - * - * @return the list of setting entries. - */ - public static List getSettingEntriesByKind(ICConfigurationDescription cfgDescription, IResource rc, String languageId, int kind) { - return getSettingEntriesByKind(cfgDescription, rc, languageId, kind, /* checkLocality */ false, /* isLocal */ false); - } - - /** - * Returns the list of "system" (such as [#include <...>]) setting entries of a certain kind - * for the given configuration description, resource and language. This is a - * combined list for all providers taking into account settings of parent folder - * if settings for the given resource are not defined. - * - * @param cfgDescription - configuration description. - * @param rc - resource such as file or folder. - * @param languageId - language id. - * @param kind - kind of language settings entries, such as - * {@link ICSettingEntry#INCLUDE_PATH} etc. This is a binary flag - * and it is possible to specify composite kind. - * Use {@link ICSettingEntry#ALL} to get all kinds. - * - * @return the list of setting entries. - */ - public static List getSystemSettingEntriesByKind(ICConfigurationDescription cfgDescription, IResource rc, String languageId, int kind) { - return getSettingEntriesByKind(cfgDescription, rc, languageId, kind, /* checkLocality */ true, /* isLocal */ false); - } - - /** - * Returns the list of "local" (such as [#include "..."]) setting entries of a certain kind - * for the given configuration description, resource and language. This is a - * combined list for all providers taking into account settings of parent folder - * if settings for the given resource are not defined. - * - * @param cfgDescription - configuration description. - * @param rc - resource such as file or folder. - * @param languageId - language id. - * @param kind - kind of language settings entries, such as - * {@link ICSettingEntry#INCLUDE_PATH} etc. This is a binary flag - * and it is possible to specify composite kind. - * Use {@link ICSettingEntry#ALL} to get all kinds. - * - * @return the list of setting entries. - */ - public static List getLocalSettingEntriesByKind(ICConfigurationDescription cfgDescription, IResource rc, String languageId, int kind) { - return getSettingEntriesByKind(cfgDescription, rc, languageId, kind, /* checkLocality */ true, /* isLocal */ true); - } - public static boolean equalsExtensionProviderShallow(ILanguageSettingsEditableProvider provider) throws CloneNotSupportedException { String id = provider.getId(); ILanguageSettingsProvider extensionProviderShallow = getExtensionProviderShallow(id); diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/settings/providers/LanguageSettingsProvidersSerializer.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/settings/providers/LanguageSettingsProvidersSerializer.java index 1e5852a9194..12450b5784d 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/settings/providers/LanguageSettingsProvidersSerializer.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/settings/providers/LanguageSettingsProvidersSerializer.java @@ -25,19 +25,29 @@ import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsProvide 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.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.internal.core.XmlUtil; +import org.eclipse.cdt.internal.core.settings.model.CConfigurationSpecSettings; +import org.eclipse.cdt.internal.core.settings.model.CProjectDescriptionManager; +import org.eclipse.cdt.internal.core.settings.model.IInternalCCfgInfo; import org.eclipse.core.filesystem.URIUtil; +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.IResource; +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.IPath; import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.ListenerList; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.ILock; import org.eclipse.core.runtime.jobs.Job; @@ -61,11 +71,15 @@ public class LanguageSettingsProvidersSerializer { private static final String ELEM_CONFIGURATION = "configuration"; //$NON-NLS-1$ private static final String ELEM_PROVIDER = "provider"; //$NON-NLS-1$ private static final String ELEM_PROVIDER_REFERENCE = "provider-reference"; //$NON-NLS-1$ + private static ILock serializingLock = Job.getJobManager().newLock(); + /** Cache of globally available providers to be consumed by calling clients */ private static Map rawGlobalWorkspaceProviders = new HashMap(); private static Map globalWorkspaceProviders = new HashMap(); + private static ListenerList fLanguageSettingsChangeListeners = new ListenerList(ListenerList.IDENTITY); + private static class ListenerAssociation { private ICListenerRegisterer listener; private ICConfigurationDescription cfgDescription; @@ -161,6 +175,75 @@ public class LanguageSettingsProvidersSerializer { } } + private static class LanguageSettingsChangeEvent implements ILanguageSettingsChangeEvent { + private String projectName = null; + private Map deltaMap = new HashMap(); + + private IResource[] resources = null; + + /** + * The act of creating event resets internal delta count in configuration state. + * That implies that when the event is retrieved it must be fired or delta will go missing. + * That side effect is here to ensure atomic processing of firing & resetting the delta. + */ + public LanguageSettingsChangeEvent(ICProjectDescription prjDescription) { + Assert.isTrue(prjDescription.isReadOnly()); + + projectName = prjDescription.getName(); + ICConfigurationDescription[] cfgDescriptions = prjDescription.getConfigurations(); + for (ICConfigurationDescription cfgDescription : cfgDescriptions) { + if (cfgDescription instanceof IInternalCCfgInfo) { + CConfigurationSpecSettings specSettings = null; + try { + specSettings = ((IInternalCCfgInfo) cfgDescription).getSpecSettings(); + } catch (CoreException e) { + CCorePlugin.log(e); + } + if (specSettings != null) { + LanguageSettingsDelta delta = specSettings.dropDelta(); + if (delta != null) + deltaMap.put(cfgDescription.getId(), delta); + } else { + IStatus ss = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, "Internal error: Missing specSettings for " + cfgDescription.getClass().getSimpleName()); + CCorePlugin.log(new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, ss.getMessage(), new CoreException(ss))); + } + } + + } + } + + public String getProjectName() { + return projectName; + } + + public String[] getConfigurationDescriptionIds() { + String[] ids = deltaMap.keySet().toArray(new String[deltaMap.size()]); + return ids; + } + + public IResource[] getResources(String cfgDescriptionId) { + if (resources == null) { + LanguageSettingsDelta delta = deltaMap.get(cfgDescriptionId); + if (delta == null) { + resources = new IResource[0]; + } else { + IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); + ICProjectDescription prjDescription = CProjectDescriptionManager.getInstance().getProjectDescription(project, false); + ICConfigurationDescription cfgDescription = prjDescription.getDefaultSettingConfiguration(); + resources = delta.getChangedResources(project, cfgDescription).toArray(new IResource[0]); + } + } + + return resources; + } + + @Override + public String toString() { + return "LanguageSettingsChangeEvent for project=[" + getProjectName() + "]" + + ", configurations=" + deltaMap.keySet() + ; + } + } /** static initializer */ static { @@ -261,24 +344,66 @@ public class LanguageSettingsProvidersSerializer { rawGlobalWorkspaceProviders = rawWorkspaceProviders; } + private static List createLanguageLettingsChangeEvents(List serializableProviders) { + List events = new ArrayList(); + + List serializableIds = new ArrayList(); + for (LanguageSettingsSerializable provider : serializableProviders) { + serializableIds.add(provider.getId()); + } + + IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); + IProject[] projects = root.getProjects(); +projects: + for (IProject project : projects) { + if (project.isAccessible()) { + ICProjectDescription prjDescription = CCorePlugin.getDefault().getProjectDescription(project, false); + if (prjDescription != null) { + ICConfigurationDescription[] cfgDescriptions = prjDescription.getConfigurations(); + for (ICConfigurationDescription cfgDescription : cfgDescriptions) { + for (ILanguageSettingsProvider provider : cfgDescription.getLanguageSettingProviders()) { + if (isWorkspaceProvider(provider) && serializableIds.contains(provider.getId())) { + LanguageSettingsChangeEvent event = new LanguageSettingsChangeEvent(prjDescription); + if (event.getConfigurationDescriptionIds().length > 0) { + events.add(event); + } + continue projects; + } + } + } + } + } + + } + + return events; + } + public static void serializeLanguageSettingsWorkspace() throws CoreException { + // AG TODO - remove the log + CCorePlugin.log(new Status(IStatus.WARNING, CCorePlugin.PLUGIN_ID, IStatus.OK, + "LanguageSettingsProvidersSerializer.serializeLanguageSettingsWorkspace()", new Exception())); + URI uriStoreWsp = getStoreInWorkspaceArea(STORAGE_WORKSPACE_LANGUAGE_SETTINGS); - List serializableExtensionProviders = new ArrayList(); + List serializableWorkspaceProviders = new ArrayList(); for (ILanguageSettingsProvider provider : rawGlobalWorkspaceProviders.values()) { if (provider instanceof LanguageSettingsSerializable) { // serialize all editable providers which are different from corresponding extension // and serialize all serializable ones that are not editable (those are singletons and we don't know whether they changed) if (!(provider instanceof ILanguageSettingsEditableProvider) || !LanguageSettingsExtensionManager.equalsExtensionProvider(provider)) { - serializableExtensionProviders.add((LanguageSettingsSerializable)provider); + serializableWorkspaceProviders.add((LanguageSettingsSerializable)provider); } } } try { - if (serializableExtensionProviders.isEmpty()) { + List events = null; + if (serializableWorkspaceProviders.isEmpty()) { java.io.File fileStoreWsp = new java.io.File(uriStoreWsp); - serializingLock.acquire(); try { + serializingLock.acquire(); fileStoreWsp.delete(); + // manufacture events while inside the lock + events = createLanguageLettingsChangeEvents(serializableWorkspaceProviders); } finally { serializingLock.release(); } @@ -287,17 +412,23 @@ public class LanguageSettingsProvidersSerializer { Element rootElement = XmlUtil.appendElement(doc, ELEM_PLUGIN); Element elementExtension = XmlUtil.appendElement(rootElement, ELEM_EXTENSION, new String[] {ATTR_POINT, LanguageSettingsExtensionManager.PROVIDER_EXTENSION_FULL_ID}); - for (LanguageSettingsSerializable provider : serializableExtensionProviders) { + for (LanguageSettingsSerializable provider : serializableWorkspaceProviders) { provider.serialize(elementExtension); } - serializingLock.acquire(); try { + serializingLock.acquire(); XmlUtil.serializeXml(doc, uriStoreWsp); + // manufacture events while inside the lock + events = createLanguageLettingsChangeEvents(serializableWorkspaceProviders); } finally { serializingLock.release(); } } + // notify the listeners outside the lock + for (LanguageSettingsChangeEvent event : events) { + notifyLanguageSettingsChangeListeners(event); + } } catch (Exception e) { CCorePlugin.log("Internal error while trying to serialize language settings", e); //$NON-NLS-1$ @@ -414,6 +545,10 @@ public class LanguageSettingsProvidersSerializer { public static void serializeLanguageSettings(ICProjectDescription prjDescription) throws CoreException { IProject project = prjDescription.getProject(); + // AG TODO - remove the log + CCorePlugin.log(new Status(IStatus.WARNING, CCorePlugin.PLUGIN_ID, IStatus.OK, + "LanguageSettingsProvidersSerializer.serializeLanguageSettings() for " + project, new Exception())); + try { // Document to store in project area Document docStorePrj = XmlUtil.newDocument(); @@ -422,26 +557,37 @@ public class LanguageSettingsProvidersSerializer { Document docStoreWsp = XmlUtil.newDocument(); Element projectElementStoreWsp = XmlUtil.appendElement(docStoreWsp, ELEM_PROJECT); - serializeLanguageSettingsInternal(projectElementStorePrj, projectElementStoreWsp, prjDescription); - - IFile fileStorePrj = getStoreInProjectArea(project); // The project store should not be absent. Absent store means legacy project, not 0 providers. - XmlUtil.serializeXml(docStorePrj, fileStorePrj); + IFile fileStorePrj = getStoreInProjectArea(project); + + URI uriStoreWsp = getStoreInWorkspaceArea(project.getName()+'.'+STORAGE_WORKSPACE_LANGUAGE_SETTINGS); + LanguageSettingsChangeEvent event = null; - URI uriStoreWsp = null; - boolean isWorkspaceStoreEmpty = projectElementStoreWsp.getChildNodes().getLength() == 0; - uriStoreWsp = getStoreInWorkspaceArea(project.getName()+'.'+STORAGE_WORKSPACE_LANGUAGE_SETTINGS); - serializingLock.acquire(); try { + serializingLock.acquire(); + + // Note that need for serialization may exist even if LSE event delta is empty, + // as number or properties of providers may differ + serializeLanguageSettingsInternal(projectElementStorePrj, projectElementStoreWsp, prjDescription); + XmlUtil.serializeXml(docStorePrj, fileStorePrj); + // project-specific location in workspace area + boolean isWorkspaceStoreEmpty = projectElementStoreWsp.getChildNodes().getLength() == 0; if (!isWorkspaceStoreEmpty) { XmlUtil.serializeXml(docStoreWsp, uriStoreWsp); } else { new java.io.File(uriStoreWsp).delete(); } + + // manufacture the event only if serialization was successful + event = new LanguageSettingsChangeEvent(prjDescription); } finally { serializingLock.release(); } + // notify the listeners outside the lock + if (event.getConfigurationDescriptionIds().length > 0) { + notifyLanguageSettingsChangeListeners(event); + } } catch (Exception e) { IStatus s = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, "Internal error while trying to serialize language settings", e); @@ -510,8 +656,16 @@ public class LanguageSettingsProvidersSerializer { } ICConfigurationDescription cfgDescription = prjDescription.getConfigurationById(cfgId); - if (cfgDescription!=null) + if (cfgDescription!=null) { cfgDescription.setLanguageSettingProviders(providers); + if (cfgDescription instanceof IInternalCCfgInfo) { + try { + ((IInternalCCfgInfo) cfgDescription).getSpecSettings().dropDelta(); + } catch (CoreException e) { + CCorePlugin.log(e); + } + } + } } } @@ -839,8 +993,9 @@ public class LanguageSettingsProvidersSerializer { 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)); + IStatus status = new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, Status.OK, + "Not able to clone provider " + provider.getClass(), e); + CCorePlugin.log(status); } } newProviders.add(provider); @@ -848,4 +1003,300 @@ public class LanguageSettingsProvidersSerializer { return new ArrayList(newProviders); } + /** + * Adds a listener that will be notified of changes in language settings. + * + * @param listener the ILanguageMappingChangeListener to add + */ + public static void registerLanguageSettingsChangeListener(ILanguageSettingsChangeListener listener) { + fLanguageSettingsChangeListeners.add(listener); + } + + /** + * Removes a language settings change listener. + * + * @param listener the ILanguageMappingChangeListener to remove. + */ + public static void unregisterLanguageSettingsChangeListener(ILanguageSettingsChangeListener listener) { + fLanguageSettingsChangeListeners.remove(listener); + } + + /** + * Notifies all language settings change listeners of a change. + * + * @param event the ILanguageSettingsChangeEvent event to be broadcast. + */ + public static void notifyLanguageSettingsChangeListeners(ILanguageSettingsChangeEvent event) { + // AG TODO - remove the log + CCorePlugin.log(new Status(IStatus.WARNING, CCorePlugin.PLUGIN_ID, IStatus.OK, + "Firing " + event, new Exception())); + + Object[] listeners = fLanguageSettingsChangeListeners.getListeners(); + for (Object obj : listeners) { + ILanguageSettingsChangeListener listener = (ILanguageSettingsChangeListener) obj; + listener.handleEvent(event); + } + } + + private static List safeGetSettingEntries(ILanguageSettingsProvider provider, + ICConfigurationDescription cfgDescription, IResource rc, String languageId) { + + try { + return provider.getSettingEntries(cfgDescription, rc, languageId); + } catch (Throwable e) { + String cfgId = cfgDescription!=null ? cfgDescription.getId() : null; + String msg = "Exception in provider "+provider.getId()+": getSettingEntries("+cfgId+", "+rc+", "+languageId+")"; + CCorePlugin.log(msg, e); + // return empty array to prevent climbing up the resource tree + return new ArrayList(0); + } + } + + /** + * Returns the list of setting entries of the given provider + * for the given configuration description, resource and language. + * This method reaches to the parent folder of the resource recursively + * in case the resource does not define the entries for the given provider. + * + * @param provider - language settings provider. + * @param cfgDescription - configuration description. + * @param rc - resource such as file or folder. + * @param languageId - language id. + * + * @return the list of setting entries. Never returns {@code null} + * although individual providers mandated to return {@code null} if no settings defined. + */ + public static List getSettingEntriesUpResourceTree(ILanguageSettingsProvider provider, ICConfigurationDescription cfgDescription, IResource rc, String languageId) { + Assert.isTrue( !(rc instanceof IWorkspaceRoot) ); + if (provider!=null) { + List entries = safeGetSettingEntries(provider, cfgDescription, rc, languageId); + if (entries!=null) { + return new ArrayList(entries); + } + if (rc!=null) { + IResource parentFolder = (rc instanceof IProject) ? null : rc.getParent(); + if (parentFolder!=null) { + return getSettingEntriesUpResourceTree(provider, cfgDescription, parentFolder, languageId); + } + // if out of parent resources - get default entries for the applicable language scope + entries = safeGetSettingEntries(provider, null, null, languageId); + if (entries!=null) { + return new ArrayList(entries); + } + } + } + + return new ArrayList(0); + } + + /** + * Builds for the provider a nice looking resource tree to present hierarchical view to the user. + * Note that it is not advisable to "compact" the tree because of potential loss of information + * which is especially important during partial or incremental builds. + * + * @param provider - language settings provider to build the tree for. + * @param cfgDescription - configuration description. + * @param languageId - language ID. + * @param folder - container where the tree roots. + */ + public static void buildResourceTree(LanguageSettingsSerializable provider, ICConfigurationDescription cfgDescription, String languageId, IContainer folder) { + IResource[] members = null; + try { + members = folder.members(); + } catch (Exception e) { + CCorePlugin.log(e); + } + if (members==null) + return; + + for (IResource rc : members) { + if (rc instanceof IContainer) { + buildResourceTree(provider, cfgDescription, languageId, (IContainer) rc); + } + } + + int rcNumber = members.length; + + Map, Integer> listMap = new HashMap, Integer>(); + + // on the first pass find majority entries + List majorityEntries = null; + List candidate = null; + int candidateCount = 0; + for (IResource rc : members) { + if (!isLanguageInScope(rc, cfgDescription, languageId)) { + rcNumber--; + } else { + List entries = provider.getSettingEntries(null, rc, languageId); + if (entries==null && rc instanceof IContainer) { + rcNumber--; + } else { + Integer count = listMap.get(entries); + if (count==null) { + count = 0; + } + count++; + + if (count>candidateCount) { + candidateCount = count; + candidate = entries; + } + + listMap.put(entries, count); + } + } + + if (candidateCount > rcNumber/2) { + majorityEntries = candidate; + break; + } + } + + if (majorityEntries!=null) { + provider.setSettingEntries(cfgDescription, folder, languageId, majorityEntries); + } + + // second pass - assign the entries to the folders + for (IResource rc : members) { + List entries = provider.getSettingEntries(null, rc, languageId); + if (entries!=null && entries==majorityEntries) { + if (!(rc instanceof IFile)) { // preserve information which files were collected + provider.setSettingEntries(cfgDescription, rc, languageId, null); + } + } + } + } + + private static boolean isLanguageInScope(IResource rc, ICConfigurationDescription cfgDescription, String languageId) { + if (rc instanceof IFile) { + ILanguage lang = null; + try { + lang = LanguageManager.getInstance().getLanguageForFile((IFile) rc, cfgDescription); + } catch (CoreException e) { + CCorePlugin.log("Error loading language settings providers extensions", e); //$NON-NLS-1$ + } + if (lang==null || (languageId!=null && !languageId.equals(lang.getId()))) { + return false; + } + } + return true; + } + + private static boolean checkBit(int flags, int bit) { + return (flags & bit) == bit; + } + + /** + * Returns the list of setting entries of a certain kind (such as include paths) + * for the given configuration description, resource and language. This is a + * combined list for all providers taking into account settings of parent folder + * if settings for the given resource are not defined. + * + * @param cfgDescription - configuration description. + * @param rc - resource such as file or folder. + * @param languageId - language id. + * @param kind - kind of language settings entries, such as + * {@link ICSettingEntry#INCLUDE_PATH} etc. This is a binary flag + * and it is possible to specify composite kind. + * Use {@link ICSettingEntry#ALL} to get all kinds. + * @param checkLocality - specifies if parameter {@code isLocal} should be considered. + * @param isLocal - {@code true} if "local" entries should be provided and + * {@code false} for "system" entries. This makes sense for include paths where + * [#include "..."] is "local" and [#include <...>] is system. + * + * @return the list of setting entries found. + */ + private static List getSettingEntriesByKind(ICConfigurationDescription cfgDescription, + IResource rc, String languageId, int kind, boolean checkLocality, boolean isLocal) { + + List entries = new ArrayList(); + List alreadyAdded = new ArrayList(); + + List providers = cfgDescription.getLanguageSettingProviders(); + for (ILanguageSettingsProvider provider: providers) { + List providerEntries = getSettingEntriesUpResourceTree(provider, cfgDescription, rc, languageId); + for (ICLanguageSettingEntry entry : providerEntries) { + if (entry!=null) { + String entryName = entry.getName(); + boolean isRightKind = (entry.getKind() & kind) != 0; + // Only first entry is considered + // Entry flagged as "UNDEFINED" prevents adding entry with the same name down the line + if (isRightKind && !alreadyAdded.contains(entryName)) { + int flags = entry.getFlags(); + boolean isRightLocal = !checkLocality || (checkBit(flags, ICSettingEntry.LOCAL) == isLocal); + if (isRightLocal) { + if (!checkBit(flags, ICSettingEntry.UNDEFINED)) { + entries.add(entry); + } + alreadyAdded.add(entryName); + } + } + } + } + } + + return entries; + } + + /** + * Returns the list of setting entries of a certain kind (such as include paths) + * for the given configuration description, resource and language. This is a + * combined list for all providers taking into account settings of parent folder + * if settings for the given resource are not defined. For include paths both + * local (#include "...") and system (#include <...>) entries are returned. + * + * @param cfgDescription - configuration description. + * @param rc - resource such as file or folder. + * @param languageId - language id. + * @param kind - kind of language settings entries, such as + * {@link ICSettingEntry#INCLUDE_PATH} etc. This is a binary flag + * and it is possible to specify composite kind. + * Use {@link ICSettingEntry#ALL} to get all kinds. + * + * @return the list of setting entries. + */ + public static List getSettingEntriesByKind(ICConfigurationDescription cfgDescription, IResource rc, String languageId, int kind) { + return getSettingEntriesByKind(cfgDescription, rc, languageId, kind, /* checkLocality */ false, /* isLocal */ false); + } + + /** + * Returns the list of "system" (such as [#include <...>]) setting entries of a certain kind + * for the given configuration description, resource and language. This is a + * combined list for all providers taking into account settings of parent folder + * if settings for the given resource are not defined. + * + * @param cfgDescription - configuration description. + * @param rc - resource such as file or folder. + * @param languageId - language id. + * @param kind - kind of language settings entries, such as + * {@link ICSettingEntry#INCLUDE_PATH} etc. This is a binary flag + * and it is possible to specify composite kind. + * Use {@link ICSettingEntry#ALL} to get all kinds. + * + * @return the list of setting entries. + */ + public static List getSystemSettingEntriesByKind(ICConfigurationDescription cfgDescription, IResource rc, String languageId, int kind) { + return getSettingEntriesByKind(cfgDescription, rc, languageId, kind, /* checkLocality */ true, /* isLocal */ false); + } + + /** + * Returns the list of "local" (such as [#include "..."]) setting entries of a certain kind + * for the given configuration description, resource and language. This is a + * combined list for all providers taking into account settings of parent folder + * if settings for the given resource are not defined. + * + * @param cfgDescription - configuration description. + * @param rc - resource such as file or folder. + * @param languageId - language id. + * @param kind - kind of language settings entries, such as + * {@link ICSettingEntry#INCLUDE_PATH} etc. This is a binary flag + * and it is possible to specify composite kind. + * Use {@link ICSettingEntry#ALL} to get all kinds. + * + * @return the list of setting entries. + */ + public static List getLocalSettingEntriesByKind(ICConfigurationDescription cfgDescription, IResource rc, String languageId, int kind) { + return getSettingEntriesByKind(cfgDescription, rc, languageId, kind, /* checkLocality */ true, /* isLocal */ true); + } + } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/settings/providers/LanguageSettingsScannerInfoProvider.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/settings/providers/LanguageSettingsScannerInfoProvider.java index ed3960a11bf..7ed1807860f 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/settings/providers/LanguageSettingsScannerInfoProvider.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/settings/providers/LanguageSettingsScannerInfoProvider.java @@ -80,23 +80,23 @@ public class LanguageSettingsScannerInfoProvider implements IScannerInfoProvider LinkedHashSet macroEntries = new LinkedHashSet(); for (String langId : languageIds) { - List incSys = LanguageSettingsExtensionManager.getSystemSettingEntriesByKind(cfgDescription, rc, langId, + List incSys = LanguageSettingsProvidersSerializer.getSystemSettingEntriesByKind(cfgDescription, rc, langId, ICSettingEntry.INCLUDE_PATH); includePathEntries.addAll(incSys); - List incLocal = LanguageSettingsExtensionManager.getLocalSettingEntriesByKind(cfgDescription, rc, langId, + List incLocal = LanguageSettingsProvidersSerializer.getLocalSettingEntriesByKind(cfgDescription, rc, langId, ICSettingEntry.INCLUDE_PATH); includePathLocalEntries.addAll(incLocal); - List incFiles = LanguageSettingsExtensionManager.getSettingEntriesByKind(cfgDescription, rc, langId, + List incFiles = LanguageSettingsProvidersSerializer.getSettingEntriesByKind(cfgDescription, rc, langId, ICSettingEntry.INCLUDE_FILE); includeFileEntries.addAll(incFiles); - List macroFiles = LanguageSettingsExtensionManager.getSettingEntriesByKind(cfgDescription, rc, langId, + List macroFiles = LanguageSettingsProvidersSerializer.getSettingEntriesByKind(cfgDescription, rc, langId, ICSettingEntry.MACRO_FILE); macroFileEntries.addAll(macroFiles); - List macros = LanguageSettingsExtensionManager.getSettingEntriesByKind(cfgDescription, rc, langId, + List macros = LanguageSettingsProvidersSerializer.getSettingEntriesByKind(cfgDescription, rc, langId, ICSettingEntry.MACRO); macroEntries.addAll(macros); } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/settings/providers/LanguageSettingsStorage.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/settings/providers/LanguageSettingsStorage.java new file mode 100644 index 00000000000..d7832dc6d1f --- /dev/null +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/language/settings/providers/LanguageSettingsStorage.java @@ -0,0 +1,378 @@ +package org.eclipse.cdt.internal.core.language.settings.providers; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; +import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry; +import org.eclipse.cdt.core.settings.model.ICSettingEntry; +import org.eclipse.cdt.core.settings.model.util.CDataUtil; +import org.eclipse.cdt.core.settings.model.util.LanguageSettingEntriesSerializer; +import org.eclipse.cdt.internal.core.XmlUtil; +import org.eclipse.cdt.internal.core.parser.util.WeakHashSet; +import org.eclipse.core.resources.IResource; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +public class LanguageSettingsStorage { + private static final String ELEM_LANGUAGE = "language"; //$NON-NLS-1$ + private static final String ATTR_LANGUAGE_ID = "id"; //$NON-NLS-1$ + private static final String ELEM_RESOURCE = "resource"; //$NON-NLS-1$ + private static final String ATTR_PROJECT_PATH = "project-relative-path"; //$NON-NLS-1$ + + private static final String ELEM_ENTRY = "entry"; //$NON-NLS-1$ + private static final String ATTR_KIND = "kind"; //$NON-NLS-1$ + private static final String ATTR_NAME = "name"; //$NON-NLS-1$ + private static final String ATTR_VALUE = "value"; //$NON-NLS-1$ + private static final String ELEM_FLAG = "flag"; //$NON-NLS-1$ + + /** + * Storage to keep settings entries. Note that it is not necessary to keep configuration in the maps + * as the configuration is always the one provider belongs to. + */ + private Map>> fStorage = new HashMap>>(); + + /** + * Pool of LSE lists implemented as WeakHashSet. That allows to gain memory savings + * at the expense of CPU time. WeakHashSet handles garbage collection when a list is not + * referenced anywhere else. See JavaDoc {@link java.lang.ref.WeakReference} about weak reference objects. + */ + private static WeakHashSet> listPool = new WeakHashSet>() { + @Override + public synchronized List add(List list) { + return super.add(list); + } + + }; + + /** + *
Note that this list is unmodifiable. To modify the list copy it, change and use + * {@link #setSettingEntries(ICConfigurationDescription, IResource, String, List)}. + * + */ + public List getSettingEntries(ICConfigurationDescription cfgDescription, IResource rc, String languageId) { + List entries = null; + Map> langMap = fStorage.get(languageId); + if (langMap!=null) { + String rcProjectPath = rc!=null ? rc.getProjectRelativePath().toString() : null; + entries = langMap.get(rcProjectPath); + } + return entries; + } + + /** + * Some providers may collect entries in pretty much random order. For the purposes of + * predictability, UI usability and efficient storage the entries are sorted by kinds + * and secondary by name for kinds where the secondary order is not significant. + * + * @param entries - list of entries to sort. + * @return - sorted entries. + */ + private List sortEntries(List entries) { + List sortedEntries = new ArrayList(entries); + Collections.sort(sortedEntries, new Comparator(){ + /** + * This comparator sorts by kinds first and the macros are sorted additionally by name. + */ + public int compare(ICLanguageSettingEntry entry0, ICLanguageSettingEntry entry1) { + int kind0 = entry0.getKind(); + int kind1 = entry1.getKind(); + if (kind0==ICSettingEntry.MACRO && kind1==ICSettingEntry.MACRO) { + return entry0.getName().compareTo(entry1.getName()); + } + + return kind0 - kind1; + }}); + + return sortedEntries; + } + + /** + * + */ + public void setSettingEntries(String rcProjectPath, String languageId, List entries) { + synchronized (fStorage) { + if (entries!=null) { + Map> langMap = fStorage.get(languageId); + if (langMap==null) { + langMap = new HashMap>(); + fStorage.put(languageId, langMap); + } + List sortedEntries = listPool.add(Collections.unmodifiableList(sortEntries(entries))); + langMap.put(rcProjectPath, sortedEntries); + } else { + // do not keep nulls in the tables + Map> langMap = fStorage.get(languageId); + if (langMap!=null) { + langMap.remove(rcProjectPath); + if (langMap.size()==0) { + fStorage.remove(languageId); + } + } + } + } + } + + /** + * @return {@code true} if the provider does not keep any settings yet or {@code false} if there are some. + */ + public boolean isEmpty() { + return fStorage.isEmpty(); + } + + /** + * Clear all the entries for all configurations, all resources and all languages. + */ + public void clear() { + synchronized (fStorage) { + fStorage.clear(); + } + } + + /** + * Serialize the provider entries under parent XML element. + * @param elementProvider - element where to serialize the entries. + */ + public void serializeEntries(Element elementProvider) { + synchronized (fStorage) { + for (Entry>> entryLang : fStorage.entrySet()) { + serializeLanguage(elementProvider, entryLang); + } + } + } + + /** + * Serialize the provider entries for a given language list. + */ + private void serializeLanguage(Element parentElement, Entry>> entryLang) { + String langId = entryLang.getKey(); + if (langId!=null) { + Element elementLanguage = XmlUtil.appendElement(parentElement, ELEM_LANGUAGE, new String[] {ATTR_LANGUAGE_ID, langId}); + parentElement = elementLanguage; + } + for (Entry> entryRc : entryLang.getValue().entrySet()) { + serializeResource(parentElement, entryRc); + } + } + + /** + * Serialize the provider entries for a given resource list. + */ + private void serializeResource(Element parentElement, Entry> entryRc) { + String rcProjectPath = entryRc.getKey(); + if (rcProjectPath!=null) { + Element elementRc = XmlUtil.appendElement(parentElement, ELEM_RESOURCE, new String[] {ATTR_PROJECT_PATH, rcProjectPath}); + parentElement = elementRc; + } + serializeSettingEntries(parentElement, entryRc.getValue()); + } + + /** + * Serialize given settings entries. + */ + private void serializeSettingEntries(Element parentElement, List settingEntries) { + for (ICLanguageSettingEntry entry : settingEntries) { + Element elementSettingEntry = XmlUtil.appendElement(parentElement, ELEM_ENTRY, new String[] { + ATTR_KIND, LanguageSettingEntriesSerializer.kindToString(entry.getKind()), + ATTR_NAME, entry.getName(), + }); + switch(entry.getKind()) { + case ICSettingEntry.MACRO: + elementSettingEntry.setAttribute(ATTR_VALUE, entry.getValue()); + break; +// case ICLanguageSettingEntry.LIBRARY_FILE: +// // TODO: sourceAttachment fields may need to be covered +// break; + } + int flags = entry.getFlags(); + if (flags!=0) { + // Element elementFlag = + XmlUtil.appendElement(elementSettingEntry, ELEM_FLAG, new String[] { + ATTR_VALUE, LanguageSettingEntriesSerializer.composeFlagsString(entry.getFlags()) + }); + } + } + } + + /** + * Load provider entries from XML provider element. + * @param providerNode - parent XML element where entries are defined. + */ + public void loadEntries(Element providerNode) { + List settings = new ArrayList(); + NodeList nodes = providerNode.getChildNodes(); + for (int i=0;i0) { + setSettingEntries(null, null, settings); + } + } + + /** + * Load a setting entry from XML element. + */ + private ICLanguageSettingEntry loadSettingEntry(Node parentElement) { + String settingKind = XmlUtil.determineAttributeValue(parentElement, ATTR_KIND); + String settingName = XmlUtil.determineAttributeValue(parentElement, ATTR_NAME); + + NodeList flagNodes = parentElement.getChildNodes(); + int flags = 0; + for (int i=0;i settings = new ArrayList(); + NodeList nodes = parentNode.getChildNodes(); + for (int i=0;i0) { + setSettingEntries(null, langId, settings); + } + } + + /** + * Load entries defined in resource element. + */ + private void loadResourceElement(Node parentNode, String cfgId, String langId) { + String rcProjectPath = XmlUtil.determineAttributeValue(parentNode, ATTR_PROJECT_PATH); + + List settings = new ArrayList(); + NodeList nodes = parentNode.getChildNodes(); + for (int i=0;i0) { + setSettingEntries(rcProjectPath, langId, settings); + } + } + + /** + * @noreference This method is not intended to be referenced by clients. + * Warning: but if you use it make sure you synchronize on it while traversing. + */ + Map>> getMapInternal() { + return fStorage; + } + /** + * Clone storage for the entries. Copies references for lists of entries as a whole. + * Note that is OK as the lists kept in storage are unmodifiable. + */ + public LanguageSettingsStorage cloneStorage() { + LanguageSettingsStorage storageClone = new LanguageSettingsStorage(); + synchronized (fStorage) { + Set>>> entrySetLang = fStorage.entrySet(); + for (Entry>> entryLang : entrySetLang) { + String langId = entryLang.getKey(); + Map> mapRc = entryLang.getValue(); + Map> mapRcClone = new HashMap>(); + Set>> entrySetRc = mapRc.entrySet(); + for (Entry> entryRc : entrySetRc) { + String rcProjectPath = entryRc.getKey(); + List lsEntries = entryRc.getValue(); + // don't need to clone entries, they are from the LSE pool + mapRcClone.put(rcProjectPath, lsEntries); + } + storageClone.fStorage.put(langId, mapRcClone); + } + } + return storageClone; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((fStorage == null) ? 0 : fStorage.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + LanguageSettingsStorage other = (LanguageSettingsStorage) obj; + if (fStorage == null) { + if (other.fStorage != null) + return false; + } else if (!fStorage.equals(other.fStorage)) + return false; + return true; + } + +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/CConfigurationSpecSettings.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/CConfigurationSpecSettings.java index 9d7ab1be7a6..8c5e1968f3f 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/CConfigurationSpecSettings.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/CConfigurationSpecSettings.java @@ -24,6 +24,8 @@ import java.util.Set; 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.settings.model.CExternalSetting; import org.eclipse.cdt.core.settings.model.ICBuildSetting; import org.eclipse.cdt.core.settings.model.ICConfigExtensionReference; @@ -41,7 +43,9 @@ 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.LanguageSettingsDelta; import org.eclipse.cdt.internal.core.language.settings.providers.LanguageSettingsProvidersSerializer; +import org.eclipse.cdt.internal.core.language.settings.providers.LanguageSettingsStorage; import org.eclipse.cdt.utils.envvar.StorableEnvironment; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.QualifiedName; @@ -94,6 +98,8 @@ public class CConfigurationSpecSettings implements ICSettingsStorage{ // private Map fExternalSettingsProviderMap; private List fLanguageSettingsProviders = new ArrayList(0); + private LinkedHashMap lspPersistedState = new LinkedHashMap(); + private class DeltaSet { public Set extSet; @@ -189,6 +195,10 @@ public class CConfigurationSpecSettings implements ICSettingsStorage{ copyExtensionInfo(base); fLanguageSettingsProviders = LanguageSettingsProvidersSerializer.cloneProviders(base.getLanguageSettingProviders()); + for (String providerId : base.lspPersistedState.keySet()) { + LanguageSettingsStorage clone = base.lspPersistedState.get(providerId).cloneStorage(); + lspPersistedState.put(providerId, clone); + } } // private void copyRefInfos(Map infosMap){ @@ -1011,4 +1021,40 @@ public class CConfigurationSpecSettings implements ICSettingsStorage{ public List getLanguageSettingProviders() { return Collections.unmodifiableList(fLanguageSettingsProviders); } + + /** + * Returns delta and atomically updates last persisted state to the new state. + * That implies that the delta needs to be used to fire an event of it will + * be lost. + */ + public LanguageSettingsDelta dropDelta() { + LanguageSettingsDelta languageSettingsDelta = null; + // newState gets shallow map first + LinkedHashMap newStateShallow = new LinkedHashMap(); + for (ILanguageSettingsProvider provider : fLanguageSettingsProviders) { + if (LanguageSettingsManager.isWorkspaceProvider(provider)) { + provider = LanguageSettingsManager.getRawProvider(provider); + } + if (provider instanceof LanguageSettingsSerializable) { + LanguageSettingsStorage store = ((LanguageSettingsSerializable) provider).getStorageInternal(); + if (!store.isEmpty()) { + newStateShallow.put(provider.getId(), store); + } + } + } + if (!newStateShallow.equals(lspPersistedState)) { + // do deep copy if the state needs to be saved + LinkedHashMap newStateDeep = new LinkedHashMap(); + for (Entry entry : newStateShallow.entrySet()) { + String providerId = entry.getKey(); + LanguageSettingsStorage store = entry.getValue(); + newStateDeep.put(providerId, store.cloneStorage()); + } + languageSettingsDelta = new LanguageSettingsDelta(lspPersistedState, newStateDeep); + lspPersistedState = newStateDeep; + } + + return languageSettingsDelta; + } + } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/LanguageSettingsChangeListener.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/LanguageSettingsChangeListener.java new file mode 100644 index 00000000000..e15d17e208c --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/LanguageSettingsChangeListener.java @@ -0,0 +1,77 @@ +/******************************************************************************* + * Copyright (c) 2011, 2011 Andrew Gvozdev and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrew Gvozdev - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.pdom; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.index.IIndexManager; +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; +import org.eclipse.cdt.core.settings.model.ICProjectDescription; +import org.eclipse.cdt.internal.core.language.settings.providers.ILanguageSettingsChangeEvent; +import org.eclipse.cdt.internal.core.language.settings.providers.ILanguageSettingsChangeListener; +import org.eclipse.cdt.internal.core.model.CModelManager; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; + +/** + * This class handles changes in language settings for the PDOM by reindexing the appropriate resources. + */ +public class LanguageSettingsChangeListener implements ILanguageSettingsChangeListener { + + private IIndexManager fManager; + + public LanguageSettingsChangeListener(IIndexManager manager) { + fManager = manager; + } + + public void handleEvent(ILanguageSettingsChangeEvent event) { + String projectName = event.getProjectName(); + IWorkspaceRoot wspRoot = ResourcesPlugin.getWorkspace().getRoot(); + IProject project = wspRoot.getProject(projectName); + + ICProjectDescription prjDescription = CCorePlugin.getDefault().getProjectDescription(project); + ICConfigurationDescription indexedCfgDescription = prjDescription.getDefaultSettingConfiguration(); + + CModelManager manager = CModelManager.getDefault(); + + IResource[] resources = event.getResources(indexedCfgDescription.getId()); + + if (resources.length > 0) { + ICProject cProject = manager.getCModel().getCProject(project); + List elements = new ArrayList(); + + for (IResource rc : resources) { + // AG TODO - remove the log + CCorePlugin.log(new Status(IStatus.WARNING, CCorePlugin.PLUGIN_ID, + "LanguageSettingsChangeListener"+"["+System.identityHashCode(this)+"]"+".handleEvent() for " + rc, new Exception())); + + elements.add(manager.create(rc, cProject)); + } + + try { + fManager.update(elements.toArray(new ICElement[elements.size()]), IIndexManager.UPDATE_ALL); + } catch (CoreException e) { + CCorePlugin.log(e); + } + } + + } + +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java index e9d85a73bd2..ee646d5b969 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMManager.java @@ -60,6 +60,7 @@ import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.core.model.LanguageManager; import org.eclipse.cdt.core.settings.model.CProjectDescriptionEvent; import org.eclipse.cdt.core.settings.model.ICProjectDescriptionListener; +import org.eclipse.cdt.core.settings.model.util.LanguageSettingEntriesSerializer; import org.eclipse.cdt.internal.core.CCoreInternals; import org.eclipse.cdt.internal.core.index.IIndexFragment; import org.eclipse.cdt.internal.core.index.IWritableIndex; @@ -68,6 +69,7 @@ import org.eclipse.cdt.internal.core.index.IndexChangeEvent; import org.eclipse.cdt.internal.core.index.IndexFactory; import org.eclipse.cdt.internal.core.index.IndexerStateEvent; import org.eclipse.cdt.internal.core.index.provider.IndexProviderManager; +import org.eclipse.cdt.internal.core.language.settings.providers.LanguageSettingsProvidersSerializer; import org.eclipse.cdt.internal.core.pdom.PDOM.IListener; import org.eclipse.cdt.internal.core.pdom.db.ChunkCache; import org.eclipse.cdt.internal.core.pdom.dom.IPDOMLinkageFactory; @@ -163,6 +165,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { private CModelListener fCModelListener= new CModelListener(this); private ILanguageMappingChangeListener fLanguageChangeListener = new LanguageMappingChangeListener(this); + private LanguageSettingsChangeListener fLanguageSettingsChangeListener = new LanguageSettingsChangeListener(this); private final ICProjectDescriptionListener fProjectDescriptionListener; private final JobChangeListener fJobChangeListener; private final IPreferenceChangeListener fPreferenceChangeListener; @@ -235,6 +238,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { ResourcesPlugin.getWorkspace().addResourceChangeListener(fCModelListener, IResourceChangeEvent.POST_BUILD); model.addElementChangedListener(fCModelListener); LanguageManager.getInstance().registerLanguageChangeListener(fLanguageChangeListener); + LanguageSettingsProvidersSerializer.registerLanguageSettingsChangeListener(fLanguageSettingsChangeListener); final int types= CProjectDescriptionEvent.DATA_APPLIED; CCorePlugin.getDefault().getProjectDescriptionManager().addCProjectDescriptionListener(fProjectDescriptionListener, types); @@ -255,6 +259,7 @@ public class PDOMManager implements IWritableIndexManager, IListener { final CoreModel model = CoreModel.getDefault(); model.removeElementChangedListener(fCModelListener); ResourcesPlugin.getWorkspace().removeResourceChangeListener(fCModelListener); + LanguageSettingsProvidersSerializer.unregisterLanguageSettingsChangeListener(fLanguageSettingsChangeListener); LanguageManager.getInstance().unregisterLanguageChangeListener(fLanguageChangeListener); PDOMIndexerJob jobToCancel= null; synchronized (fTaskQueue) { diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/language/settings/providers/LanguageSettingsEntriesTab.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/language/settings/providers/LanguageSettingsEntriesTab.java index 068efb454a7..e003ba067cd 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/language/settings/providers/LanguageSettingsEntriesTab.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/language/settings/providers/LanguageSettingsEntriesTab.java @@ -21,7 +21,6 @@ import java.util.Map; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; -import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.viewers.IDecoration; @@ -47,7 +46,6 @@ import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsEditabl 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.LanguageSettingsManager_TBD; import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsSerializable; import org.eclipse.cdt.core.language.settings.providers.ScannerDiscoveryLegacySupport; import org.eclipse.cdt.core.model.ILanguage; @@ -1019,14 +1017,6 @@ providers: for (ILanguageSettingsProvider provider : providers) { ScannerDiscoveryLegacySupport.setLanguageSettingsProvidersFunctionalityEnabled(page.getProject(), enabled); enableProvidersCheckBox.setSelection(enabled); } - - try { - LanguageSettingsManager_TBD.serializeWorkspaceProviders(); - } catch (CoreException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - throw new UnsupportedOperationException("Internal Error"); - } trackInitialSettings(); updateData(getResDesc()); @@ -1063,19 +1053,4 @@ providers: for (ILanguageSettingsProvider provider : providers) { provider.setSettingEntries(cfgDescription, rc, currentLanguageId, entries); } - @Override - protected boolean isIndexerAffected() { -// List newProvidersList = null; -// ICConfigurationDescription cfgDescription = getConfigurationDescription(); -// if (cfgDescription!=null) { -// newProvidersList = cfgDescription.getLanguageSettingProviders(); -// } -// boolean newEnablement = LanguageSettingsManager.isLanguageSettingsProvidersEnabled(page.getProject()); -// -// boolean isEqualList = (newProvidersList==initialProvidersList) || (newProvidersList!=null && newProvidersList.equals(initialProvidersList)); -// return newEnablement!=initialEnablement || (newEnablement==true && !isEqualList); - // FIXME - return true; - } - } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/language/settings/providers/LanguageSettingsProviderTab.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/language/settings/providers/LanguageSettingsProviderTab.java index 9289eb47e25..b49e82a9f1f 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/language/settings/providers/LanguageSettingsProviderTab.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/language/settings/providers/LanguageSettingsProviderTab.java @@ -51,14 +51,8 @@ import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsManager; import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsManager_TBD; import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsSerializable; import org.eclipse.cdt.core.language.settings.providers.ScannerDiscoveryLegacySupport; -import org.eclipse.cdt.core.model.ILanguageDescriptor; -import org.eclipse.cdt.core.model.LanguageManager; import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; -import org.eclipse.cdt.core.settings.model.ICFileDescription; -import org.eclipse.cdt.core.settings.model.ICFolderDescription; -import org.eclipse.cdt.core.settings.model.ICLanguageSetting; import org.eclipse.cdt.core.settings.model.ICResourceDescription; -import org.eclipse.cdt.core.settings.model.ICSettingBase; import org.eclipse.cdt.ui.CDTSharedImages; import org.eclipse.cdt.ui.CUIPlugin; import org.eclipse.cdt.ui.dialogs.ICOptionPage; @@ -66,7 +60,6 @@ import org.eclipse.cdt.ui.newui.AbstractCPropertyTab; import org.eclipse.cdt.ui.newui.CDTPrefUtil; import org.eclipse.cdt.utils.ui.controls.TabFolderLayout; - import org.eclipse.cdt.internal.ui.newui.Messages; import org.eclipse.cdt.internal.ui.newui.StatusMessageLine; @@ -983,13 +976,6 @@ public class LanguageSettingsProviderTab extends AbstractCPropertyTab { } } - try { - LanguageSettingsManager_TBD.serializeWorkspaceProviders(); - } catch (CoreException e) { - CUIPlugin.log("Internal Error", e); - throw new UnsupportedOperationException("Internal Error"); - } - trackInitialSettings(); updateData(getResDesc()); } @@ -1002,21 +988,6 @@ public class LanguageSettingsProviderTab extends AbstractCPropertyTab { return page.isForPrefs() || page.isForProject(); } - @Override - protected boolean isIndexerAffected() { - List newProvidersList = null; - ICConfigurationDescription cfgDescription = getConfigurationDescription(); - if (cfgDescription!=null) { - newProvidersList = cfgDescription.getLanguageSettingProviders(); - } - boolean newEnablement = ScannerDiscoveryLegacySupport.isLanguageSettingsProvidersFunctionalityEnabled(page.getProject()); - - // TODO - boolean isEqualList = false; -// boolean isEqualList = (newProvidersList==initialProvidersMap) || (newProvidersList!=null && newProvidersList.equals(initialProvidersMap)); - return newEnablement!=initialEnablement || (newEnablement==true && !isEqualList); - } - private ILanguageSettingsProvider findRawProvider(String id, List providers) { for (ILanguageSettingsProvider provider : providers) { if (provider.getId().equals(id)) {