diff --git a/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/core/tests/BuildDescriptionModelTests.java b/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/core/tests/BuildDescriptionModelTests.java index f045d96132f..e692d867a8b 100644 --- a/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/core/tests/BuildDescriptionModelTests.java +++ b/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/core/tests/BuildDescriptionModelTests.java @@ -1096,12 +1096,16 @@ public class BuildDescriptionModelTests extends TestCase { type.addResource(tDes.createResource(cName + "/" + art)); // - //FIXME: this is very bad, need to wait until the indexing is completed here -/* try { - Thread.sleep(10000); - } catch (InterruptedException e1) { - } -*/ + // TODO: more testing needed, may still need a sleep here because: + // the legacy project creation mechanism is used for this test + //the IManagedBuildInfo gets created/cached when the project contains only C nature + //thus C++ settings are initialy not taken into the account + //after that the CC nature is added + //in this the build system is initiating the core settings update (ICProjectDescription cache refresh) + //the refresh is scheduled as a job, so in case we do not wait here the job may not be completed by the time + //the test is run + + CCorePlugin.getIndexManager().joinIndexer(-1, new NullProgressMonitor()); IBuildDescription des = null; diff --git a/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/projectmodel/tests/ProjectModelTests.java b/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/projectmodel/tests/ProjectModelTests.java index 00804565521..511836a45da 100644 --- a/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/projectmodel/tests/ProjectModelTests.java +++ b/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/projectmodel/tests/ProjectModelTests.java @@ -37,8 +37,10 @@ import org.eclipse.cdt.core.settings.model.ICLanguageSettingEntry; import org.eclipse.cdt.core.settings.model.ICProjectDescription; import org.eclipse.cdt.core.settings.model.ICResourceDescription; import org.eclipse.cdt.core.settings.model.ICSettingBase; +import org.eclipse.cdt.core.settings.model.ICSettingEntry; import org.eclipse.cdt.core.settings.model.ICSourceEntry; import org.eclipse.cdt.core.settings.model.extension.CConfigurationData; +import org.eclipse.cdt.core.settings.model.extension.CLanguageData; import org.eclipse.cdt.managedbuilder.core.IConfiguration; import org.eclipse.cdt.managedbuilder.core.IFileInfo; import org.eclipse.cdt.managedbuilder.core.IFolderInfo; @@ -112,6 +114,35 @@ public class ProjectModelTests extends TestCase implements IElementChangedListen CoreModel.getDefault().removeElementChangedListener(this); } + private void modify(ICFileDescription fiDes){ + ICLanguageSetting ls = fiDes.getLanguageSetting(); + modify(ls); + } + + private void modify(ICFolderDescription foDes){ + ICLanguageSetting ls = foDes.getLanguageSettingForFile("a.c"); + modify(ls); + } + + private void modify(ICLanguageSetting ls){ + List list = ls.getSettingEntriesList(ICSourceEntry.INCLUDE_PATH); + list.add(new CIncludePathEntry("_modify_", 0)); + ls.setSettingEntries(ICSettingEntry.INCLUDE_PATH, list); + } + + private void modify(IFileInfo fiInfo){ + CLanguageData lData = fiInfo.getCLanguageDatas()[0]; + modify(lData); + } + + private void modify(CLanguageData lData){ + ICLanguageSettingEntry[] entries = lData.getEntries(ICSourceEntry.INCLUDE_PATH); + ICLanguageSettingEntry[] updatedEntries = new ICLanguageSettingEntry[entries.length + 1]; + System.arraycopy(entries, 0, updatedEntries, 0, entries.length); + updatedEntries[entries.length] = new CIncludePathEntry("_modify_", 0); + lData.setEntries(ICSettingEntry.INCLUDE_PATH, updatedEntries); + } + public void testDescription() throws Exception{ final String projectName = "test1"; IProject project = createProject(projectName); @@ -176,8 +207,11 @@ public class ProjectModelTests extends TestCase implements IElementChangedListen assertEquals(cfgDes.getRootFolderDescription(), cfgDes.getResourceDescription(new Path(""), true)); assertEquals(null, cfgDes.getResourceDescription(new Path("ds/sd/sdf/"), true)); - ICFileDescription fd_abc = cfgDes.createFileDescription(new Path("a/b/c"), rcDess[0]); + ICFileDescription fd_abc = cfgDes.createFileDescription(new Path("a/b/c.c"), rcDess[0]); + assertTrue(cfgDes.isModified()); + + modify(fd_abc); ICProjectDescription anotherDes = coreModel.getProjectDescription(project); assertNotNull("project description is null for re-created project", des); @@ -206,22 +240,25 @@ public class ProjectModelTests extends TestCase implements IElementChangedListen assertEquals(0, nestedFos.length); assertEquals(1, nestedFis.length); - ICFileDescription fd_asd = cfgDes.createFileDescription(new Path("a/s/d"), cfgDes.getRootFolderDescription()); + ICFileDescription fd_asd = cfgDes.createFileDescription(new Path("a/s/d.c"), cfgDes.getRootFolderDescription()); + modify(fd_asd); assertEquals(3, cfgDes.getResourceDescriptions().length); nestedFis = rf.getNestedResourceDescriptions(ICSettingBase.SETTING_FILE); nestedFos = rf.getNestedResourceDescriptions(ICSettingBase.SETTING_FOLDER); assertEquals(0, nestedFos.length); assertEquals(2, nestedFis.length); - cfg.createFileInfo(new Path("z/x/c")); + IFileInfo fi = cfg.createFileInfo(new Path("z/x/c.c")); + modify(fi); nestedFis = rf.getNestedResourceDescriptions(ICSettingBase.SETTING_FILE); nestedFos = rf.getNestedResourceDescriptions(ICSettingBase.SETTING_FOLDER); assertEquals(0, nestedFos.length); assertEquals(3, nestedFis.length); assertEquals(4, cfgDes.getResourceDescriptions().length); - cfg.createFileInfo(new Path("q/w/e")); - ICFileDescription fd_qwe = (ICFileDescription)cfgDes.getResourceDescription(new Path("q/w/e"), true); + fi = cfg.createFileInfo(new Path("q/w/e.c")); + modify(fi); + ICFileDescription fd_qwe = (ICFileDescription)cfgDes.getResourceDescription(new Path("q/w/e.c"), true); assertNotNull(fd_qwe); assertEquals(5, cfgDes.getResourceDescriptions().length); nestedFis = rf.getNestedResourceDescriptions(ICSettingBase.SETTING_FILE); @@ -236,36 +273,38 @@ public class ProjectModelTests extends TestCase implements IElementChangedListen assertEquals(3, nestedFis.length); assertEquals(4, cfgDes.getResourceDescriptions().length); - cfg.removeResourceInfo(new Path("a/s/d")); + cfg.removeResourceInfo(new Path("a/s/d.c")); assertEquals(3, cfgDes.getResourceDescriptions().length); nestedFis = rf.getNestedResourceDescriptions(ICSettingBase.SETTING_FILE); nestedFos = rf.getNestedResourceDescriptions(ICSettingBase.SETTING_FOLDER); assertEquals(0, nestedFos.length); assertEquals(2, nestedFis.length); - IFileInfo fi_qwe = (IFileInfo)cfg.getResourceInfo(new Path("q/w/e"), true); + IFileInfo fi_qwe = (IFileInfo)cfg.getResourceInfo(new Path("q/w/e.c"), true); assertNotNull(fi_qwe); - ICFileDescription fid_qwe = (ICFileDescription)cfgDes.getResourceDescription(new Path("q/w/e"), true); + ICFileDescription fid_qwe = (ICFileDescription)cfgDes.getResourceDescription(new Path("q/w/e.c"), true); assertNotNull(fid_qwe); - fi_qwe.setPath(new Path("r/t/y")); - assertEquals(fi_qwe, cfg.getResourceInfo(new Path("r/t/y"), true)); - assertNull(cfgDes.getResourceDescription(new Path("q/w/e"), true)); - ICFileDescription fid_rty = (ICFileDescription)cfgDes.getResourceDescription(new Path("r/t/y"), true); + fi_qwe.setPath(new Path("r/t/y.c")); + assertEquals(fi_qwe, cfg.getResourceInfo(new Path("r/t/y.c"), true)); + assertNull(cfgDes.getResourceDescription(new Path("q/w/e.c"), true)); + ICFileDescription fid_rty = (ICFileDescription)cfgDes.getResourceDescription(new Path("r/t/y.c"), true); assertEquals(fid_qwe, fid_rty); - fid_rty.setPath(new Path("f/g/h")); - assertNull(cfg.getResourceInfo(new Path("r/t/y"), true)); - IFileInfo fi_fgh = (IFileInfo)cfg.getResourceInfo(new Path("f/g/h"), true); + fid_rty.setPath(new Path("f/g/h.c")); + assertNull(cfg.getResourceInfo(new Path("r/t/y.c"), true)); + IFileInfo fi_fgh = (IFileInfo)cfg.getResourceInfo(new Path("f/g/h.c"), true); assertEquals(fi_qwe, fi_fgh); ICFolderDescription fod_fg1 = cfgDes.createFolderDescription(new Path("f/g/1"), cfgDes.getRootFolderDescription()); - + modify(fod_fg1); ICFolderDescription fod_fg12 = cfgDes.createFolderDescription(new Path("f/g/1/2"), fod_fg1); + modify(fod_fg12); assertEquals(fod_fg12, fod_fg1.getNestedResourceDescription(new Path("2"), true)); - ICFileDescription fid_fg13 = cfgDes.createFileDescription(new Path("f/g/1/3"), fod_fg1); - assertEquals(fid_fg13, fod_fg1.getNestedResourceDescription(new Path("3"), true)); + ICFileDescription fid_fg13 = cfgDes.createFileDescription(new Path("f/g/1/3.c"), fod_fg1); + modify(fid_fg13); + assertEquals(fid_fg13, fod_fg1.getNestedResourceDescription(new Path("3.c"), true)); assertEquals(2, fod_fg1.getNestedResourceDescriptions().length); assertEquals(1, fod_fg1.getNestedResourceDescriptions(ICSettingBase.SETTING_FILE).length); @@ -281,7 +320,7 @@ public class ProjectModelTests extends TestCase implements IElementChangedListen assertEquals(1, fod_fg1.getNestedResourceDescriptions(ICSettingBase.SETTING_FOLDER).length); assertEquals(fod_fg12, cfgDes.getResourceDescription(new Path("t/y/u/2"), true)); - assertEquals(fid_fg13, cfgDes.getResourceDescription(new Path("t/y/u/3"), true)); + assertEquals(fid_fg13, cfgDes.getResourceDescription(new Path("t/y/u/3.c"), true)); ICLanguageSetting settings[] = cfgDes.getRootFolderDescription().getLanguageSettings(); for(int i = 0; i < settings.length; i++){ @@ -501,7 +540,7 @@ public class ProjectModelTests extends TestCase implements IElementChangedListen cfgDes.setSourceEntries(updatetSEs); s = cfgDes.getSourceEntries(); - updatetSEs[1] = new CSourceEntry(projPath, new Path[]{new Path("a")}, ICSourceEntry.VALUE_WORKSPACE_PATH); + updatetSEs[1] = new CSourceEntry(projPath, new Path[]{new Path("a")}, ICSourceEntry.VALUE_WORKSPACE_PATH | ICSourceEntry.RESOLVED); checkArrays(updatetSEs, s); //assertTrue(Arrays.equals(updatetSEs, s)); diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/ResourceChangeHandler2.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/ResourceChangeHandler2.java index 2fcfb0716b3..05328881209 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/ResourceChangeHandler2.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/ResourceChangeHandler2.java @@ -10,12 +10,30 @@ *******************************************************************************/ package org.eclipse.cdt.managedbuilder.core; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +import org.eclipse.cdt.core.CCProjectNature; +import org.eclipse.cdt.core.CProjectNature; import org.eclipse.cdt.core.settings.model.util.ResourceChangeHandlerBase; import org.eclipse.cdt.managedbuilder.internal.core.ManagedBuildInfo; +import org.eclipse.cdt.managedbuilder.internal.dataprovider.ConfigurationDataProvider; import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceChangeEvent; +import org.eclipse.core.resources.IResourceDelta; +import org.eclipse.core.resources.IResourceDeltaVisitor; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; class ResourceChangeHandler2 extends ResourceChangeHandlerBase{ private class RcMoveHandler implements IResourceMoveHandler { @@ -80,5 +98,113 @@ class ResourceChangeHandler2 extends ResourceChangeHandlerBase{ } } + private static class Visitor implements IResourceDeltaVisitor { + private Set fProjSet; + + Visitor(Set projSet){ + fProjSet = projSet; + } + + public boolean visit(IResourceDelta delta) throws CoreException { + IResource rc = delta.getResource(); + switch (rc.getType()) { + case IResource.ROOT: + return true; + case IResource.PROJECT: + int flags = delta.getFlags(); + if((flags & IResourceDelta.DESCRIPTION) == IResourceDelta.DESCRIPTION){ + IProject project = rc.getProject(); + IManagedBuildInfo info = ManagedBuildManager.getBuildInfo(project); + if(info != null && info.isValid() && info.getManagedProject() != null){ + IProjectDescription eDes = project.getDescription(); + IConfiguration[] cfgs = info.getManagedProject().getConfigurations(); + String natureIds[] = eDes.getNatureIds(); + for(int i = 0; i < cfgs.length; i++){ + String cachedIds[] = ConfigurationDataProvider.getNaturesIdsUsedOnCache(cfgs[i]); + if(checkNaturesNeedUpdate(cachedIds, natureIds)){ + if(fProjSet == null) + fProjSet = new HashSet(); + + fProjSet.add(project); + break; + } + } + } + } + return false; + default: + return false; + } + } + + Set getProjSet(){ + return fProjSet; + } + + } + + private static boolean checkNaturesNeedUpdate(String[] oldIds, String[] newIds){ + if(oldIds == null) + return true; + + Set oldSet = new HashSet(Arrays.asList(oldIds)); + Set oldSetCopy = new HashSet(oldSet); + Set newSet = new HashSet(Arrays.asList(newIds)); + oldSet.removeAll(newSet); + newSet.removeAll(oldSetCopy); + if(oldSet.contains(CProjectNature.C_NATURE_ID) + || oldSet.contains(CCProjectNature.CC_NATURE_ID) + || newSet.contains(CProjectNature.C_NATURE_ID) + || newSet.contains(CCProjectNature.CC_NATURE_ID)) + return true; + + return false; + } + + public void resourceChanged(IResourceChangeEvent event) { + super.resourceChanged(event); + + switch(event.getType()){ + case IResourceChangeEvent.POST_CHANGE: + IResourceDelta delta = event.getDelta(); + if(delta != null){ + Visitor visitor = new Visitor(null); + try { + delta.accept(visitor); + } catch (CoreException e) { + ManagedBuilderCorePlugin.log(e); + } + postProcess(visitor.getProjSet()); + } + } + } + + private void postProcess(final Set projSet){ + if(projSet == null || projSet.size() == 0) + return; + + IWorkspace wsp = ResourcesPlugin.getWorkspace(); + IWorkspaceRoot root = wsp.getRoot(); + + Job job = new Job("project build settings update job"){ + + protected IStatus run(IProgressMonitor monitor) { + for(Iterator iter = projSet.iterator(); iter.hasNext();){ + IProject project = (IProject)iter.next(); + try { + ManagedBuildManager.updateCoreSettings(project); + } catch (CoreException e) { + ManagedBuilderCorePlugin.log(e); + } + } + return Status.OK_STATUS; + } + + }; + + job.setRule(root); + job.setSystem(true); + job.schedule(); + } } diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/dataprovider/ConfigurationDataProvider.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/dataprovider/ConfigurationDataProvider.java index 1beee18ab8c..d747ab42f62 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/dataprovider/ConfigurationDataProvider.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/dataprovider/ConfigurationDataProvider.java @@ -48,6 +48,7 @@ import org.eclipse.cdt.managedbuilder.internal.core.NotificationManager; import org.eclipse.cdt.managedbuilder.internal.core.SettingsChangeEvent; import org.eclipse.cdt.managedbuilder.internal.core.Tool; import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.QualifiedName; @@ -60,6 +61,7 @@ public class ConfigurationDataProvider extends CConfigurationDataProvider implem public static final String PREF_TC_ID = "org.eclipse.cdt.build.core.prefbase.toolchain"; //$NON-NLS-1$ private static final String PREF_TOOL_ID = "org.eclipse.cdt.build.core.settings.holder"; //$NON-NLS-1$ private static final QualifiedName CFG_PERSISTED_PROPERTY = new QualifiedName(ManagedBuilderCorePlugin.getUniqueIdentifier(), "configPersisted"); //$NON-NLS-1$ + private static final QualifiedName NATURES_USED_ON_CACHE_PROPERTY = new QualifiedName(ManagedBuilderCorePlugin.getUniqueIdentifier(), "naturesUsedOnCache"); //$NON-NLS-1$ private static boolean registered; @@ -123,6 +125,8 @@ public class ConfigurationDataProvider extends CConfigurationDataProvider implem info.setValid(true); setPersistedFlag(des); + cacheNaturesIdsUsedOnCache(des); + return appliedCfg; } @@ -241,6 +245,34 @@ public class ConfigurationDataProvider extends CConfigurationDataProvider implem return mProj; } + public static String[] getNaturesIdsUsedOnCache(IConfiguration cfg){ + ICConfigurationDescription cfgDes = ManagedBuildManager.getDescriptionForConfiguration(cfg); + if(cfgDes != null) + return getNaturesIdsUsedOnCache(cfgDes); + return null; + } + + public static String[] getNaturesIdsUsedOnCache(ICConfigurationDescription cfg){ + String[] strs = (String[])cfg.getSessionProperty(NATURES_USED_ON_CACHE_PROPERTY); + return strs != null && strs.length != 0 ? (String[])strs.clone() : strs; + } + + public static void cacheNaturesIdsUsedOnCache(ICConfigurationDescription des){ + IProject project = des.getProjectDescription().getProject(); + try { + IProjectDescription eDes = project.getDescription(); + String[] natures = eDes.getNatureIds(); + setNaturesIdsUsedOnCache(des, natures); + } catch (CoreException e) { + ManagedBuilderCorePlugin.log(e); + } + } + + private static void setNaturesIdsUsedOnCache(ICConfigurationDescription cfg, String ids[]){ + ids = ids != null && ids.length != 0 ? (String[])ids.clone() : ids; + cfg.setSessionProperty(NATURES_USED_ON_CACHE_PROPERTY, ids); + } + private Configuration load(ICConfigurationDescription des, ManagedProject mProj, boolean isPreference) throws CoreException{ ICStorageElement rootElement = des.getStorage(BUILD_SYSTEM_DATA_MODULE_NAME, true); ICStorageElement children[] = rootElement.getChildren(); @@ -428,6 +460,7 @@ public class ConfigurationDataProvider extends CConfigurationDataProvider implem cfg.setConfigurationDescription(des); info.setValid(true); setPersistedFlag(des); + cacheNaturesIdsUsedOnCache(des); return cfg.getConfigurationData(); } return null; diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/settings/model/util/ResourceChangeHandlerBase.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/settings/model/util/ResourceChangeHandlerBase.java index ff7595c2ad2..9444fc1d9a4 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/settings/model/util/ResourceChangeHandlerBase.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/settings/model/util/ResourceChangeHandlerBase.java @@ -121,33 +121,36 @@ public abstract class ResourceChangeHandlerBase implements IResourceChangeListen */ public void resourceChanged(IResourceChangeEvent event) { if (event.getSource() instanceof IWorkspace) { - IResourceMoveHandler handler = createResourceMoveHandler(event); - switch (event.getType()) { - case IResourceChangeEvent.PRE_CLOSE: - handler.handleProjectClose((IProject)event.getResource()); - break; + doHahdleResourceMove(event, handler); + } + } + + protected void doHahdleResourceMove(IResourceChangeEvent event, IResourceMoveHandler handler){ + switch (event.getType()) { + case IResourceChangeEvent.PRE_CLOSE: + handler.handleProjectClose((IProject)event.getResource()); + break; // case IResourceChangeEvent.PRE_DELETE : // handler.handleResourceRemove(event.getResource()); // break; - case IResourceChangeEvent.POST_CHANGE : - IResourceDelta resDelta = event.getDelta(); - if (resDelta == null) { - break; - } - try { - DeltaVisitor rcChecker = new DeltaVisitor(handler, resDelta); - resDelta.accept(rcChecker); - } catch (CoreException e) { - CCorePlugin.log(e); - } + case IResourceChangeEvent.POST_CHANGE : + IResourceDelta resDelta = event.getDelta(); + if (resDelta == null) { break; - default : - break; - } - - handler.done(); + } + try { + DeltaVisitor rcChecker = new DeltaVisitor(handler, resDelta); + resDelta.accept(rcChecker); + } catch (CoreException e) { + CCorePlugin.log(e); + } + break; + default : + break; } + + handler.done(); } protected abstract IResourceMoveHandler createResourceMoveHandler(IResourceChangeEvent event);