1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-23 08:55:25 +02:00

bug 416628: Handle case when projects reference each other recursively

This commit is contained in:
Andrew Gvozdev 2013-09-21 05:15:58 -04:00
parent 6791f19c41
commit f49338fed1
2 changed files with 125 additions and 14 deletions

View file

@ -141,12 +141,12 @@ public class LanguageSettingsProviderReferencedProjectsTests extends BaseTestCas
IProject referencedProject = ResourceHelper.createCDTProjectWithConfig(projectName+"-referenced");
setReference(project, referencedProject);
// get cfgDescription and language to work with
// get cfgDescription
ICConfigurationDescription[] cfgDescriptions = getConfigurationDescriptions(project);
ICConfigurationDescription cfgDescription = cfgDescriptions[0];
{
// doublecheck that provider for referenced projects is set in the configuration
// double-check that provider for referenced projects is set in the configuration
ILanguageSettingsProvider refProjectsProvider = LanguageSettingsManager.getWorkspaceProvider(ReferencedProjectsLanguageSettingsProvider.ID);
assertNotNull(refProjectsProvider);
List<ILanguageSettingsProvider> providers = ((ILanguageSettingsProvidersKeeper) cfgDescription).getLanguageSettingProviders();
@ -207,4 +207,96 @@ public class LanguageSettingsProviderReferencedProjectsTests extends BaseTestCas
}
}
/**
* Test case when projects reference each other recursively.
*/
public void testRecursiveReferences() throws Exception {
// Create model projects that reference each other
String projectName = getName();
IProject projectA = ResourceHelper.createCDTProjectWithConfig(projectName + "-A");
IProject projectB = ResourceHelper.createCDTProjectWithConfig(projectName + "-B");
setReference(projectA, projectB);
setReference(projectB, projectA);
{
// get cfgDescriptions to work with
ICConfigurationDescription[] cfgDescriptionsA = getConfigurationDescriptions(projectA);
ICConfigurationDescription cfgDescriptionA = cfgDescriptionsA[0];
ICConfigurationDescription[] cfgDescriptionsB = getConfigurationDescriptions(projectB);
ICConfigurationDescription cfgDescriptionB = cfgDescriptionsB[0];
// double-check that provider for referenced projects is set in the configurations
ILanguageSettingsProvider refProjectsProvider = LanguageSettingsManager.getWorkspaceProvider(ReferencedProjectsLanguageSettingsProvider.ID);
assertNotNull(refProjectsProvider);
List<ILanguageSettingsProvider> providersA = ((ILanguageSettingsProvidersKeeper) cfgDescriptionA).getLanguageSettingProviders();
assertTrue(providersA.contains(refProjectsProvider));
List<ILanguageSettingsProvider> providersB = ((ILanguageSettingsProvidersKeeper) cfgDescriptionB).getLanguageSettingProviders();
assertTrue(providersB.contains(refProjectsProvider));
// Check that no setting entries are set initially
List<ICLanguageSettingEntry> entriesA = LanguageSettingsManager.getSettingEntriesByKind(cfgDescriptionA, projectA, null, ICSettingEntry.ALL);
assertEquals(0, entriesA.size());
List<ICLanguageSettingEntry> entriesB = LanguageSettingsManager.getSettingEntriesByKind(cfgDescriptionA, projectB, null, ICSettingEntry.ALL);
assertEquals(0, entriesB.size());
}
CIncludePathEntry entryExportedA = CDataUtil.createCIncludePathEntry("referenced-exported-A", ICSettingEntry.EXPORTED);
CIncludePathEntry entryNotExportedA = CDataUtil.createCIncludePathEntry("referenced-not-exported-A", 0);
// Add entries into a project A
{
ICConfigurationDescription[] refCfgDescriptions = getConfigurationDescriptions(projectA);
ICConfigurationDescription refCfgDescription = refCfgDescriptions[0];
List<ILanguageSettingsProvider> providersRef = ((ILanguageSettingsProvidersKeeper) refCfgDescription).getLanguageSettingProviders();
// get user provider which is the first one
ILanguageSettingsProvider userProviderRef = providersRef.get(0);
assertEquals(ScannerDiscoveryLegacySupport.USER_LANGUAGE_SETTINGS_PROVIDER_ID, userProviderRef.getId());
assertTrue(userProviderRef instanceof LanguageSettingsGenericProvider);
// add sample entries
ArrayList<ICLanguageSettingEntry> entries = new ArrayList<ICLanguageSettingEntry>();
entries.add(entryExportedA);
entries.add(entryNotExportedA);
((LanguageSettingsGenericProvider) userProviderRef).setSettingEntries(null, null, null, entries);
}
CIncludePathEntry entryExportedB = CDataUtil.createCIncludePathEntry("referenced-exported-B", ICSettingEntry.EXPORTED);
CIncludePathEntry entryNotExportedB = CDataUtil.createCIncludePathEntry("referenced-not-exported-B", 0);
// Add entries into a project B
{
ICConfigurationDescription[] refCfgDescriptions = getConfigurationDescriptions(projectB);
ICConfigurationDescription refCfgDescription = refCfgDescriptions[0];
List<ILanguageSettingsProvider> providersRef = ((ILanguageSettingsProvidersKeeper) refCfgDescription).getLanguageSettingProviders();
// get user provider which is the first one
ILanguageSettingsProvider userProviderRef = providersRef.get(0);
assertEquals(ScannerDiscoveryLegacySupport.USER_LANGUAGE_SETTINGS_PROVIDER_ID, userProviderRef.getId());
assertTrue(userProviderRef instanceof LanguageSettingsGenericProvider);
// add sample entries
ArrayList<ICLanguageSettingEntry> entries = new ArrayList<ICLanguageSettingEntry>();
entries.add(entryExportedB);
entries.add(entryNotExportedB);
((LanguageSettingsGenericProvider) userProviderRef).setSettingEntries(null, null, null, entries);
}
// Check that the new entries from projectB made it to projectA
{
ICConfigurationDescription[] cfgDescriptionsA = getConfigurationDescriptions(projectA);
ICConfigurationDescription cfgDescriptionA = cfgDescriptionsA[0];
List<ICLanguageSettingEntry> entries = LanguageSettingsManager.getSettingEntriesByKind(cfgDescriptionA, projectA, null, ICSettingEntry.ALL);
assertEquals(entryExportedA, entries.get(0));
assertEquals(entryNotExportedA, entries.get(1));
assertEquals(CDataUtil.createCIncludePathEntry(entryExportedB.getName(), 0), entries.get(2));
assertEquals(3, entries.size());
}
// Check that the new entries from projectA made it to projectB
{
ICConfigurationDescription[] cfgDescriptionsB = getConfigurationDescriptions(projectB);
ICConfigurationDescription cfgDescriptionB = cfgDescriptionsB[0];
List<ICLanguageSettingEntry> entries = LanguageSettingsManager.getSettingEntriesByKind(cfgDescriptionB, projectB, null, ICSettingEntry.ALL);
assertEquals(entryExportedB, entries.get(0));
assertEquals(entryNotExportedB, entries.get(1));
assertEquals(CDataUtil.createCIncludePathEntry(entryExportedA.getName(), 0), entries.get(2));
assertEquals(3, entries.size());
}
// Hopefully it gets here without stack overflow
}
}

View file

@ -31,8 +31,22 @@ public class ReferencedProjectsLanguageSettingsProvider extends LanguageSettings
/** ID of the provider used in extension point from plugin.xml */
public static final String ID = "org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider"; //$NON-NLS-1$
final private ThreadLocal<Boolean> recursiveCallIndicator = new ThreadLocal<Boolean>() {
@Override
protected Boolean initialValue() {
return false;
}
};
@Override
public List<ICLanguageSettingEntry> getSettingEntries(ICConfigurationDescription cfgDescription, IResource rc, String languageId) {
if (recursiveCallIndicator.get()) {
// Recursive call indicates that the provider of a referenced project is called.
// Only exported entries of the original configuration should be considered,
// entries of referenced projects are not re-exported.
return null;
}
if (cfgDescription == null) {
return null;
}
@ -41,20 +55,25 @@ public class ReferencedProjectsLanguageSettingsProvider extends LanguageSettings
return null;
}
List<ICLanguageSettingEntry> entries = new ArrayList<ICLanguageSettingEntry>();
ICConfigurationDescription[] refCfgDescriptions = CoreModelUtil.getReferencedConfigurationDescriptions(cfgDescription, false);
for (ICConfigurationDescription refCfgDescription : refCfgDescriptions) {
List<ICLanguageSettingEntry> refEntries = LanguageSettingsManager.getSettingEntriesByKind(refCfgDescription, rc, languageId, ICSettingEntry.ALL);
for (ICLanguageSettingEntry refEntry : refEntries) {
int flags = refEntry.getFlags();
if ((flags & ICSettingEntry.EXPORTED) == ICSettingEntry.EXPORTED) {
// create a new entry with EXPORTED flag cleared
ICLanguageSettingEntry entry = CDataUtil.createEntry(refEntry, flags & ~ICSettingEntry.EXPORTED);
entries.add(entry);
try {
recursiveCallIndicator.set(true);
List<ICLanguageSettingEntry> entries = new ArrayList<ICLanguageSettingEntry>();
ICConfigurationDescription[] refCfgDescriptions = CoreModelUtil.getReferencedConfigurationDescriptions(cfgDescription, false);
for (ICConfigurationDescription refCfgDescription : refCfgDescriptions) {
List<ICLanguageSettingEntry> refEntries = LanguageSettingsManager.getSettingEntriesByKind(refCfgDescription, rc, languageId, ICSettingEntry.ALL);
for (ICLanguageSettingEntry refEntry : refEntries) {
int flags = refEntry.getFlags();
if ((flags & ICSettingEntry.EXPORTED) == ICSettingEntry.EXPORTED) {
// create a new entry with EXPORTED flag cleared
ICLanguageSettingEntry entry = CDataUtil.createEntry(refEntry, flags & ~ICSettingEntry.EXPORTED);
entries.add(entry);
}
}
}
}
return LanguageSettingsStorage.getPooledList(new ArrayList<ICLanguageSettingEntry>(entries));
return LanguageSettingsStorage.getPooledList(new ArrayList<ICLanguageSettingEntry>(entries));
} finally {
recursiveCallIndicator.set(false);
}
}
}