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 9e1c4c4badf..cc6424a42bd 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 @@ -13,6 +13,7 @@ package org.eclipse.cdt.core.language.settings.providers; import java.util.ArrayList; import java.util.List; +import java.util.Set; import junit.framework.TestSuite; @@ -25,7 +26,10 @@ import org.eclipse.cdt.core.testplugin.ResourceHelper; import org.eclipse.cdt.core.testplugin.util.BaseTestCase; import org.eclipse.cdt.internal.core.language.settings.providers.LanguageSettingsProvidersSerializer; import org.eclipse.cdt.internal.core.settings.model.CProjectDescriptionManager; +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.runtime.jobs.Job; /** @@ -1131,5 +1135,371 @@ public class LanguageSettingsListenersTests extends BaseTestCase { assertEquals(cfgDescriptionId, event.getConfigurationDescriptionIds()[0]); } } + + /** + * Test case when a project is present in the list of resources in delta. + */ + public void testDelta_AffectedResources_Project() throws Exception { + // create project + IProject project = ResourceHelper.createCDTProjectWithConfig(this.getName()); + ScannerDiscoveryLegacySupport.setLanguageSettingsProvidersFunctionalityEnabled(project, true); + + // create a mock provider and add to cfgDescription + { + // get project descriptions + ICProjectDescription prjDescriptionWritable = CProjectDescriptionManager.getInstance().getProjectDescription(project, true); + assertNotNull(prjDescriptionWritable); + ICConfigurationDescription[] cfgDescriptions = prjDescriptionWritable.getConfigurations(); + assertEquals(1, cfgDescriptions.length); + ICConfigurationDescription cfgDescription = cfgDescriptions[0]; + assertTrue(cfgDescription instanceof ILanguageSettingsProvidersKeeper); + + // add mock provider to cfgDescription + List providers = new ArrayList(); + MockLanguageSettingsEditableProvider mockProvider = new MockLanguageSettingsEditableProvider(PROVIDER_1, PROVIDER_NAME_1); + providers.add(mockProvider); + ((ILanguageSettingsProvidersKeeper) cfgDescription).setLanguageSettingProviders(providers); + List storedProviders = ((ILanguageSettingsProvidersKeeper) cfgDescription).getLanguageSettingProviders(); + assertEquals(1, storedProviders.size()); + + // write to project description + CoreModel.getDefault().setProjectDescription(project, prjDescriptionWritable); + } + + // register mock listener to inspect the notifications + { + LanguageSettingsManager.registerLanguageSettingsChangeListener(mockLseListener); + assertEquals(0, mockLseListener.getCount()); + assertEquals(null, mockLseListener.getLastEvent()); + } + + // trigger an event on the project + ICConfigurationDescription cfgDescription; + { + // get project descriptions + ICProjectDescription prjDescription = CProjectDescriptionManager.getInstance().getProjectDescription(project, false); + assertNotNull(prjDescription); + ICConfigurationDescription[] cfgDescriptions = prjDescription.getConfigurations(); + assertEquals(1, cfgDescriptions.length); + cfgDescription = cfgDescriptions[0]; + assertTrue(cfgDescription instanceof ILanguageSettingsProvidersKeeper); + List providers = ((ILanguageSettingsProvidersKeeper)cfgDescription).getLanguageSettingProviders(); + assertEquals(1, providers.size()); + MockLanguageSettingsEditableProvider mockProvider = (MockLanguageSettingsEditableProvider) providers.get(0); + + List entries = new ArrayList(); + entries.add(SAMPLE_LSE); + mockProvider.setSettingEntries(cfgDescription, project, null, entries); + mockProvider.serializeLanguageSettings(cfgDescription); + } + + // inspect event + { + assertEquals(1, mockLseListener.getCount()); + ILanguageSettingsChangeEvent event = mockLseListener.getLastEvent(); + assertNotNull(event); + assertEquals(event.getProjectName(), project.getName()); + + Set resources = event.getAffectedResources(cfgDescription.getId()); + assertNotNull(resources); + assertEquals(project, resources.toArray()[0]); + assertEquals(1, resources.size()); + } + } + + /** + * Test case when a default resource (null) is represented in the list of resources in delta. + */ + public void testDelta_AffectedResources_DefaultResource() throws Exception { + // create project + IProject project = ResourceHelper.createCDTProjectWithConfig(this.getName()); + ScannerDiscoveryLegacySupport.setLanguageSettingsProvidersFunctionalityEnabled(project, true); + + // create a mock provider and add to cfgDescription + { + // get project descriptions + ICProjectDescription prjDescriptionWritable = CProjectDescriptionManager.getInstance().getProjectDescription(project, true); + assertNotNull(prjDescriptionWritable); + ICConfigurationDescription[] cfgDescriptions = prjDescriptionWritable.getConfigurations(); + assertEquals(1, cfgDescriptions.length); + ICConfigurationDescription cfgDescription = cfgDescriptions[0]; + assertTrue(cfgDescription instanceof ILanguageSettingsProvidersKeeper); + + // add mock provider to cfgDescription + List providers = new ArrayList(); + MockLanguageSettingsEditableProvider mockProvider = new MockLanguageSettingsEditableProvider(PROVIDER_1, PROVIDER_NAME_1); + providers.add(mockProvider); + ((ILanguageSettingsProvidersKeeper) cfgDescription).setLanguageSettingProviders(providers); + List storedProviders = ((ILanguageSettingsProvidersKeeper) cfgDescription).getLanguageSettingProviders(); + assertEquals(1, storedProviders.size()); + + // write to project description + CoreModel.getDefault().setProjectDescription(project, prjDescriptionWritable); + } + + // register mock listener to inspect the notifications + { + LanguageSettingsManager.registerLanguageSettingsChangeListener(mockLseListener); + assertEquals(0, mockLseListener.getCount()); + assertEquals(null, mockLseListener.getLastEvent()); + } + + // trigger an event on the project + ICConfigurationDescription cfgDescription; + { + // get project descriptions + ICProjectDescription prjDescription = CProjectDescriptionManager.getInstance().getProjectDescription(project, false); + assertNotNull(prjDescription); + ICConfigurationDescription[] cfgDescriptions = prjDescription.getConfigurations(); + assertEquals(1, cfgDescriptions.length); + cfgDescription = cfgDescriptions[0]; + assertTrue(cfgDescription instanceof ILanguageSettingsProvidersKeeper); + List providers = ((ILanguageSettingsProvidersKeeper)cfgDescription).getLanguageSettingProviders(); + assertEquals(1, providers.size()); + MockLanguageSettingsEditableProvider mockProvider = (MockLanguageSettingsEditableProvider) providers.get(0); + + List entries = new ArrayList(); + entries.add(SAMPLE_LSE); + mockProvider.setSettingEntries(cfgDescription, null, null, entries); + mockProvider.serializeLanguageSettings(cfgDescription); + } + + // inspect event + { + assertEquals(1, mockLseListener.getCount()); + ILanguageSettingsChangeEvent event = mockLseListener.getLastEvent(); + assertNotNull(event); + assertEquals(event.getProjectName(), project.getName()); + + Set resources = event.getAffectedResources(cfgDescription.getId()); + assertNotNull(resources); + assertEquals(project, resources.toArray()[0]); + assertEquals(1, resources.size()); + } + } + + /** + * Test case when a folder is present in the list of resources in delta. + */ + public void testDelta_AffectedResources_Folder() throws Exception { + // create project + IProject project = ResourceHelper.createCDTProjectWithConfig(this.getName()); + IFolder folder = ResourceHelper.createFolder(project, "Folder"); + ScannerDiscoveryLegacySupport.setLanguageSettingsProvidersFunctionalityEnabled(project, true); + + // create a mock provider and add to cfgDescription + { + // get project descriptions + ICProjectDescription prjDescriptionWritable = CProjectDescriptionManager.getInstance().getProjectDescription(project, true); + assertNotNull(prjDescriptionWritable); + ICConfigurationDescription[] cfgDescriptions = prjDescriptionWritable.getConfigurations(); + assertEquals(1, cfgDescriptions.length); + ICConfigurationDescription cfgDescription = cfgDescriptions[0]; + assertTrue(cfgDescription instanceof ILanguageSettingsProvidersKeeper); + + // add mock provider to cfgDescription + List providers = new ArrayList(); + MockLanguageSettingsEditableProvider mockProvider = new MockLanguageSettingsEditableProvider(PROVIDER_1, PROVIDER_NAME_1); + providers.add(mockProvider); + ((ILanguageSettingsProvidersKeeper) cfgDescription).setLanguageSettingProviders(providers); + List storedProviders = ((ILanguageSettingsProvidersKeeper) cfgDescription).getLanguageSettingProviders(); + assertEquals(1, storedProviders.size()); + + // write to project description + CoreModel.getDefault().setProjectDescription(project, prjDescriptionWritable); + } + + // register mock listener to inspect the notifications + { + LanguageSettingsManager.registerLanguageSettingsChangeListener(mockLseListener); + assertEquals(0, mockLseListener.getCount()); + assertEquals(null, mockLseListener.getLastEvent()); + } + + // trigger an event on the project + ICConfigurationDescription cfgDescription; + { + // get project descriptions + ICProjectDescription prjDescription = CProjectDescriptionManager.getInstance().getProjectDescription(project, false); + assertNotNull(prjDescription); + ICConfigurationDescription[] cfgDescriptions = prjDescription.getConfigurations(); + assertEquals(1, cfgDescriptions.length); + cfgDescription = cfgDescriptions[0]; + assertTrue(cfgDescription instanceof ILanguageSettingsProvidersKeeper); + List providers = ((ILanguageSettingsProvidersKeeper)cfgDescription).getLanguageSettingProviders(); + assertEquals(1, providers.size()); + MockLanguageSettingsEditableProvider mockProvider = (MockLanguageSettingsEditableProvider) providers.get(0); + + List entries = new ArrayList(); + entries.add(SAMPLE_LSE); + mockProvider.setSettingEntries(cfgDescription, folder, null, entries); + mockProvider.serializeLanguageSettings(cfgDescription); + } + + // inspect event + { + assertEquals(1, mockLseListener.getCount()); + ILanguageSettingsChangeEvent event = mockLseListener.getLastEvent(); + assertNotNull(event); + assertEquals(event.getProjectName(), project.getName()); + + Set resources = event.getAffectedResources(cfgDescription.getId()); + assertNotNull(resources); + assertEquals(folder, resources.toArray()[0]); + assertEquals(1, resources.size()); + } + } + + /** + * Test case when a file is present in the list of resources in delta. + */ + public void testDelta_AffectedResources_File() throws Exception { + // create project + IProject project = ResourceHelper.createCDTProjectWithConfig(this.getName()); + IFile file = ResourceHelper.createFile(project, "file.cpp"); + ScannerDiscoveryLegacySupport.setLanguageSettingsProvidersFunctionalityEnabled(project, true); + + // create a mock provider and add to cfgDescription + { + // get project descriptions + ICProjectDescription prjDescriptionWritable = CProjectDescriptionManager.getInstance().getProjectDescription(project, true); + assertNotNull(prjDescriptionWritable); + ICConfigurationDescription[] cfgDescriptions = prjDescriptionWritable.getConfigurations(); + assertEquals(1, cfgDescriptions.length); + ICConfigurationDescription cfgDescription = cfgDescriptions[0]; + assertTrue(cfgDescription instanceof ILanguageSettingsProvidersKeeper); + + // add mock provider to cfgDescription + List providers = new ArrayList(); + MockLanguageSettingsEditableProvider mockProvider = new MockLanguageSettingsEditableProvider(PROVIDER_1, PROVIDER_NAME_1); + providers.add(mockProvider); + ((ILanguageSettingsProvidersKeeper) cfgDescription).setLanguageSettingProviders(providers); + List storedProviders = ((ILanguageSettingsProvidersKeeper) cfgDescription).getLanguageSettingProviders(); + assertEquals(1, storedProviders.size()); + + // write to project description + CoreModel.getDefault().setProjectDescription(project, prjDescriptionWritable); + } + + // register mock listener to inspect the notifications + { + LanguageSettingsManager.registerLanguageSettingsChangeListener(mockLseListener); + assertEquals(0, mockLseListener.getCount()); + assertEquals(null, mockLseListener.getLastEvent()); + } + + // trigger an event on the project + ICConfigurationDescription cfgDescription; + { + // get project descriptions + ICProjectDescription prjDescription = CProjectDescriptionManager.getInstance().getProjectDescription(project, false); + assertNotNull(prjDescription); + ICConfigurationDescription[] cfgDescriptions = prjDescription.getConfigurations(); + assertEquals(1, cfgDescriptions.length); + cfgDescription = cfgDescriptions[0]; + assertTrue(cfgDescription instanceof ILanguageSettingsProvidersKeeper); + List providers = ((ILanguageSettingsProvidersKeeper)cfgDescription).getLanguageSettingProviders(); + assertEquals(1, providers.size()); + MockLanguageSettingsEditableProvider mockProvider = (MockLanguageSettingsEditableProvider) providers.get(0); + + List entries = new ArrayList(); + entries.add(SAMPLE_LSE); + mockProvider.setSettingEntries(cfgDescription, file, null, entries); + mockProvider.serializeLanguageSettings(cfgDescription); + } + + // inspect event + { + assertEquals(1, mockLseListener.getCount()); + ILanguageSettingsChangeEvent event = mockLseListener.getLastEvent(); + assertNotNull(event); + assertEquals(event.getProjectName(), project.getName()); + + Set resources = event.getAffectedResources(cfgDescription.getId()); + assertNotNull(resources); + assertEquals(file, resources.toArray()[0]); + assertEquals(1, resources.size()); + } + } + + /** + * Test case when a mix of files and folders is present in the list of resources in delta. + */ + public void testDelta_AffectedResources_Mix() throws Exception { + // create project + IProject project = ResourceHelper.createCDTProjectWithConfig(this.getName()); + IFolder folder = ResourceHelper.createFolder(project, "Folder"); + IFile file1 = ResourceHelper.createFile(project, "file1.cpp"); + IFile file2 = ResourceHelper.createFile(project, "file2.cpp"); + IFile file3 = ResourceHelper.createFile(project, "file3.cpp"); + ScannerDiscoveryLegacySupport.setLanguageSettingsProvidersFunctionalityEnabled(project, true); + + // create a mock provider and add to cfgDescription + { + // get project descriptions + ICProjectDescription prjDescriptionWritable = CProjectDescriptionManager.getInstance().getProjectDescription(project, true); + assertNotNull(prjDescriptionWritable); + ICConfigurationDescription[] cfgDescriptions = prjDescriptionWritable.getConfigurations(); + assertEquals(1, cfgDescriptions.length); + ICConfigurationDescription cfgDescription = cfgDescriptions[0]; + assertTrue(cfgDescription instanceof ILanguageSettingsProvidersKeeper); + + // add mock provider to cfgDescription + List providers = new ArrayList(); + MockLanguageSettingsEditableProvider mockProvider = new MockLanguageSettingsEditableProvider(PROVIDER_1, PROVIDER_NAME_1); + providers.add(mockProvider); + ((ILanguageSettingsProvidersKeeper) cfgDescription).setLanguageSettingProviders(providers); + List storedProviders = ((ILanguageSettingsProvidersKeeper) cfgDescription).getLanguageSettingProviders(); + assertEquals(1, storedProviders.size()); + + // write to project description + CoreModel.getDefault().setProjectDescription(project, prjDescriptionWritable); + } + + // register mock listener to inspect the notifications + { + LanguageSettingsManager.registerLanguageSettingsChangeListener(mockLseListener); + assertEquals(0, mockLseListener.getCount()); + assertEquals(null, mockLseListener.getLastEvent()); + } + + // trigger an event on the project + ICConfigurationDescription cfgDescription; + { + // get project descriptions + ICProjectDescription prjDescription = CProjectDescriptionManager.getInstance().getProjectDescription(project, false); + assertNotNull(prjDescription); + ICConfigurationDescription[] cfgDescriptions = prjDescription.getConfigurations(); + assertEquals(1, cfgDescriptions.length); + cfgDescription = cfgDescriptions[0]; + assertTrue(cfgDescription instanceof ILanguageSettingsProvidersKeeper); + List providers = ((ILanguageSettingsProvidersKeeper)cfgDescription).getLanguageSettingProviders(); + assertEquals(1, providers.size()); + MockLanguageSettingsEditableProvider mockProvider = (MockLanguageSettingsEditableProvider) providers.get(0); + + List entries = new ArrayList(); + entries.add(SAMPLE_LSE); + mockProvider.setSettingEntries(cfgDescription, folder, null, entries); + mockProvider.setSettingEntries(cfgDescription, file1, null, entries); + mockProvider.setSettingEntries(cfgDescription, file2, null, entries); + mockProvider.serializeLanguageSettings(cfgDescription); + } + + // inspect event + { + assertEquals(1, mockLseListener.getCount()); + ILanguageSettingsChangeEvent event = mockLseListener.getLastEvent(); + assertNotNull(event); + assertEquals(event.getProjectName(), project.getName()); + + Set resources = event.getAffectedResources(cfgDescription.getId()); + assertNotNull(resources); + assertTrue(resources.contains(folder)); + assertTrue(resources.contains(file1)); + assertTrue(resources.contains(file2)); + assertFalse(resources.contains(file3)); + assertEquals(3, resources.size()); + } + } } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/settings/providers/ILanguageSettingsChangeEvent.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/settings/providers/ILanguageSettingsChangeEvent.java index 8bcb1046571..caf2240d028 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/settings/providers/ILanguageSettingsChangeEvent.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/settings/providers/ILanguageSettingsChangeEvent.java @@ -10,7 +10,10 @@ *******************************************************************************/ package org.eclipse.cdt.core.language.settings.providers; +import java.util.Set; + 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 @@ -21,7 +24,7 @@ import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry; *

* EXPERIMENTAL. This class interface is not stable yet as * it is not currently clear how it may need to be used in future. Only bare - * minimum is provided here at this point (CDT 9.0, Juno). + * minimum is provided here at this point (CDT 8.1, Juno). * There is no guarantee that this API will work or that it will remain the same. * Please do not use this API without consulting with the CDT team. *

@@ -38,8 +41,12 @@ public interface ILanguageSettingsChangeEvent { public String getProjectName(); /** - * @return configuration IDs which are affected by the language settings changes. + * @return configuration IDs which are affected by the language settings entries changes. */ public String[] getConfigurationDescriptionIds(); + /** + * @return list of resources affected by the language settings entries changes. + */ + public Set getAffectedResources(String cfgId); } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/settings/providers/LanguageSettingsStorage.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/settings/providers/LanguageSettingsStorage.java index 33db176254d..d1dd06f6fce 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/settings/providers/LanguageSettingsStorage.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/language/settings/providers/LanguageSettingsStorage.java @@ -14,6 +14,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -91,8 +92,10 @@ public class LanguageSettingsStorage implements Cloneable { /** * Sets language settings entries for the resource and language. * - * @param rcProjectPath - path to the resource relative to the project. - * @param languageId - language id. + * @param rcProjectPath - path to the resource relative to the project. If {@code null} the entries are + * considered to be being defined as default entries for resources. + * @param languageId - language id. If {@code null}, then entries are considered + * to be defined for the language scope. * @param entries - language settings entries to set. */ public void setSettingEntries(String rcProjectPath, String languageId, List entries) { @@ -134,6 +137,31 @@ public class LanguageSettingsStorage implements Cloneable { } } + /** + * @return set of all languages associated with the entries. + * Note that the storage can keep default entries for the language scope + * of the provider, so the set can contain {@code null}. + */ + public Set getLanguages() { + return new HashSet(fStorage.keySet()); + } + + /** + * Returns set of paths for all resources associated with entries for given language. + * The paths are project relative. + * + * @param languageId - language ID. + * @return the set of resource paths associated with entries for the given language or empty set. + * Note that the storage can keep default entries for resources, so the set can contain {@code null}. + */ + public Set getResourcePaths(String languageId) { + Map> rcPathsMap = fStorage.get(languageId); + if (rcPathsMap == null) { + return new HashSet(); + } + return new HashSet(rcPathsMap.keySet()); + } + /** * Find and return the equal list of entries from the pool. * 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 index 5fd372612aa..5aef3614481 100644 --- 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 @@ -11,6 +11,9 @@ package org.eclipse.cdt.internal.core.language.settings.providers; import java.util.LinkedHashMap; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; import org.eclipse.cdt.core.language.settings.providers.LanguageSettingsStorage; import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry; @@ -24,7 +27,7 @@ import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry; *

* EXPERIMENTAL. This class interface is not stable yet as * it is not currently clear how it may need to be used in future. Only bare - * minimum is provided here at this point (CDT 9.0, Juno). + * minimum is provided here at this point (CDT 8.1, Juno). * There is no guarantee that this API will work or that it will remain the same. * Please do not use this API without consulting with the CDT team. *

@@ -33,12 +36,12 @@ import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry; * @noinstantiate This class is not intended to be instantiated by clients. */ public class LanguageSettingsDelta { - // maps need to be ordered by providers - @SuppressWarnings("unused") + // maps are ordered by providers private LinkedHashMap oldLanguageSettingsState; - @SuppressWarnings("unused") private LinkedHashMap newLanguageSettingsState; + private Set paths = null; + /** * Constructor. * @@ -50,4 +53,64 @@ public class LanguageSettingsDelta { newLanguageSettingsState = newState; } + /** + * @return resource paths affected by changes represented by this delta. + */ + public Set getAffectedResourcePaths() { + if (paths != null) { + return paths; + } + + paths = new TreeSet(); + + LanguageSettingsStorage oldCombinedStorage = combineStorage(oldLanguageSettingsState); + LanguageSettingsStorage newCombinedStorage = combineStorage(newLanguageSettingsState); + + for (String lang : oldCombinedStorage.getLanguages()) { + for (String path : oldCombinedStorage.getResourcePaths(lang)) { + if (oldCombinedStorage.getSettingEntries(path, lang) != newCombinedStorage.getSettingEntries(path, lang)) { + if (path == null) { + // add path of the project + path = ""; //$NON-NLS-1$ + } + paths.add(path); + } + } + } + + for (String lang : newCombinedStorage.getLanguages()) { + for (String path : newCombinedStorage.getResourcePaths(lang)) { + if (newCombinedStorage.getSettingEntries(path, lang) != oldCombinedStorage.getSettingEntries(path, lang)) { + if (path == null) { + // add path of the project + path = ""; //$NON-NLS-1$ + } + paths.add(path); + } + } + } + + return paths; + } + + /** + * Language settings entries from different providers can overlap. This method resolves all overlapping + * ones combining entries into one aggregate storage. + */ + private LanguageSettingsStorage combineStorage(LinkedHashMap state) { + LanguageSettingsStorage combinedStore = new LanguageSettingsStorage(); + for (LanguageSettingsStorage providerStore : state.values()) { + for (String lang : providerStore.getLanguages()) { + for (String path : providerStore.getResourcePaths(lang)) { + // provider (store) higher on the list overrides others below + if (combinedStore.getSettingEntries(path, lang) == null) { + List entries = providerStore.getSettingEntries(path, lang); + combinedStore.setSettingEntries(path, lang, entries); + } + } + } + } + + return combinedStore; + } } 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 9b6224f89f1..1e822641ed6 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 @@ -14,8 +14,10 @@ import java.net.URI; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.language.settings.providers.ICListenerAgent; @@ -305,6 +307,26 @@ public class LanguageSettingsProvidersSerializer { return "LanguageSettingsChangeEvent for project=[" + getProjectName() + "]" + ", configurations=" + deltaMap.keySet(); } + + @Override + public Set getAffectedResources(String cfgId) { + LanguageSettingsDelta delta = deltaMap.get(cfgId); + if (delta != null) { + Set paths = delta.getAffectedResourcePaths(); + if (!paths.isEmpty()) { + IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); + Set resources = new HashSet(); + for (String path : paths) { + IResource rc = project.findMember(path); + if (rc != null) { + resources.add(rc); + } + } + return resources; + } + } + return null; + } } /** static initializer */ 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 index bc1846adba7..b1c26471852 100644 --- 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 @@ -10,14 +10,23 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom; +import java.util.HashSet; +import java.util.Set; + import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.index.IIndexManager; import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsChangeEvent; import org.eclipse.cdt.core.language.settings.providers.ILanguageSettingsChangeListener; +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.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; /** * This class handles changes in language settings for the PDOM. @@ -42,16 +51,36 @@ public class LanguageSettingsChangeListener implements ILanguageSettingsChangeLi if (project != null) { ICProjectDescription prjDescription = CCorePlugin.getDefault().getProjectDescription(project); if (prjDescription != null) { - ICConfigurationDescription indexedCfgDescription = prjDescription.getDefaultSettingConfiguration(); - String indexedCfgId = indexedCfgDescription.getId(); + // cfgDescription being indexed + ICConfigurationDescription cfgDescription = prjDescription.getDefaultSettingConfiguration(); + String indexedId = cfgDescription.getId(); - for (String cfgId : event.getConfigurationDescriptionIds()) { - if (cfgId.equals(indexedCfgId)) { - fManager.handlePostBuildEvent(); + for (String id : event.getConfigurationDescriptionIds()) { + if (id.equals(indexedId)) { + reindex(id, event); return; } } } } } + + private void reindex(String cfgId, ILanguageSettingsChangeEvent event) { + CModelManager manager = CModelManager.getDefault(); + ICProject cProject = manager.getCModel().getCProject(event.getProjectName()); + Set tuSelection = new HashSet(); + + Set resources = event.getAffectedResources(cfgId); + if (resources != null && !resources.isEmpty()) { + for (IResource rc : resources) { + tuSelection.add(manager.create(rc, cProject)); + } + + try { + fManager.update(tuSelection.toArray(new ICElement[tuSelection.size()]), IIndexManager.UPDATE_ALL); + } catch (CoreException e) { + CCorePlugin.log(e); + } + } + } }