# HG changeset patch # User timkelly # Date 1249578118 18000 # Node ID 42077b7eab6e830306beaf99843b2f78c0a4e2bb # Parent 49c226a8748eb78c9e75d80adf60e1edab345aab Second merge to proper cdt_6_0 branch for CDT bugs 181020, 279844, & Carbide bugs 6152 & 9031. diff -r 49c226a8748e -r 42077b7eab6e cdt/cdt_6_0_x/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/util/CElementBaseLabels.java --- a/cdt/cdt_6_0_x/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/util/CElementBaseLabels.java Wed Aug 05 17:35:39 2009 -0500 +++ b/cdt/cdt_6_0_x/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/util/CElementBaseLabels.java Thu Aug 06 12:01:58 2009 -0500 @@ -33,6 +33,7 @@ import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; /** * Creates labels for ICElement objects. @@ -758,7 +759,14 @@ if (rootQualified) { buf.append(container.getPath().makeRelative().toString()); } else { - buf.append(container.getElementName()); + if (CCorePlugin.showSourceRootsAtTopOfProject()) { + buf.append(container.getElementName()); + } + else { + String elementName = container.getElementName(); + IPath path = new Path(elementName); + buf.append(path.lastSegment()); + } if (getFlag(flags, ROOT_QUALIFIED)) { if (resource != null && container instanceof ISourceRoot && isReferenced((ISourceRoot)container)) { buf.append(CONCAT_STRING); diff -r 49c226a8748e -r 42077b7eab6e cdt/cdt_6_0_x/org.eclipse.cdt.core/model/org/eclipse/cdt/core/settings/model/CLibraryFileEntry.java --- a/cdt/cdt_6_0_x/org.eclipse.cdt.core/model/org/eclipse/cdt/core/settings/model/CLibraryFileEntry.java Wed Aug 05 17:35:39 2009 -0500 +++ b/cdt/cdt_6_0_x/org.eclipse.cdt.core/model/org/eclipse/cdt/core/settings/model/CLibraryFileEntry.java Thu Aug 06 12:01:58 2009 -0500 @@ -93,6 +93,18 @@ } @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((fSourceAttachmentPath == null) ? 0 : fSourceAttachmentPath.hashCode()); + result = prime * result + + ((fSourceAttachmentPrefixMapping == null) ? 0 : fSourceAttachmentPrefixMapping.hashCode()); + result = prime * result + + ((fSourceAttachmentRootPath == null) ? 0 : fSourceAttachmentRootPath.hashCode()); + return result; + } + + @Override public boolean equals(Object other) { if(other == this) return true; diff -r 49c226a8748e -r 42077b7eab6e cdt/cdt_6_0_x/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/APathEntry.java --- a/cdt/cdt_6_0_x/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/APathEntry.java Wed Aug 05 17:35:39 2009 -0500 +++ b/cdt/cdt_6_0_x/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/APathEntry.java Thu Aug 06 12:01:58 2009 -0500 @@ -81,6 +81,16 @@ } @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((basePath == null) ? 0 : basePath.hashCode()); + result = prime * result + ((baseRef == null) ? 0 : baseRef.hashCode()); + result = prime * result + Arrays.hashCode(exclusionPatterns); + return result; + } + + @Override public boolean equals(Object obj) { if (obj instanceof APathEntry) { APathEntry otherEntry = (APathEntry)obj; @@ -125,16 +135,6 @@ return super.equals(obj); } - @Override - public int hashCode() { - int hashCode = Arrays.hashCode(exclusionPatterns); - if (basePath != null) - hashCode += basePath.hashCode(); - if (baseRef != null) - hashCode += baseRef.hashCode(); - return hashCode + super.hashCode(); - } - /* (non-Javadoc) * @see java.lang.Object#toString() */ @@ -150,4 +150,5 @@ } return sb.toString(); } + } diff -r 49c226a8748e -r 42077b7eab6e cdt/cdt_6_0_x/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/IncludeEntry.java --- a/cdt/cdt_6_0_x/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/IncludeEntry.java Wed Aug 05 17:35:39 2009 -0500 +++ b/cdt/cdt_6_0_x/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/IncludeEntry.java Thu Aug 06 12:01:58 2009 -0500 @@ -49,6 +49,16 @@ return isSystemInclude; } +@Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + + ((includePath == null) ? 0 : includePath.hashCode()); + result = prime * result + (isSystemInclude ? 1231 : 1237); + return result; + } + @Override public boolean equals(Object obj) { if (obj instanceof IIncludeEntry) { diff -r 49c226a8748e -r 42077b7eab6e cdt/cdt_6_0_x/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/IncludeFileEntry.java --- a/cdt/cdt_6_0_x/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/IncludeFileEntry.java Wed Aug 05 17:35:39 2009 -0500 +++ b/cdt/cdt_6_0_x/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/IncludeFileEntry.java Thu Aug 06 12:01:58 2009 -0500 @@ -41,6 +41,16 @@ } @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + + ((includeFilePath == null) ? 0 : includeFilePath.hashCode()); + return result; + } + + + @Override public boolean equals(Object obj) { if (obj instanceof IIncludeFileEntry) { IIncludeFileEntry otherEntry = (IIncludeFileEntry) obj; diff -r 49c226a8748e -r 42077b7eab6e cdt/cdt_6_0_x/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/LibraryEntry.java --- a/cdt/cdt_6_0_x/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/LibraryEntry.java Wed Aug 05 17:35:39 2009 -0500 +++ b/cdt/cdt_6_0_x/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/LibraryEntry.java Thu Aug 06 12:01:58 2009 -0500 @@ -133,6 +133,17 @@ return super.equals(obj); } + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((libraryPath == null) ? 0 : libraryPath.hashCode()); + result = prime * result + ((sourceAttachmentPath == null) ? 0 : sourceAttachmentPath.hashCode()); + result = prime * result + + ((sourceAttachmentRootPath == null) ? 0 : sourceAttachmentRootPath.hashCode()); + return result; + } + public IPath getFullLibraryPath() { IPath p; IPath lib = getLibraryPath(); diff -r 49c226a8748e -r 42077b7eab6e cdt/cdt_6_0_x/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/MacroEntry.java --- a/cdt/cdt_6_0_x/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/MacroEntry.java Wed Aug 05 17:35:39 2009 -0500 +++ b/cdt/cdt_6_0_x/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/MacroEntry.java Thu Aug 06 12:01:58 2009 -0500 @@ -45,6 +45,17 @@ } @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + + ((macroName == null) ? 0 : macroName.hashCode()); + result = prime * result + + ((macroValue == null) ? 0 : macroValue.hashCode()); + return result; + } + + @Override public boolean equals(Object obj) { if (obj instanceof IMacroEntry) { IMacroEntry otherEntry = (IMacroEntry)obj; @@ -74,11 +85,6 @@ return super.equals(obj); } - @Override - public int hashCode() { - return macroName.hashCode() + macroValue.hashCode() + super.hashCode(); - } - /* (non-Javadoc) * @see java.lang.Object#toString() */ diff -r 49c226a8748e -r 42077b7eab6e cdt/cdt_6_0_x/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/MacroFileEntry.java --- a/cdt/cdt_6_0_x/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/MacroFileEntry.java Wed Aug 05 17:35:39 2009 -0500 +++ b/cdt/cdt_6_0_x/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/MacroFileEntry.java Thu Aug 06 12:01:58 2009 -0500 @@ -40,6 +40,15 @@ } @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + + ((macroFilePath == null) ? 0 : macroFilePath.hashCode()); + return result; + } + + @Override public boolean equals(Object obj) { if (obj instanceof IMacroFileEntry) { IMacroFileEntry otherEntry = (IMacroFileEntry) obj; diff -r 49c226a8748e -r 42077b7eab6e cdt/cdt_6_0_x/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/PathEntry.java --- a/cdt/cdt_6_0_x/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/PathEntry.java Wed Aug 05 17:35:39 2009 -0500 +++ b/cdt/cdt_6_0_x/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/PathEntry.java Thu Aug 06 12:01:58 2009 -0500 @@ -73,7 +73,12 @@ @Override public int hashCode() { - return path.hashCode() + entryKind * 17 + (isExported ? 3 : 2); + final int prime = 31; + int result = 1; + result = prime * result + entryKind; + result = prime * result + (isExported ? 1231 : 1237); + result = prime * result + ((path == null) ? 0 : path.hashCode()); + return result; } /** diff -r 49c226a8748e -r 42077b7eab6e cdt/cdt_6_0_x/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/PathEntryUtil.java --- a/cdt/cdt_6_0_x/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/PathEntryUtil.java Wed Aug 05 17:35:39 2009 -0500 +++ b/cdt/cdt_6_0_x/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/PathEntryUtil.java Thu Aug 06 12:01:58 2009 -0500 @@ -12,9 +12,12 @@ package org.eclipse.cdt.internal.core.model; import java.io.File; +import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashSet; import java.util.List; +import java.util.Set; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.model.CModelException; @@ -335,17 +338,17 @@ public static ICModelStatus validatePathEntry(ICProject cProject, IPathEntry[] entries) { // Check duplication. + Set entrySet = new HashSet(entries.length); for (IPathEntry entry : entries) { - if (entry == null) { - continue; - } - for (IPathEntry otherEntry : entries) { - if (otherEntry == null) { - continue; + if (entry != null) { + if (entrySet.contains(entry)) { + return new CModelStatus(ICModelStatusConstants.INVALID_PATHENTRY, + MessageFormat.format("{0}{1}", //$NON-NLS-1$ + CCorePlugin.getResourceString("CoreModel.PathEntry.DuplicateEntry"), //$NON-NLS-1$ + entry.getPath().toString())); } - if (entry != otherEntry && otherEntry.equals(entry)) { - StringBuffer errMesg = new StringBuffer(CCorePlugin.getResourceString("CoreModel.PathEntry.DuplicateEntry")); //$NON-NLS-1$ - return new CModelStatus(ICModelStatusConstants.INVALID_PATHENTRY, errMesg.toString()); + else { + entrySet.add(entry); } } } diff -r 49c226a8748e -r 42077b7eab6e cdt/cdt_6_0_x/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/CProjectDescriptionManager.java --- a/cdt/cdt_6_0_x/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/CProjectDescriptionManager.java Wed Aug 05 17:35:39 2009 -0500 +++ b/cdt/cdt_6_0_x/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/settings/model/CProjectDescriptionManager.java Thu Aug 06 12:01:58 2009 -0500 @@ -1793,14 +1793,15 @@ newEntries = EMPTY_LANGUAGE_SETTINGS_ENTRIES_ARRAY; } + Set newEntrySet = new HashSet(Arrays.asList(newEntries)); + Set oldEntrySet = new HashSet(Arrays.asList(oldEntries)); + // Check the removed entries. - for (int i = 0; i < oldEntries.length; i++) { + for (ICLanguageSettingEntry oldEntry : oldEntries) { boolean found = false; - for (int j = 0; j < newEntries.length; j++) { - if (oldEntries[i].equals(newEntries[j])) { - found = true; - break; - } + if (newEntrySet.contains(oldEntry)) { + found = true; + break; } if(!found){ result[1] = true; @@ -1809,13 +1810,11 @@ } // Check the new entries. - for (int i = 0; i < newEntries.length; i++) { + for (ICLanguageSettingEntry newEntry : newEntries) { boolean found = false; - for (int j = 0; j < oldEntries.length; j++) { - if (newEntries[i].equals(oldEntries[j])) { - found = true; - break; - } + if (oldEntrySet.contains(newEntry)) { + found = true; + break; } if(!found){ result[0] = true; diff -r 49c226a8748e -r 42077b7eab6e cdt/cdt_6_0_x/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java --- a/cdt/cdt_6_0_x/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java Wed Aug 05 17:35:39 2009 -0500 +++ b/cdt/cdt_6_0_x/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java Thu Aug 06 12:01:58 2009 -0500 @@ -1262,4 +1262,14 @@ public static IPDOMManager getPDOMManager() { return getDefault().pdomManager; } + + /** + * Returns preference controlling whether source roots are shown at the top of projects + * or embedded within the resource tree of projects when they are not top level folders. + * + * @return boolean preference value + */ + public static boolean showSourceRootsAtTopOfProject() { + return getDefault().getPluginPreferences().getBoolean( CCorePreferenceConstants.SHOW_SOURCE_ROOTS_AT_TOP_LEVEL_OF_PROJECT); + } } \ No newline at end of file diff -r 49c226a8748e -r 42077b7eab6e cdt/cdt_6_0_x/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePreferenceConstants.java --- a/cdt/cdt_6_0_x/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePreferenceConstants.java Wed Aug 05 17:35:39 2009 -0500 +++ b/cdt/cdt_6_0_x/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePreferenceConstants.java Thu Aug 06 12:01:58 2009 -0500 @@ -135,4 +135,9 @@ * Attempt to show source files for executable binaries. */ public static final String SHOW_SOURCE_FILES_IN_BINARIES = CCorePlugin.PLUGIN_ID + ".showSourceFilesInBinaries"; //$NON-NLS-1$ + + /** + * Show source roots at the top level of projects. + */ + public static final String SHOW_SOURCE_ROOTS_AT_TOP_LEVEL_OF_PROJECT = CCorePlugin.PLUGIN_ID + ".showSourceRootsAtTopLevelOfProject"; //$NON-NLS-1$ } diff -r 49c226a8748e -r 42077b7eab6e cdt/cdt_6_0_x/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/CCorePluginResources.properties --- a/cdt/cdt_6_0_x/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/CCorePluginResources.properties Wed Aug 05 17:35:39 2009 -0500 +++ b/cdt/cdt_6_0_x/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/CCorePluginResources.properties Thu Aug 06 12:01:58 2009 -0500 @@ -22,7 +22,7 @@ CoreModel.NullBinaryParser.Null_Format=Null Format CoreModel.PathEntry.IllegalContainerPath= Illegal container entry -CoreModel.PathEntry.DuplicateEntry= Duplicate path entries +CoreModel.PathEntry.DuplicateEntry= Duplicate path entries found: {0} CoreModel.PathEntry.NestedEntry= Nested path entries CoreModel.PathEntry.InvalidPathEntry= Invalid path diff -r 49c226a8748e -r 42077b7eab6e cdt/cdt_6_0_x/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/CCorePreferenceInitializer.java --- a/cdt/cdt_6_0_x/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/CCorePreferenceInitializer.java Wed Aug 05 17:35:39 2009 -0500 +++ b/cdt/cdt_6_0_x/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/CCorePreferenceInitializer.java Thu Aug 06 12:01:58 2009 -0500 @@ -59,6 +59,8 @@ defaultPreferences.putBoolean(CCorePreferenceConstants.SHOW_SOURCE_FILES_IN_BINARIES, true); defaultPreferences.putBoolean(CCorePlugin.PREF_USE_STRUCTURAL_PARSE_MODE, false); + + defaultPreferences.putBoolean(CCorePreferenceConstants.SHOW_SOURCE_ROOTS_AT_TOP_LEVEL_OF_PROJECT, true); // indexer defaults IndexerPreferences.initializeDefaultPreferences(defaultPreferences); diff -r 49c226a8748e -r 42077b7eab6e cdt/cdt_6_0_x/org.eclipse.cdt.debug.core/plugin.xml --- a/cdt/cdt_6_0_x/org.eclipse.cdt.debug.core/plugin.xml Wed Aug 05 17:35:39 2009 -0500 +++ b/cdt/cdt_6_0_x/org.eclipse.cdt.debug.core/plugin.xml Thu Aug 06 12:01:58 2009 -0500 @@ -5,6 +5,10 @@ + + + + diff -r 49c226a8748e -r 42077b7eab6e cdt/cdt_6_0_x/org.eclipse.cdt.debug.core/schema/ExecutablesImporter.exsd --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cdt/cdt_6_0_x/org.eclipse.cdt.debug.core/schema/ExecutablesImporter.exsd Thu Aug 06 12:01:58 2009 -0500 @@ -0,0 +1,86 @@ + + + + + + + + + This extension points allows you to extened the executables manager in CDT by providing your own executables importer. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CDT 7.0 + + + + + + + + + <extension + point="org.eclipse.cdt.debug.core.ExecutablesImporter"> + <modifier class="com.xyz.MyExecutablesImporter"/> + </extension> + + + + diff -r 49c226a8748e -r 42077b7eab6e cdt/cdt_6_0_x/org.eclipse.cdt.debug.core/schema/ExecutablesProvider.exsd --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cdt/cdt_6_0_x/org.eclipse.cdt.debug.core/schema/ExecutablesProvider.exsd Thu Aug 06 12:01:58 2009 -0500 @@ -0,0 +1,86 @@ + + + + + + + + + This extension points allows you to extened the executables manager in CDT by providing your own executables provider for certain types of projects. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CDT 7.0 + + + + + + + + + <extension + point="org.eclipse.cdt.debug.core.ExecutablesProvider"> + <modifier class="com.xyz.MyExecutablesProvider"/> + </extension> + + + + diff -r 49c226a8748e -r 42077b7eab6e cdt/cdt_6_0_x/org.eclipse.cdt.debug.core/schema/SourceFilesProvider.exsd --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cdt/cdt_6_0_x/org.eclipse.cdt.debug.core/schema/SourceFilesProvider.exsd Thu Aug 06 12:01:58 2009 -0500 @@ -0,0 +1,86 @@ + + + + + + + + + This extension points allows you to extened the executables manager in CDT by providing your own source files provider for certain types of executables. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CDT 7.0 + + + + + + + + + <extension + point="org.eclipse.cdt.debug.core.SourceFilesProvider"> + <modifier class="com.xyz.MySourceFilesProvider"/> + </extension> + + + + diff -r 49c226a8748e -r 42077b7eab6e cdt/cdt_6_0_x/org.eclipse.cdt.debug.core/schema/SourceRemappingProvider.exsd --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cdt/cdt_6_0_x/org.eclipse.cdt.debug.core/schema/SourceRemappingProvider.exsd Thu Aug 06 12:01:58 2009 -0500 @@ -0,0 +1,86 @@ + + + + + + + + + This extension points allows you to extened the executables manager in CDT by providing your own source remapping provider. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CDT 7.0 + + + + + + + + + <extension + point="org.eclipse.cdt.debug.core.SourceRemappingProvider"> + <modifier class="com.xyz.MySourceRemappingProvider"/> + </extension> + + + + diff -r 49c226a8748e -r 42077b7eab6e cdt/cdt_6_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/Executable.java --- a/cdt/cdt_6_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/Executable.java Wed Aug 05 17:35:39 2009 -0500 +++ b/cdt/cdt_6_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/Executable.java Thu Aug 06 12:01:58 2009 -0500 @@ -135,7 +135,7 @@ * @noreference This method is not intended to be referenced by clients. * @since 6.0 */ - public TranslationUnit[] getSourceFiles(IProgressMonitor monitor) { + public synchronized TranslationUnit[] getSourceFiles(IProgressMonitor monitor) { if (!refreshSourceFiles) return sourceFiles.toArray(new TranslationUnit[sourceFiles.size()]) ; @@ -241,7 +241,7 @@ this.refreshSourceFiles = refreshSourceFiles; } - public String getOriginalLocation(ITranslationUnit tu) { + public synchronized String getOriginalLocation(ITranslationUnit tu) { String orgLocation = remappedPaths.get(tu); if (orgLocation == null) orgLocation = tu.getLocation().toOSString(); diff -r 49c226a8748e -r 42077b7eab6e cdt/cdt_6_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/ExecutablesManager.java --- a/cdt/cdt_6_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/ExecutablesManager.java Wed Aug 05 17:35:39 2009 -0500 +++ b/cdt/cdt_6_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/ExecutablesManager.java Thu Aug 06 12:01:58 2009 -0500 @@ -11,29 +11,50 @@ package org.eclipse.cdt.debug.core.executables; +import java.text.DateFormat; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; +import java.util.Date; import java.util.HashMap; import java.util.List; +import java.util.Map; +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.core.settings.model.CProjectDescriptionEvent; +import org.eclipse.cdt.core.settings.model.ICProjectDescription; +import org.eclipse.cdt.core.settings.model.ICProjectDescriptionListener; import org.eclipse.cdt.debug.core.CDebugCorePlugin; -import org.eclipse.cdt.debug.internal.core.executables.ExecutablesChangeEvent; import org.eclipse.cdt.debug.internal.core.executables.StandardExecutableImporter; -import org.eclipse.cdt.debug.internal.core.executables.StandardExecutableProvider; import org.eclipse.cdt.debug.internal.core.executables.StandardSourceFileRemapping; import org.eclipse.cdt.debug.internal.core.executables.StandardSourceFilesProvider; +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.IResourceChangeListener; +import org.eclipse.core.resources.IResourceDelta; +import org.eclipse.core.resources.IResourceDeltaVisitor; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtension; +import org.eclipse.core.runtime.IExtensionPoint; +import org.eclipse.core.runtime.IExtensionRegistry; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.MultiStatus; +import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.PlatformObject; import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.SubMonitor; import org.eclipse.core.runtime.SubProgressMonitor; import org.eclipse.core.runtime.jobs.Job; -import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.osgi.service.debug.DebugOptions; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; /** * The Executables Manager maintains a collection of executables built by all of @@ -43,28 +64,75 @@ * @author Ken Ryall * */ -public class ExecutablesManager extends PlatformObject { +public class ExecutablesManager extends PlatformObject implements IResourceChangeListener, ICProjectDescriptionListener { - private final HashMap executables = new HashMap(); - private final List changeListeners = Collections.synchronizedList(new ArrayList()); - private final List sourceFileRemappings = Collections.synchronizedList(new ArrayList()); - private final List executableProviders = Collections.synchronizedList(new ArrayList()); - private final List sourceFileProviders = Collections.synchronizedList(new ArrayList()); - private final List executableImporters = Collections.synchronizedList(new ArrayList()); - private boolean refreshNeeded = true; - private boolean tempDisableRefresh = false; + private static final String EXECUTABLES_MANAGER_DEBUG_TRACING = CDebugCorePlugin.PLUGIN_ID + "EXECUTABLES_MANAGER_DEBUG_TRACING"; //$NON-NLS-1$ + + private Map executablesProviderMap = new HashMap(); + private Map> executablesMap = new HashMap>(); + private List changeListeners = Collections.synchronizedList(new ArrayList()); + private List executableProviders; + private List sourceFileProviders; + private List sourceFileRemappings; + private List executableImporters; + + private boolean DEBUG; private final Job refreshJob = new Job("Get Executables") { @Override public IStatus run(IProgressMonitor monitor) { - refreshExecutables(monitor); + + trace("Get Executables job started at " + + getStringFromTimestamp(System.currentTimeMillis())); + List projects = getProjectsToCheck(); + SubMonitor subMonitor = SubMonitor + .convert(monitor, projects.size()); + for (IProject project : projects) { + if (subMonitor.isCanceled()) { + trace("Get Executables job cancelled at " + + getStringFromTimestamp(System.currentTimeMillis())); + return Status.CANCEL_STATUS; + } + + subMonitor.subTask("Checking project: " + project.getName()); + + // get the executables provider for this project + IProjectExecutablesProvider provider = getExecutablesProviderForProject(project); + if (provider != null) { + trace("Getting executables for project: " + + project.getName() + " using " + + provider.toString()); + + // store the list of executables for this project + synchronized (executablesMap) { + executablesMap.put(project, provider.getExecutables( + project, subMonitor.newChild(1, + SubMonitor.SUPPRESS_NONE))); + } + } + } + + // notify the listeners + synchronized (changeListeners) { + for (IExecutablesChangeListener listener : changeListeners) { + listener.executablesListChanged(); + } + } + + trace("Get Executables job finished at " + + getStringFromTimestamp(System.currentTimeMillis())); + return Status.OK_STATUS; } }; private static ExecutablesManager executablesManager = null; - + + /** + * Get the executables manager instance + * @return the executables manager + * */ public static ExecutablesManager getExecutablesManager() { if (executablesManager == null) executablesManager = new ExecutablesManager(); @@ -72,126 +140,116 @@ } public ExecutablesManager() { - addSourceFileRemapping(new StandardSourceFileRemapping()); - addExecutableImporter(new StandardExecutableImporter()); - addExecutablesProvider(new StandardExecutableProvider()); - addSourceFilesProvider(new StandardSourceFilesProvider()); + // check if debugging is enabled + BundleContext context = CDebugCorePlugin.getDefault().getBundle().getBundleContext(); + if (context != null) { + ServiceReference reference = CDebugCorePlugin.getDefault().getBundle().getBundleContext().getServiceReference( + DebugOptions.class.getName()); + if (reference != null) { + DebugOptions service = (DebugOptions) context.getService(reference); + if (service != null) { + try { + DEBUG = service.getBooleanOption(EXECUTABLES_MANAGER_DEBUG_TRACING, false); + } finally { + // we have what we want - release the service + context.ungetService(reference); + } + } + } + } + + refreshJob.setPriority(Job.SHORT); + + // load the extension points + loadExecutableProviderExtensions(); + loadSoureFileProviderExtensions(); + loadSoureRemappingExtensions(); + loadExecutableImporterExtensions(); + + // add the standard providers + executableProviders.add(0, new StandardExecutableProvider()); + sourceFileProviders.add(0, new StandardSourceFilesProvider()); + sourceFileRemappings.add(0, new StandardSourceFileRemapping()); + executableImporters.add(0, new StandardExecutableImporter()); + + // listen for events we're interested in + ResourcesPlugin.getWorkspace().addResourceChangeListener( + this, IResourceChangeEvent.POST_CHANGE | IResourceChangeEvent.POST_BUILD); + CoreModel.getDefault().getProjectDescriptionManager().addCProjectDescriptionListener(this, CProjectDescriptionEvent.DATA_APPLIED); + + // schedule a refresh so we get up to date + scheduleRefresh(); } + + /** + * Adds an executable listener + * @param listener the listener to add + */ public void addExecutablesChangeListener(IExecutablesChangeListener listener) { changeListeners.add(listener); } + /** + * Removes an executable listener + * @param listener the listener to remove + */ public void removeExecutablesChangeListener(IExecutablesChangeListener listener) { changeListeners.remove(listener); } - public void addSourceFileRemapping(ISourceFileRemapping remapping) { - sourceFileRemappings.add(remapping); - } - - public void removeSourceFileRemapping(ISourceFileRemapping remapping) { - sourceFileRemappings.remove(remapping); - } - - public void addExecutableImporter(IExecutableImporter importer) { - executableImporters.add(importer); - } + /** + * Gets the list of executables in the workspace. + * @return the list of executables which may be empty + */ + public Collection getExecutables() { + trace("getExecutables called at " + + getStringFromTimestamp(System.currentTimeMillis())); + List executables = new ArrayList(); - public void removeExecutableImporter(IExecutableImporter importer) { - executableImporters.remove(importer); - } - - public void addExecutablesProvider(IExecutableProvider provider) { - executableProviders.add(provider); - } - - /** - * @since 6.0 - */ - public void addSourceFilesProvider(ISourceFilesProvider provider) { - sourceFileProviders.add(provider); + synchronized (executablesMap) { + for (List exes : executablesMap.values()) { + for (Executable exe : exes) { + if (!executables.contains(exe)) { + executables.add(exe); + } + } + } + } + trace("getExecutables returned at " + + getStringFromTimestamp(System.currentTimeMillis())); + return executables; } /** - * @since 6.0 - */ - public void removeSourceFilesProvider(ISourceFilesProvider provider) { - sourceFileProviders.remove(provider); - } - - public void removeExecutablesProvider(IExecutableProvider provider) { - executableProviders.remove(provider); - } - - public IStatus refreshExecutables(IProgressMonitor monitor) { - if (tempDisableRefresh) { - return Status.OK_STATUS; - } - - - synchronized (executables) { - HashMap oldList = new HashMap(executables); - executables.clear(); - - IExecutableProvider[] exeProviders = getExecutableProviders(); - - Arrays.sort(exeProviders, new Comparator() { - - public int compare(IExecutableProvider arg0, IExecutableProvider arg1) { - int p0 = arg0.getPriority(); - int p1 = arg1.getPriority(); - if (p0 > p1) - return 1; - if (p0 < p1) - return -1; - return 0; - }}); - - refreshNeeded = false; - monitor.beginTask("Refresh Executables", exeProviders.length); - for (IExecutableProvider provider : exeProviders) { - Executable[] exes = provider.getExecutables(new SubProgressMonitor(monitor, 1)); - for (Executable executable : exes) { - executables.put(executable.getPath().toOSString(), executable); - } - } - monitor.done(); - - synchronized (changeListeners) { - Collection newExes = executables.values(); - Executable[] exeArray = newExes.toArray(new Executable[newExes.size()]); - Collection oldExes = oldList.values(); - Executable[] oldArray = oldExes.toArray(new Executable[oldExes.size()]); - for (IExecutablesChangeListener listener : changeListeners) { - listener.executablesChanged(new ExecutablesChangeEvent(oldArray, exeArray)); + * @since 6.0 + * Gets the collection of executables for the given project + * @param project the project + * @return collection of executables which may be empty + * */ + public Collection getExecutablesForProject(IProject project) { + List executables = new ArrayList(); + synchronized (executablesMap) { + List exes = executablesMap.get(project); + if (exes != null) { + for (Executable exe : exes) { + if (!executables.contains(exe)) { + executables.add(exe); + } } } } - - return monitor.isCanceled() ? Status.CANCEL_STATUS : Status.OK_STATUS; - } - - public Executable[] getExecutables() { - if (refreshNeeded) { - try { - refreshJob.schedule(); - refreshJob.join(); - } catch (InterruptedException e) { - DebugPlugin.log( e ); - } - } - - synchronized (executables) - { - Collection exes = executables.values(); - return exes.toArray(new Executable[exes.size()]); - } - } - - /** - * @since 6.0 - */ + return executables; + } + + /** Attempt to remap the path to the given source file in the given executable using + * source file mapping extensions + * @param executable the executable + * @param filePath the absolute path to the source file + * @return the new path to the source file, which was remapped if possible + * + * @since 6.0 + */ public String remapSourceFile(Executable executable, String filePath) { synchronized (sourceFileRemappings) { for (ISourceFileRemapping remapping : sourceFileRemappings) { @@ -202,83 +260,70 @@ } return filePath; } - + /** + * Import the given executables into the manager + * @param fileNames the absolute paths of the executables to import + * @param monitor progress monitor + */ public void importExecutables(final String[] fileNames, IProgressMonitor monitor) { boolean handled = false; - try { - - tempDisableRefresh = true; - monitor.beginTask("Import Executables", executableImporters.size()); - synchronized (executableImporters) { - Collections.sort(executableImporters, new Comparator() { + + monitor.beginTask("Import Executables", executableImporters.size()); + synchronized (executableImporters) { + Collections.sort(executableImporters, + new Comparator() { + + public int compare(IExecutableImporter arg0, + IExecutableImporter arg1) { + int p0 = arg0.getPriority(fileNames); + int p1 = arg1.getPriority(fileNames); + if (p0 < p1) + return 1; + if (p0 > p1) + return -1; + return 0; + } + }); - public int compare(IExecutableImporter arg0, IExecutableImporter arg1) { - int p0 = arg0.getPriority(fileNames); - int p1 = arg1.getPriority(fileNames); - if (p0 < p1) - return 1; - if (p0 > p1) - return -1; - return 0; - }}); - - for (IExecutableImporter importer : executableImporters) { - handled = importer.importExecutables(fileNames, new SubProgressMonitor(monitor, 1)); - if (handled || monitor.isCanceled()) { - break; - } + for (IExecutableImporter importer : executableImporters) { + if (handled || monitor.isCanceled()) { + break; + } + } + } + scheduleRefresh(); + } + + /** + * Determines if the given executable is currently known by the manager + * * @param exePath + * the absolute path to the executable + * @return true if the manager knows about it, false otherwise + */ + public boolean executableExists(IPath exePath) { + synchronized (executablesMap) { + for (List exes : executablesMap.values()) { + for (Executable exe : exes) { + if (exe.getPath().equals(exePath)) { + return true; } + } + } } + return false; } - } finally { - tempDisableRefresh = false; - } - - if (handled) - refreshExecutables(monitor); - monitor.done(); - } - - public ISourceFileRemapping[] getSourceFileRemappings() { - return sourceFileRemappings.toArray(new ISourceFileRemapping[sourceFileRemappings.size()]); - } - - public IExecutableProvider[] getExecutableProviders() { - return executableProviders.toArray(new IExecutableProvider[executableProviders.size()]); - } - - /** - * @since 6.0 - */ - public ISourceFilesProvider[] getSourceFileProviders() { - return sourceFileProviders.toArray(new ISourceFilesProvider[sourceFileProviders.size()]); - } + + /** + * Get the list of source files for the given executable + * @param executable the executable + * @param monitor progress monitor + * @return an array of source files which may be empty + */ + public String[] getSourceFiles(final Executable executable, IProgressMonitor monitor) { + String[] result = new String[0]; + + trace("getSourceFiles called at " + getStringFromTimestamp(System.currentTimeMillis()) + " for " + executable.getPath().toOSString()); - public IExecutableImporter[] getExecutableImporters() { - return executableImporters.toArray(new IExecutableImporter[executableImporters.size()]); - } - - public void scheduleRefresh(IExecutableProvider provider, long delay) { - refreshNeeded = true; - refreshJob.schedule(delay); - } - - public boolean refreshNeeded() { - return refreshNeeded; - } - - public boolean executableExists(IPath exePath) { - synchronized (executables) { - return executables.containsKey(exePath.toOSString()); - } - } - - /** - * @since 6.0 - */ - public String[] getSourceFiles(final Executable executable, - IProgressMonitor monitor) { - String[] result = new String[0]; synchronized (sourceFileProviders) { Collections.sort(sourceFileProviders, new Comparator() { @@ -295,67 +340,463 @@ monitor.beginTask("Finding source files in " + executable.getName(), sourceFileProviders.size()); for (ISourceFilesProvider provider : sourceFileProviders) { String[] sourceFiles = provider.getSourceFiles(executable, new SubProgressMonitor(monitor, 1)); - if (sourceFiles.length > 0) - { + if (sourceFiles.length > 0) { result = sourceFiles; + + trace("getSourceFiles got " + sourceFiles.length + " files from " + provider.toString()); + break; } } monitor.done(); } - return result; - } - - /** - * @since 6.0 - */ - public IStatus removeExecutables(Executable[] executables, IProgressMonitor monitor) { - IExecutableProvider[] exeProviders = getExecutableProviders(); - - IStatus result = Status.OK_STATUS; - Arrays.sort(exeProviders, new Comparator() { - - public int compare(IExecutableProvider arg0, IExecutableProvider arg1) { - int p0 = arg0.getPriority(); - int p1 = arg1.getPriority(); - if (p0 > p1) - return 1; - if (p0 < p1) - return -1; - return 0; - } - }); - - MultiStatus combinedStatus = new MultiStatus(CDebugCorePlugin.PLUGIN_ID, IStatus.WARNING, "Couldn't remove all of the selected executables", null); - refreshNeeded = false; - monitor.beginTask("Remove Executables", exeProviders.length); - for (Executable executable : executables) { - boolean handled = false; - IStatus rmvStatus = Status.OK_STATUS;; - for (IExecutableProvider provider : exeProviders) { - if (!handled) - { - rmvStatus = provider.removeExecutable(executable, new SubProgressMonitor(monitor, 1)); - handled = rmvStatus.getSeverity() == IStatus.OK; - } - } - if (!handled) - { - combinedStatus.add(rmvStatus); - result = combinedStatus; - } - } - monitor.done(); + trace("getSourceFiles returned at " + getStringFromTimestamp(System.currentTimeMillis())); return result; } + /** + * Removes the given executables + * @param executables the array of executables to be removed + * @param monitor progress monitor + * @return IStatus of the operation + * + * @since 6.0 + */ + public IStatus removeExecutables(Executable[] executables, IProgressMonitor monitor) { + + MultiStatus status = new MultiStatus(CDebugCorePlugin.PLUGIN_ID, IStatus.WARNING, "Couldn't remove all of the selected executables", null); + + monitor.beginTask("Remove Executables", executables.length); + for (Executable executable : executables) { + IProjectExecutablesProvider provider = getExecutablesProviderForProject(executable + .getProject()); + if (provider != null) { + IStatus result = provider.removeExecutable(executable, + new SubProgressMonitor(monitor, 1)); + if (result.isOK()) { + // remove the exe from the list + List exes = executablesMap.get(executable + .getProject()); + if (exes != null) { + exes.remove(executable); + } + } else { + status.add(result); + } + } + } + // notify listeners that the list has changed. only do this if at least one delete succeeded. + if (status.getChildren().length != executables.length) { + synchronized (changeListeners) { + for (IExecutablesChangeListener listener : changeListeners) { + listener.executablesListChanged(); + } + } + } + + return status; + } + /** - * @since 6.0 + * Refresh the list of executables for the given projects + * + * @param projects + * the list of projects, or null. if null or the list is empty, + * all projects will be refreshed. */ - public void setRefreshNeeded(boolean refresh) { - refreshNeeded = true; + public void refresh(List projects) { + if (projects == null || projects.size() == 0) { + // clear the entire cache + executablesMap.clear(); + } else { + for (IProject project : projects) { + executablesMap.remove(project); + } + } + + scheduleRefresh(); + } + + public void resourceChanged(IResourceChangeEvent event) { + + synchronized (executablesMap) { + // project needs to be refreshed after a build/clean as the binary + // may + // be added/removed/renamed etc. + if (event.getType() == IResourceChangeEvent.POST_BUILD) { + Object obj = event.getSource(); + if (obj != null && obj instanceof IProject) { + if (executablesMap.containsKey(obj)) { + List executables = executablesMap + .remove(obj); + + trace("Scheduling refresh because project " + + ((IProject) obj).getName() + + " built or cleaned"); + + scheduleRefresh(); + + // notify the listeners that these executables have + // possibly changed + if (executables != null && executables.size() > 0) { + synchronized (changeListeners) { + for (IExecutablesChangeListener listener : changeListeners) { + listener.executablesChanged(executables); + } + } + } + } + } + return; + } + + // refresh when projects are opened or closed. note that deleted + // projects are handled later in this method. new projects are + // handled + // in handleEvent. resource changed events always start at the + // workspace + // root, so projects are the next level down + boolean refreshNeeded = false; + IResourceDelta[] projects = event.getDelta().getAffectedChildren(); + for (IResourceDelta projectDelta : projects) { + if ((projectDelta.getFlags() & IResourceDelta.OPEN) != 0) { + if (projectDelta.getKind() == IResourceDelta.CHANGED) { + // project was opened or closed + if (executablesMap.containsKey(projectDelta + .getResource())) { + executablesMap.remove(projectDelta.getResource()); + } + refreshNeeded = true; + } + } + } + + if (refreshNeeded) { + trace("Scheduling refresh because project(s) opened or closed"); + + scheduleRefresh(); + return; + } + + try { + event.getDelta().accept(new IResourceDeltaVisitor() { + + public boolean visit(IResourceDelta delta) + throws CoreException { + if (delta.getKind() == IResourceDelta.ADDED + || delta.getKind() == IResourceDelta.REMOVED) { + IResource deltaResource = delta.getResource(); + if (deltaResource != null) { + boolean refresh = false; + if (delta.getKind() == IResourceDelta.REMOVED + && deltaResource instanceof IProject) { + // project deleted + if (executablesMap + .containsKey(deltaResource)) { + executablesMap.remove(deltaResource); + refresh = true; + + trace("Scheduling refresh because project " + + deltaResource.getName() + + " deleted"); + } + } else { + // see if a binary has been added/removed + IPath resourcePath = deltaResource + .getLocation(); + if (resourcePath != null + && Executable + .isExecutableFile(resourcePath)) { + if (executablesMap + .containsKey(deltaResource + .getProject())) { + executablesMap.remove(deltaResource + .getProject()); + refresh = true; + + trace("Scheduling refresh because a binary was added/removed"); + } + } + } + + if (refresh) { + scheduleRefresh(); + return false; + } + } + } + return true; + } + }); + } catch (CoreException e) { + } + } + } + + public void handleEvent(CProjectDescriptionEvent event) { + // this handles the cases where the active build configuration changes, + // and when new projects are created or loaded at startup. + boolean refresh = false; + + int eventType = event.getEventType(); + + if (eventType == CProjectDescriptionEvent.DATA_APPLIED) { + + synchronized (executablesMap) { + // see if the active build config has changed + ICProjectDescription newDesc = event + .getNewCProjectDescription(); + ICProjectDescription oldDesc = event + .getOldCProjectDescription(); + if (oldDesc != null && newDesc != null) { + String newConfigName = newDesc.getActiveConfiguration() + .getName(); + String oldConfigName = oldDesc.getActiveConfiguration() + .getName(); + if (!newConfigName.equals(oldConfigName)) { + if (executablesMap.containsKey(newDesc.getProject())) { + executablesMap.remove(newDesc.getProject()); + refresh = true; + + trace("Scheduling refresh because active build configuration changed"); + } + } + } else if (newDesc != null && oldDesc == null) { + // project just created + refresh = true; + + trace("Scheduling refresh because project " + + newDesc.getProject().getName() + " created"); + } + } + } + + if (refresh) { + scheduleRefresh(); + } } -} \ No newline at end of file + private List getProjectsToCheck() { + + List projects = new ArrayList(); + + synchronized (executablesMap) { + // look for any CDT projects not in our cache + for (IProject project : ResourcesPlugin.getWorkspace().getRoot() + .getProjects()) { + if (!executablesMap.containsKey(project)) { + if (CoreModel.hasCNature(project)) { + projects.add(project); + } + } + } + } + + return projects; + } + + private void scheduleRefresh() { + trace("scheduleRefresh called at " + + getStringFromTimestamp(System.currentTimeMillis())); + + refreshJob.cancel(); + refreshJob.schedule(); + } + + private IProjectExecutablesProvider getExecutablesProviderForProject( + IProject project) { + IProjectExecutablesProvider provider = executablesProviderMap + .get(project); + if (provider == null) { + // not cached yet. get the list of project natures from the + // providers and + // pick the one with the closest match + try { + IProjectDescription description = project.getDescription(); + int mostNaturesMatched = 0; + for (IProjectExecutablesProvider exeProvider : executableProviders) { + List natures = exeProvider.getProjectNatures(); + + int naturesMatched = 0; + for (String nature : description.getNatureIds()) { + if (natures.contains(nature)) { + naturesMatched++; + } + } + + if (naturesMatched > mostNaturesMatched) { + provider = exeProvider; + mostNaturesMatched = naturesMatched; + } + } + + // cache it + executablesProviderMap.put(project, provider); + + } catch (CoreException e) { + e.printStackTrace(); + } + } + + return provider; + } + + private void loadExecutableProviderExtensions() { + executableProviders = Collections + .synchronizedList(new ArrayList()); + + IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry(); + IExtensionPoint extensionPoint = extensionRegistry + .getExtensionPoint(CDebugCorePlugin.PLUGIN_ID + + ".ExecutablesProvider"); //$NON-NLS-1$ + IExtension[] extensions = extensionPoint.getExtensions(); + + for (int i = 0; i < extensions.length; i++) { + IExtension extension = extensions[i]; + IConfigurationElement[] elements = extension + .getConfigurationElements(); + IConfigurationElement element = elements[0]; + + boolean failed = false; + try { + Object extObject = element.createExecutableExtension("class"); //$NON-NLS-1$ + if (extObject instanceof IProjectExecutablesProvider) { + executableProviders + .add((IProjectExecutablesProvider) extObject); + } else { + failed = true; + } + } catch (CoreException e) { + failed = true; + } + + if (failed) { + CDebugCorePlugin + .log("Unable to load ExecutablesProvider extension from " + + extension.getContributor().getName()); + } + } + } + + private void loadSoureFileProviderExtensions() { + sourceFileProviders = Collections + .synchronizedList(new ArrayList()); + + IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry(); + IExtensionPoint extensionPoint = extensionRegistry + .getExtensionPoint(CDebugCorePlugin.PLUGIN_ID + + ".SourceFilesProvider"); //$NON-NLS-1$ + IExtension[] extensions = extensionPoint.getExtensions(); + + for (int i = 0; i < extensions.length; i++) { + IExtension extension = extensions[i]; + IConfigurationElement[] elements = extension + .getConfigurationElements(); + IConfigurationElement element = elements[0]; + + boolean failed = false; + try { + Object extObject = element.createExecutableExtension("class"); //$NON-NLS-1$ + if (extObject instanceof ISourceFilesProvider) { + sourceFileProviders.add((ISourceFilesProvider) extObject); + } else { + failed = true; + } + } catch (CoreException e) { + failed = true; + } + + if (failed) { + CDebugCorePlugin + .log("Unable to load SourceFilesProvider extension from " + + extension.getContributor().getName()); + } + } + } + + private void loadSoureRemappingExtensions() { + sourceFileRemappings = Collections + .synchronizedList(new ArrayList()); + + IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry(); + IExtensionPoint extensionPoint = extensionRegistry + .getExtensionPoint(CDebugCorePlugin.PLUGIN_ID + + ".SourceRemappingProvider"); //$NON-NLS-1$ + IExtension[] extensions = extensionPoint.getExtensions(); + + for (int i = 0; i < extensions.length; i++) { + IExtension extension = extensions[i]; + IConfigurationElement[] elements = extension + .getConfigurationElements(); + IConfigurationElement element = elements[0]; + + boolean failed = false; + try { + Object extObject = element.createExecutableExtension("class"); //$NON-NLS-1$ + if (extObject instanceof ISourceFileRemapping) { + sourceFileRemappings.add((ISourceFileRemapping) extObject); + } else { + failed = true; + } + } catch (CoreException e) { + failed = true; + } + + if (failed) { + CDebugCorePlugin + .log("Unable to load SourceRemappingProvider extension from " + + extension.getContributor().getName()); + } + } + } + + private void loadExecutableImporterExtensions() { + executableImporters = Collections + .synchronizedList(new ArrayList()); + + IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry(); + IExtensionPoint extensionPoint = extensionRegistry + .getExtensionPoint(CDebugCorePlugin.PLUGIN_ID + + ".ExecutablesImporter"); //$NON-NLS-1$ + IExtension[] extensions = extensionPoint.getExtensions(); + + for (int i = 0; i < extensions.length; i++) { + IExtension extension = extensions[i]; + IConfigurationElement[] elements = extension + .getConfigurationElements(); + IConfigurationElement element = elements[0]; + + boolean failed = false; + try { + Object extObject = element.createExecutableExtension("class"); //$NON-NLS-1$ + if (extObject instanceof IExecutableImporter) { + executableImporters.add((IExecutableImporter) extObject); + } else { + failed = true; + } + } catch (CoreException e) { + failed = true; + } + + if (failed) { + CDebugCorePlugin + .log("Unable to load ExecutablesImporter extension from " + + extension.getContributor().getName()); + } + } + } + + private void trace(String msg) { + if (DEBUG) { + // TODO use Logger? + System.out.println(msg); + } + } + + private String getStringFromTimestamp(long timestamp) { + return DateFormat.getTimeInstance(DateFormat.MEDIUM).format( + new Date(timestamp)); + } +} diff -r 49c226a8748e -r 42077b7eab6e cdt/cdt_6_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/IExecutableImporter.java --- a/cdt/cdt_6_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/IExecutableImporter.java Wed Aug 05 17:35:39 2009 -0500 +++ b/cdt/cdt_6_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/IExecutableImporter.java Thu Aug 06 12:01:58 2009 -0500 @@ -42,6 +42,6 @@ /** * @since 6.0 */ - public abstract boolean importExecutables(String[] fileNames, IProgressMonitor monitor); + public boolean importExecutables(String[] fileNames, IProgressMonitor monitor); -} \ No newline at end of file +} diff -r 49c226a8748e -r 42077b7eab6e cdt/cdt_6_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/IExecutableProvider.java --- a/cdt/cdt_6_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/IExecutableProvider.java Wed Aug 05 17:35:39 2009 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2008 Nokia 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: - * Nokia - Initial API and implementation - *******************************************************************************/ -package org.eclipse.cdt.debug.core.executables; - -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; - -/** - * IExecutablesProvider supplies a list of executables to the Executables - * Manager. - * - * @author Ken Ryall - * - */ -public interface IExecutableProvider { - - /** - * @since 6.0 - */ - public static final int LOW_PRIORITY = 25; - /** - * @since 6.0 - */ - public static final int NORMAL_PRIORITY = 50; - /** - * @since 6.0 - */ - public static final int HIGH_PRIORITY = 75; - - /** - * Gets the priority to be used when providing a list of executables. - * The priority is used by the Executables Manager when multiple IExecutableProvider are available. - * IExecutableImporter.importExecutables will be called for each one in priority order. - * - * @param executable - * @return the priority level to be used for this ISourceFilesProvider - * @since 6.0 - */ - int getPriority(); - - /** - * @since 6.0 - */ - Executable[] getExecutables(IProgressMonitor monitor); - - /** - * @since 6.0 - */ - IStatus removeExecutable(Executable executable, IProgressMonitor monitor); - -} \ No newline at end of file diff -r 49c226a8748e -r 42077b7eab6e cdt/cdt_6_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/IExecutablesChangeEvent.java --- a/cdt/cdt_6_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/IExecutablesChangeEvent.java Wed Aug 05 17:35:39 2009 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2008 Nokia 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: - * Nokia - Initial API and implementation - *******************************************************************************/ - -package org.eclipse.cdt.debug.core.executables; - - -public interface IExecutablesChangeEvent { - - /** - * @since 6.0 - */ - public Executable[] getCurrentExecutables(); - - /** - * @since 6.0 - */ - public Executable[] getPreviousExecutables(); -} \ No newline at end of file diff -r 49c226a8748e -r 42077b7eab6e cdt/cdt_6_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/IExecutablesChangeListener.java --- a/cdt/cdt_6_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/IExecutablesChangeListener.java Wed Aug 05 17:35:39 2009 -0500 +++ b/cdt/cdt_6_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/IExecutablesChangeListener.java Thu Aug 06 12:01:58 2009 -0500 @@ -12,9 +12,21 @@ package org.eclipse.cdt.debug.core.executables; import java.util.EventListener; +import java.util.List; public interface IExecutablesChangeListener extends EventListener { - public void executablesChanged(IExecutablesChangeEvent event); + /** + * Called whenever the list of executables in the workspace changes, e.g. a + * project was opened/closed/created/deleted + */ + public void executablesListChanged(); -} \ No newline at end of file + /** + * Called whenever some executables have changed, e.g. when a project is rebuilt or + * cleaned. The content may have changed for example, so the list of source files + * may be different. + * @param executables + */ + public void executablesChanged(List executables); +} diff -r 49c226a8748e -r 42077b7eab6e cdt/cdt_6_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/IProjectExecutablesProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cdt/cdt_6_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/IProjectExecutablesProvider.java Thu Aug 06 12:01:58 2009 -0500 @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2009 Nokia 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: + * Nokia - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.debug.core.executables; + +import java.util.List; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; + +/** + * IProjectExecutablesProvider supplies a list of executables for a project + * to the Executables Manager. + * + * @author Warren Paul + * + */ +public interface IProjectExecutablesProvider { + + /** + * Get the list of project natures that should be present in projects that + * this provider will get the list of executables for. Since there could + * be any number of executable providers, the one that matches the given + * project natures the closest will be chosen. + * @return the list of project nature id's + */ + List getProjectNatures(); + + /** + * Get the list of executables for the given project + * @param project the project to get the executables for + * @param monitor progress monitor + * @return the list of executables (which may be empty) + */ + List getExecutables(IProject project, IProgressMonitor monitor); + + /** + * Remove the given executable. Note that the project can be obtained from Executable. + * @param executable the executable to remove + * @param monitor progress monitor + * @return the status of the remove operation + */ + IStatus removeExecutable(Executable executable, IProgressMonitor monitor); + +} diff -r 49c226a8748e -r 42077b7eab6e cdt/cdt_6_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/StandardExecutableProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cdt/cdt_6_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/executables/StandardExecutableProvider.java Thu Aug 06 12:01:58 2009 -0500 @@ -0,0 +1,98 @@ +/******************************************************************************* + * Copyright (c) 2008 Nokia 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: + * Nokia - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.core.executables; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.cdt.core.CCProjectNature; +import org.eclipse.cdt.core.CProjectNature; +import org.eclipse.cdt.core.model.CModelException; +import org.eclipse.cdt.core.model.IBinary; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.debug.core.CDebugCorePlugin; +import org.eclipse.cdt.internal.core.model.CModelManager; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.SubMonitor; +import org.eclipse.debug.core.DebugPlugin; + +public class StandardExecutableProvider implements IProjectExecutablesProvider { + + List supportedNatureIds = new ArrayList(); + + public StandardExecutableProvider() { + supportedNatureIds.add(CProjectNature.C_NATURE_ID); + supportedNatureIds.add(CCProjectNature.CC_NATURE_ID); + } + + public List getProjectNatures() { + return supportedNatureIds; + } + + + public List getExecutables(IProject project, + IProgressMonitor monitor) { + List executables = new ArrayList(); + + ICProject cproject = CModelManager.getDefault().create(project); + try { + IBinary[] binaries = cproject.getBinaryContainer().getBinaries(); + + SubMonitor progress = SubMonitor.convert(monitor, binaries.length); + + for (IBinary binary : binaries) { + if (progress.isCanceled()) { + break; + } + + if (binary.isExecutable() || binary.isSharedLib()) { + IPath exePath = binary.getResource().getLocation(); + if (exePath == null) + exePath = binary.getPath(); + executables.add(new Executable(exePath, project, binary + .getResource())); + } + + progress.worked(1); + + } + } catch (CModelException e) { + } + + return executables; + } + + public IStatus removeExecutable(Executable executable, + IProgressMonitor monitor) { + IResource exeResource = executable.getResource(); + if (exeResource != null) { + try { + exeResource.delete(true, monitor); + } catch (CoreException e) { + DebugPlugin.log(e); + + } + return Status.OK_STATUS; + } + return new Status(IStatus.WARNING, CDebugCorePlugin.PLUGIN_ID, + "Can't remove " + executable.getName() + + ": it is built by project \"" + + executable.getProject().getName() + "\""); + } + +} \ No newline at end of file diff -r 49c226a8748e -r 42077b7eab6e cdt/cdt_6_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/executables/ExecutablesChangeEvent.java --- a/cdt/cdt_6_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/executables/ExecutablesChangeEvent.java Wed Aug 05 17:35:39 2009 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2008 Nokia 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: - * Nokia - Initial API and implementation - *******************************************************************************/ -package org.eclipse.cdt.debug.internal.core.executables; - -import org.eclipse.cdt.debug.core.executables.Executable; -import org.eclipse.cdt.debug.core.executables.IExecutablesChangeEvent; -import org.eclipse.core.runtime.PlatformObject; - -public class ExecutablesChangeEvent extends PlatformObject implements IExecutablesChangeEvent { - - private Executable[] oldExecutables; - private Executable[] newExecutables; - - public ExecutablesChangeEvent(Executable[] oldList, Executable[] newList) { - oldExecutables = oldList; - newExecutables = newList; - } - - public Executable[] getCurrentExecutables() { - return newExecutables; - } - - public Executable[] getPreviousExecutables() { - return oldExecutables; - } - -} diff -r 49c226a8748e -r 42077b7eab6e cdt/cdt_6_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/executables/StandardExecutableProvider.java --- a/cdt/cdt_6_0_x/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/internal/core/executables/StandardExecutableProvider.java Wed Aug 05 17:35:39 2009 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,194 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2008 Nokia 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: - * Nokia - Initial API and implementation - *******************************************************************************/ - -package org.eclipse.cdt.debug.internal.core.executables; - -import java.util.ArrayList; - -import org.eclipse.cdt.core.model.CModelException; -import org.eclipse.cdt.core.model.CoreModel; -import org.eclipse.cdt.core.model.IBinary; -import org.eclipse.cdt.core.model.ICProject; -import org.eclipse.cdt.core.settings.model.CProjectDescriptionEvent; -import org.eclipse.cdt.core.settings.model.ICProjectDescription; -import org.eclipse.cdt.core.settings.model.ICProjectDescriptionListener; -import org.eclipse.cdt.debug.core.CDebugCorePlugin; -import org.eclipse.cdt.debug.core.executables.Executable; -import org.eclipse.cdt.debug.core.executables.ExecutablesManager; -import org.eclipse.cdt.debug.core.executables.IExecutableProvider; -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.IResourceChangeEvent; -import org.eclipse.core.resources.IResourceChangeListener; -import org.eclipse.core.resources.IResourceDelta; -import org.eclipse.core.resources.IResourceDeltaVisitor; -import org.eclipse.core.resources.IWorkspaceRoot; -import org.eclipse.core.resources.ResourcesPlugin; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IPath; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.debug.core.DebugPlugin; - -public class StandardExecutableProvider implements IResourceChangeListener, ICProjectDescriptionListener, IExecutableProvider { - - private ArrayList executables = new ArrayList(); - - public StandardExecutableProvider() { - ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE); - CoreModel.getDefault().getProjectDescriptionManager().addCProjectDescriptionListener(this, - CProjectDescriptionEvent.DATA_APPLIED | CProjectDescriptionEvent.LOADED); - } - - public void resourceChanged(IResourceChangeEvent event) { - - // refresh when projects are opened or closed. note that deleted - // projects are handled later - // in this method. new projects are handled in handleEvent. - // resource changed events always start at the workspace root, so - // projects - // are the next level down - IResourceDelta[] projects = event.getDelta().getAffectedChildren(); - for (IResourceDelta projectDelta : projects) { - if ((projectDelta.getFlags() & IResourceDelta.OPEN) != 0) { - if (projectDelta.getKind() == IResourceDelta.CHANGED) { - // project was opened or closed - ExecutablesManager.getExecutablesManager().scheduleRefresh(this, 0); - return; - } - } - } - - try { - final StandardExecutableProvider provider = this; - event.getDelta().accept(new IResourceDeltaVisitor() { - - public boolean visit(IResourceDelta delta) throws CoreException { - if (delta.getKind() == IResourceDelta.ADDED || delta.getKind() == IResourceDelta.REMOVED) { - IResource deltaResource = delta.getResource(); - if (deltaResource != null) { - boolean refresh = false; - if (delta.getKind() == IResourceDelta.REMOVED && deltaResource instanceof IProject) { - // project deleted - refresh = true; - } else { - // see if a binary has been added/removed - IPath resourcePath = delta.getResource().getLocation(); - if (resourcePath != null && Executable.isExecutableFile(resourcePath)) { - refresh = true; - } - } - if (refresh) { - ExecutablesManager.getExecutablesManager().scheduleRefresh(provider, 0); - return false; - } - } - } - return true; - } - }); - } catch (CoreException e) { - } - } - - public void handleEvent(CProjectDescriptionEvent event) { - // this handles the cases where the active build configuration changes, - // and when new - // projects are created. - boolean refresh = false; - - int eventType = event.getEventType(); - - if (eventType == CProjectDescriptionEvent.DATA_APPLIED) { - // see if the active build config has changed - ICProjectDescription newDesc = event.getNewCProjectDescription(); - ICProjectDescription oldDesc = event.getOldCProjectDescription(); - if (oldDesc != null && newDesc != null) { - String newConfigName = newDesc.getActiveConfiguration().getName(); - String oldConfigName = oldDesc.getActiveConfiguration().getName(); - refresh = (!newConfigName.equals(oldConfigName)); - } else if (newDesc != null && oldDesc == null) { - // project just created - refresh = true; - } - } - - if (refresh) { - ExecutablesManager.getExecutablesManager().scheduleRefresh(this, 0); - } - } - - public Executable[] getExecutables(IProgressMonitor monitor) { - synchronized (executables) { - executables.clear(); - - IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); - IProject[] projects = root.getProjects(); - - monitor.beginTask("Checking C/C++ Projects", projects.length); - - for (IProject project : projects) { - - if (monitor.isCanceled()) - break; - - try { - if (CoreModel.hasCNature(project)) { - CModelManager manager = CModelManager.getDefault(); - ICProject cproject = manager.create(project); - try { - IBinary[] binaries = cproject.getBinaryContainer().getBinaries(); - for (IBinary binary : binaries) { - if (binary.isExecutable() || binary.isSharedLib()) { - IPath exePath = binary.getResource().getLocation(); - if (exePath == null) - exePath = binary.getPath(); - Executable exe = new Executable(exePath, project, binary.getResource()); - executables.add(exe); - } - } - } catch (CModelException e) { - } - } - } catch (Exception e) { - DebugPlugin.log( e ); - } - monitor.worked(1); - } - monitor.done(); - } - return executables.toArray(new Executable[executables.size()]); - } - - public int getPriority() { - return NORMAL_PRIORITY; - } - - public IStatus removeExecutable(Executable executable, IProgressMonitor monitor) { - IResource exeResource = executable.getResource(); - if (exeResource != null) - { - if (exeResource.isLinked()) - { - try { - exeResource.delete(true, monitor); - } catch (CoreException e) { - DebugPlugin.log( e ); - } - } - return Status.OK_STATUS; - } - return new Status(IStatus.WARNING, CDebugCorePlugin.PLUGIN_ID, "Can't remove " + executable.getName() + ": it is built by project \"" + executable.getProject().getName() + "\""); - } - -} \ No newline at end of file diff -r 49c226a8748e -r 42077b7eab6e cdt/cdt_6_0_x/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/ExecutablesContentProvider.java --- a/cdt/cdt_6_0_x/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/ExecutablesContentProvider.java Wed Aug 05 17:35:39 2009 -0500 +++ b/cdt/cdt_6_0_x/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/ExecutablesContentProvider.java Thu Aug 06 12:01:58 2009 -0500 @@ -17,9 +17,6 @@ import org.eclipse.cdt.debug.core.executables.Executable; import org.eclipse.cdt.debug.core.executables.ExecutablesManager; import org.eclipse.core.runtime.IPath; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.viewers.ColumnLabelProvider; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.ITreeContentProvider; @@ -29,10 +26,7 @@ class ExecutablesContentProvider extends ColumnLabelProvider implements IStructuredContentProvider, ITreeContentProvider { - private TreeViewer viewer; - public ExecutablesContentProvider(TreeViewer viewer) { - this.viewer = viewer; } public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { @@ -43,42 +37,8 @@ public Object[] getElements(final Object inputElement) { if (inputElement instanceof ExecutablesManager) { - final ExecutablesManager em = (ExecutablesManager) inputElement; - if (em.refreshNeeded()) { - // do this asynchronously. just return an empty array - // immediately, and then refresh the view - // once the list of executables has been calculated. this can - // take a while and we don't want - // to block the UI. - Job refreshJob = new Job(Messages.ExecutablesContentProvider_FetchingExecutables) { - - @Override - protected IStatus run(IProgressMonitor monitor) { - IStatus status = em.refreshExecutables(monitor); - - // Are we in the UIThread? If so spin it until we are done - if (!viewer.getControl().isDisposed()) { - if (viewer.getControl().getDisplay().getThread() == Thread.currentThread()) { - viewer.refresh(inputElement); - } else { - viewer.getControl().getDisplay().asyncExec(new Runnable() { - public void run() { - viewer.refresh(inputElement); - } - }); - } - } - - monitor.done(); - return status; - } - }; - - refreshJob.schedule(); - - } else { - return em.getExecutables(); - } + ExecutablesManager em = (ExecutablesManager) inputElement; + return em.getExecutables().toArray(); } return new Object[] {}; } diff -r 49c226a8748e -r 42077b7eab6e cdt/cdt_6_0_x/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/ExecutablesView.java --- a/cdt/cdt_6_0_x/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/ExecutablesView.java Wed Aug 05 17:35:39 2009 -0500 +++ b/cdt/cdt_6_0_x/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/ExecutablesView.java Thu Aug 06 12:01:58 2009 -0500 @@ -268,36 +268,48 @@ // update the source files viewer executablesViewer.addSelectionChangedListener(new ISelectionChangedListener() { - public void selectionChanged(SelectionChangedEvent event) { - ISelection newSelection = event.getSelection(); - if (newSelection instanceof IStructuredSelection) { - final Object firstElement = ((IStructuredSelection) newSelection).getFirstElement(); - - Job setectExeJob = new Job(Messages.ExecutablesView_Select_Executable) { + public void selectionChanged(SelectionChangedEvent event) { + ISelection newSelection = event.getSelection(); + if (newSelection instanceof IStructuredSelection) { + + // update the remove action + removeAction.setEnabled(!newSelection.isEmpty()); + + final Object firstElement = ((IStructuredSelection) newSelection) + .getFirstElement(); + + Job setectExeJob = new Job( + Messages.ExecutablesView_Select_Executable) { - @Override - protected IStatus run(IProgressMonitor monitor) { - if (firstElement instanceof Executable) { - Executable executable = (Executable)firstElement; - this.setName(Messages.ExecutablesView_Finding_Sources_Job_Name + executable.getName()); - executable.getSourceFiles(monitor); - } - UIJob selectExeUIJob = new UIJob(Messages.ExecutablesView_Select_Executable){ @Override - public IStatus runInUIThread(IProgressMonitor monitor) { - sourceFilesViewer.setInput(firstElement); + protected IStatus run(IProgressMonitor monitor) { if (firstElement instanceof Executable) { - sourceFilesViewer.packColumns(); + Executable executable = (Executable) firstElement; + this + .setName(Messages.ExecutablesView_Finding_Sources_Job_Name + + executable.getName()); + executable.getSourceFiles(monitor); + UIJob selectExeUIJob = new UIJob( + Messages.ExecutablesView_Select_Executable) { + @Override + public IStatus runInUIThread( + IProgressMonitor monitor) { + sourceFilesViewer + .setInput(firstElement); + sourceFilesViewer.packColumns(); + return Status.OK_STATUS; + } + }; + selectExeUIJob.schedule(); } + return Status.OK_STATUS; - }}; - selectExeUIJob.schedule(); - return Status.OK_STATUS; - }}; - setectExeJob.schedule(); - } - } - }); + } + }; + setectExeJob.schedule(); + } + } + }); executablesViewer.packColumns(); sourceFilesViewer.packColumns(); @@ -360,6 +372,7 @@ private Action createRemoveAction() { Action action = new Action("Remove") { + public void run() { ISelection selection = getExecutablesViewer().getSelection(); if (selection instanceof IStructuredSelection) @@ -404,7 +417,7 @@ action.setToolTipText("Remove the selected executables"); action.setImageDescriptor(ExecutablesView.DESC_REMOVE); action.setDisabledImageDescriptor(ExecutablesView.DESC_REMOVE_DISABLED); - action.setEnabled(true); + action.setEnabled(false); return action; } @@ -460,7 +473,7 @@ private Action createRefreshAction() { Action action = new Action(Messages.ExecutablesView_Refresh) { public void run() { - ExecutablesManager.getExecutablesManager().scheduleRefresh(null, 0); + ExecutablesManager.getExecutablesManager().refresh(null); } }; action.setToolTipText(Messages.ExecutablesView_RefreshList); diff -r 49c226a8748e -r 42077b7eab6e cdt/cdt_6_0_x/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/ExecutablesViewer.java --- a/cdt/cdt_6_0_x/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/ExecutablesViewer.java Wed Aug 05 17:35:39 2009 -0500 +++ b/cdt/cdt_6_0_x/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/ExecutablesViewer.java Thu Aug 06 12:01:58 2009 -0500 @@ -10,9 +10,9 @@ *******************************************************************************/ package org.eclipse.cdt.debug.internal.ui.views.executables; +import java.util.List; import org.eclipse.cdt.debug.core.executables.Executable; import org.eclipse.cdt.debug.core.executables.ExecutablesManager; -import org.eclipse.cdt.debug.core.executables.IExecutablesChangeEvent; import org.eclipse.cdt.debug.core.executables.IExecutablesChangeListener; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; @@ -166,39 +166,7 @@ return new ExecutablesViewerComparator(sortType, column_sort_order[sortType]); } - /* - * (non-Javadoc) - * - * @see org.eclipse.cdt.debug.core.executables.IExecutablesChangeListener#executablesChanged(org.eclipse.cdt.debug.core.executables.IExecutablesChangeEvent) - */ - public void executablesChanged(IExecutablesChangeEvent event) { - // Executables have changed so refresh the view. - final ExecutablesViewer viewer = this; - UIJob refreshJob = new UIJob(Messages.ExecutablesViewer_RefreshExecutablesView) { - - @Override - public IStatus runInUIThread(IProgressMonitor monitor) { - // if the user has selected an executable, they expect its - // list of source files to be refreshed automatically - if (viewer.getSelection() != null && - viewer.getSelection() instanceof IStructuredSelection) { - IStructuredSelection selection = (IStructuredSelection) viewer.getSelection(); - - Object firstElement = selection.getFirstElement(); - if (firstElement instanceof Executable) { - Executable executable = (Executable)firstElement; - executable.setRefreshSourceFiles(true); - viewer.setSelection(selection); - } - } - viewer.refresh(null); - viewer.packColumns(); - return Status.OK_STATUS; - } - }; - refreshJob.schedule(); - } - + @Override protected String getColumnOrderKey() { return P_COLUMN_ORDER_KEY_EXE; @@ -224,4 +192,48 @@ // default visible columns return "1,1,1,0,0,0"; //$NON-NLS-1$ } + + public void executablesChanged(final List executables) { + // some executables have been updated. if one of them is currently + // selected, we need to update the source file list + UIJob refreshJob = new UIJob( + Messages.ExecutablesViewer_RefreshExecutablesView) { + + @Override + public IStatus runInUIThread(IProgressMonitor monitor) { + // if the user has selected an executable, they expect its + // list of source files to be refreshed automatically + if (getSelection() != null + && getSelection() instanceof IStructuredSelection) { + IStructuredSelection selection = (IStructuredSelection) getSelection(); + + Object firstElement = selection.getFirstElement(); + if (firstElement instanceof Executable) { + Executable executable = (Executable) firstElement; + if (executables.contains(executable)) { + executable.setRefreshSourceFiles(true); + setSelection(selection); + } + } + } + return Status.OK_STATUS; + } + }; + refreshJob.schedule(); + } + + public void executablesListChanged() { + // Executables list has changed so refresh the view. + UIJob refreshJob = new UIJob( + Messages.ExecutablesViewer_RefreshExecutablesView) { + + @Override + public IStatus runInUIThread(IProgressMonitor monitor) { + refresh(null); + packColumns(); + return Status.OK_STATUS; + } + }; + refreshJob.schedule(); + } } \ No newline at end of file diff -r 49c226a8748e -r 42077b7eab6e cdt/cdt_6_0_x/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/SourceFilesLabelProvider.java --- a/cdt/cdt_6_0_x/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/SourceFilesLabelProvider.java Wed Aug 05 17:35:39 2009 -0500 +++ b/cdt/cdt_6_0_x/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/views/executables/SourceFilesLabelProvider.java Thu Aug 06 12:01:58 2009 -0500 @@ -70,7 +70,7 @@ if (cell.getElement() instanceof ITranslationUnit) { Executable executable = (Executable) viewer.getInput(); Path path = new Path(executable.getOriginalLocation((ITranslationUnit) cell.getElement())); - cell.setText(executable.getOriginalLocation((ITranslationUnit) cell.getElement())); + cell.setText(path.toOSString()); if (path.toFile().exists()) cell.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_BLACK)); else diff -r 49c226a8748e -r 42077b7eab6e cdt/cdt_6_0_x/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/BaseCElementContentProvider.java --- a/cdt/cdt_6_0_x/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/BaseCElementContentProvider.java Wed Aug 05 17:35:39 2009 -0500 +++ b/cdt/cdt_6_0_x/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/BaseCElementContentProvider.java Thu Aug 06 12:01:58 2009 -0500 @@ -12,6 +12,7 @@ package org.eclipse.cdt.internal.ui; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -26,6 +27,7 @@ import org.eclipse.jface.viewers.Viewer; import org.eclipse.ui.model.IWorkbenchAdapter; +import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.model.CModelException; import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.IArchive; @@ -396,8 +398,12 @@ ICElement[] c2 = ((ISourceRoot)child).getChildren(); for (int k = 0; k < c2.length; ++k) list.add(c2[k]); - } else + } else if (CCorePlugin.showSourceRootsAtTopOfProject()) { list.add(child); + } else if (child instanceof ISourceRoot && + child.getResource().getParent().equals(cproject.getProject())) { + list.add(child); + } } Object[] objects = list.toArray(); @@ -513,7 +519,11 @@ protected Object[] getCResources(ICContainer container) throws CModelException { Object[] objects = null; - Object[] children = container.getChildren(); + ICElement[] children = container.getChildren(); + List missingElements = Collections.emptyList(); + if (!CCorePlugin.showSourceRootsAtTopOfProject()) { + missingElements = getMissingElements(container, children); + } try { objects = container.getNonCResources(); if (objects.length > 0) { @@ -524,7 +534,38 @@ if (objects == null || objects.length == 0) { return children; } - return concatenate(children, objects); + Object[] result = concatenate(children, objects); + return concatenate(result, missingElements.toArray()); + } + + private List getMissingElements(ICContainer container, ICElement[] elements) { + // nested source roots may be filtered out below the project root, + // we need to find them to add them back in + List missingElements = new ArrayList(); + try { + List missingContainers = new ArrayList(); + IResource[] allChildren = ((IContainer) container.getResource()).members(); + for (IResource child : allChildren) { + if (!(child instanceof IContainer)) + continue; + boolean found = false; + for (ICElement element : elements) { + if (element.getResource().equals(child)) { + found = true; + break; + } + } + if (!found) + missingContainers.add(child); + } + for (IResource resource : missingContainers) { + ICElement element = container.getCProject().findElement(resource.getFullPath()); + if (element != null) + missingElements.add(element); + } + } catch (CoreException e1) { + } + return missingElements; } protected Object[] getResources(IProject project) { @@ -576,16 +617,19 @@ // folder we have to exclude it as a normal child. if (o instanceof IFolder) { IFolder folder = (IFolder)o; - boolean found = false; + ISourceRoot root = null; for (int j = 0; j < roots.length; j++) { if (roots[j].getPath().equals(folder.getFullPath())) { - found = true; + root = roots[j]; break; } } // it is a sourceRoot skip it. - if (found) { - continue; + if (root != null) { + if (CCorePlugin.showSourceRootsAtTopOfProject()) + continue; + else + o = root; } } else if (o instanceof IFile){ boolean found = false; diff -r 49c226a8748e -r 42077b7eab6e cdt/cdt_6_0_x/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPluginImages.java --- a/cdt/cdt_6_0_x/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPluginImages.java Wed Aug 05 17:35:39 2009 -0500 +++ b/cdt/cdt_6_0_x/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPluginImages.java Thu Aug 06 12:01:58 2009 -0500 @@ -98,6 +98,7 @@ public static final String IMG_OBJS_TUNIT_RESOURCE_H= NAME_PREFIX + "ch_resource_obj.gif"; //$NON-NLS-1$ public static final String IMG_OBJS_TUNIT_RESOURCE_A= NAME_PREFIX + "asm_resource_obj.gif"; //$NON-NLS-1$ public static final String IMG_OBJS_SOURCE_ROOT= NAME_PREFIX + "sroot_obj.gif"; // $NON-NLS-1$ //$NON-NLS-1$ + public static final String IMG_OBJS_SOURCE2_ROOT= NAME_PREFIX + "sroot2_obj.gif"; // $NON-NLS-1$ //$NON-NLS-1$ public static final String IMG_OBJS_CFOLDER= NAME_PREFIX + "cfolder_obj.gif"; // $NON-NLS-1$ //$NON-NLS-1$ public static final String IMG_OBJS_CONFIG = NAME_PREFIX + "config.gif"; // $NON-NLS-1$ //$NON-NLS-1$ public static final String IMG_OBJS_ARCHIVE= NAME_PREFIX + "ar_obj.gif"; //$NON-NLS-1$ @@ -180,6 +181,7 @@ public static final ImageDescriptor DESC_OBJS_TUNIT_RESOURCE_H= createManaged(T_OBJ, IMG_OBJS_TUNIT_RESOURCE_H); public static final ImageDescriptor DESC_OBJS_TUNIT_RESOURCE_A= createManaged(T_OBJ, IMG_OBJS_TUNIT_RESOURCE_A); public static final ImageDescriptor DESC_OBJS_SOURCE_ROOT= createManaged(T_OBJ, IMG_OBJS_SOURCE_ROOT); + public static final ImageDescriptor DESC_OBJS_SOURCE2_ROOT= createManaged(T_OBJ, IMG_OBJS_SOURCE2_ROOT); public static final ImageDescriptor DESC_OBJS_CFOLDER= createManaged(T_OBJ, IMG_OBJS_CFOLDER); public static final ImageDescriptor DESC_OBJS_CONFIG = createManaged(T_OBJ, IMG_OBJS_CONFIG); public static final ImageDescriptor DESC_OBJS_ARCHIVE= createManaged(T_OBJ, IMG_OBJS_ARCHIVE); diff -r 49c226a8748e -r 42077b7eab6e cdt/cdt_6_0_x/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/AppearancePreferencePage.java --- a/cdt/cdt_6_0_x/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/AppearancePreferencePage.java Wed Aug 05 17:35:39 2009 -0500 +++ b/cdt/cdt_6_0_x/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/AppearancePreferencePage.java Thu Aug 06 12:01:58 2009 -0500 @@ -12,6 +12,7 @@ package org.eclipse.cdt.internal.ui.preferences; import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Preferences; import org.eclipse.core.runtime.preferences.InstanceScope; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.IDialogConstants; @@ -28,6 +29,8 @@ import org.eclipse.ui.PlatformUI; import org.osgi.service.prefs.BackingStoreException; +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.CCorePreferenceConstants; import org.eclipse.cdt.ui.CUIPlugin; import org.eclipse.cdt.ui.PreferenceConstants; @@ -47,6 +50,7 @@ private SelectionButtonDialogField fCViewGroupIncludes; private SelectionButtonDialogField fCViewSeparateHeaderAndSource; private SelectionButtonDialogField fOutlineGroupMembers; + private SelectionButtonDialogField fShowSourceRootsAtTopOfProject; public AppearancePreferencePage() { setPreferenceStore(PreferenceConstants.getPreferenceStore()); @@ -81,6 +85,12 @@ fCViewSeparateHeaderAndSource= new SelectionButtonDialogField(SWT.CHECK); fCViewSeparateHeaderAndSource.setDialogFieldListener(listener); fCViewSeparateHeaderAndSource.setLabelText(PreferencesMessages.AppearancePreferencePage_cviewSeparateHeaderAndSource_label); + + fShowSourceRootsAtTopOfProject= new SelectionButtonDialogField(SWT.CHECK); + fShowSourceRootsAtTopOfProject.setDialogFieldListener(listener); + fShowSourceRootsAtTopOfProject.setLabelText(PreferencesMessages.AppearancePreferencePage_showSourceRootsAtTopOfProject_label); + + } private void initFields() { @@ -91,6 +101,8 @@ fOutlineGroupIncludes.setSelection(prefs.getBoolean(PreferenceConstants.OUTLINE_GROUP_INCLUDES)); fOutlineGroupNamespaces.setSelection(prefs.getBoolean(PreferenceConstants.OUTLINE_GROUP_NAMESPACES)); fOutlineGroupMembers.setSelection(prefs.getBoolean(PreferenceConstants.OUTLINE_GROUP_MEMBERS)); + boolean showSourceRootsAtTopOfProject = CCorePlugin.showSourceRootsAtTopOfProject(); + fShowSourceRootsAtTopOfProject.setSelection(showSourceRootsAtTopOfProject); } /* @@ -134,6 +146,10 @@ gd.horizontalSpan= 2; noteControl.setLayoutData(gd); + + new Separator().doFillIntoGrid(result, nColumns); + fShowSourceRootsAtTopOfProject.doFillIntoGrid(result, nColumns); + initFields(); Dialog.applyDialogFont(result); @@ -176,6 +192,8 @@ } catch (BackingStoreException exc) { CUIPlugin.log(exc); } + CCorePlugin.getDefault().getPluginPreferences().setValue(CCorePreferenceConstants.SHOW_SOURCE_ROOTS_AT_TOP_LEVEL_OF_PROJECT, fShowSourceRootsAtTopOfProject.isSelected()); + CCorePlugin.getDefault().savePluginPreferences(); return super.performOk(); } @@ -191,6 +209,8 @@ fOutlineGroupIncludes.setSelection(prefs.getDefaultBoolean(PreferenceConstants.OUTLINE_GROUP_INCLUDES)); fOutlineGroupNamespaces.setSelection(prefs.getDefaultBoolean(PreferenceConstants.OUTLINE_GROUP_NAMESPACES)); fOutlineGroupMembers.setSelection(prefs.getDefaultBoolean(PreferenceConstants.OUTLINE_GROUP_MEMBERS)); + Preferences corePrefs = CCorePlugin.getDefault().getPluginPreferences(); + fShowSourceRootsAtTopOfProject.setSelection(corePrefs.getDefaultBoolean(CCorePreferenceConstants.SHOW_SOURCE_ROOTS_AT_TOP_LEVEL_OF_PROJECT)); super.performDefaults(); } } diff -r 49c226a8748e -r 42077b7eab6e cdt/cdt_6_0_x/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.java --- a/cdt/cdt_6_0_x/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.java Wed Aug 05 17:35:39 2009 -0500 +++ b/cdt/cdt_6_0_x/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.java Thu Aug 06 12:01:58 2009 -0500 @@ -138,6 +138,7 @@ public static String AppearancePreferencePage_outlineGroupNamespaces_label; public static String AppearancePreferencePage_note; public static String AppearancePreferencePage_preferenceOnlyForNewViews; + public static String AppearancePreferencePage_showSourceRootsAtTopOfProject_label; public static String CEditorPreferencePage_folding_title; public static String FoldingConfigurationBlock_enable; public static String FoldingConfigurationBlock_combo_caption; diff -r 49c226a8748e -r 42077b7eab6e cdt/cdt_6_0_x/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties --- a/cdt/cdt_6_0_x/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties Wed Aug 05 17:35:39 2009 -0500 +++ b/cdt/cdt_6_0_x/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties Thu Aug 06 12:01:58 2009 -0500 @@ -157,6 +157,7 @@ AppearancePreferencePage_outlineGroupNamespaces_label= Group namespaces in the Outline view AppearancePreferencePage_note=Note: AppearancePreferencePage_preferenceOnlyForNewViews=This preference does not affect open views +AppearancePreferencePage_showSourceRootsAtTopOfProject_label=Show source roots at top of project #Folding CEditorPreferencePage_folding_title= &Folding diff -r 49c226a8748e -r 42077b7eab6e cdt/cdt_6_0_x/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/CElementImageProvider.java --- a/cdt/cdt_6_0_x/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/CElementImageProvider.java Wed Aug 05 17:35:39 2009 -0500 +++ b/cdt/cdt_6_0_x/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/CElementImageProvider.java Thu Aug 06 12:01:58 2009 -0500 @@ -14,8 +14,10 @@ package org.eclipse.cdt.internal.ui.viewsupport; import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IPath; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; @@ -23,12 +25,14 @@ import org.eclipse.ui.ide.IDE; import org.eclipse.ui.model.IWorkbenchAdapter; +import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.model.CModelException; import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.IArchiveContainer; import org.eclipse.cdt.core.model.IBinary; import org.eclipse.cdt.core.model.IBinaryContainer; import org.eclipse.cdt.core.model.IBinaryModule; +import org.eclipse.cdt.core.model.ICContainer; import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.ICProject; import org.eclipse.cdt.core.model.IContributedCElement; @@ -46,6 +50,8 @@ import org.eclipse.cdt.ui.CElementImageDescriptor; import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.cdt.internal.core.model.CModelManager; + import org.eclipse.cdt.internal.ui.CPluginImages; @@ -120,7 +126,11 @@ public Image getImageLabel(Object element, int flags) { ImageDescriptor descriptor= null; if (element instanceof ICElement) { - descriptor= getCImageDescriptor((ICElement) element, flags); + if (!CCorePlugin.showSourceRootsAtTopOfProject() && + element instanceof ICContainer && isParentOfSourceRoot(element)) + descriptor = CPluginImages.DESC_OBJS_SOURCE2_ROOT; + else + descriptor= getCImageDescriptor((ICElement) element, flags); } else if (element instanceof IFile) { // Check for Non Translation Unit. IFile file = (IFile)element; @@ -138,6 +148,9 @@ Point size= useSmallSize(flags) ? SMALL_SIZE : BIG_SIZE; descriptor = new CElementImageDescriptor(descriptor, 0, size); } + } else if (!CCorePlugin.showSourceRootsAtTopOfProject() && + element instanceof IFolder && isParentOfSourceRoot(element)) { + descriptor = CPluginImages.DESC_OBJS_SOURCE2_ROOT; } if (descriptor == null && element instanceof IAdaptable) { descriptor= getWorkbenchImageDescriptor((IAdaptable) element, flags); @@ -148,6 +161,34 @@ return null; } + private boolean isParentOfSourceRoot(Object element) { + // we want to return true for parents of source roots which are not themselves source roots + // so we can distinguish the two and return the source root icon or the parent of source root icon + IFolder folder = null; + if (element instanceof ICContainer && !(element instanceof ISourceRoot)) + folder = (IFolder) ((ICContainer) element).getResource(); + else if (element instanceof IFolder) + folder = (IFolder) element; + if (folder == null) + return false; + + ICProject cproject = CModelManager.getDefault().getCModel().findCProject(folder.getProject()); + if (cproject != null) { + try { + IPath folderPath = folder.getFullPath(); + for (ICElement sourceRoot : cproject.getSourceRoots()) { + IPath sourceRootPath = sourceRoot.getPath(); + if (folderPath.isPrefixOf(sourceRootPath)) { + return true; + } + } + } catch (CModelException e) { + } + } + + return false; + } + public static ImageDescriptor getImageDescriptor(int type) { switch (type) { case ICElement.C_VCONTAINER: