private bool RecurseInto(SelectionItem si, ProjectWalkDepth depth) { ThreadHelper.ThrowIfNotOnUIThread(); object value; if (VSErr.Succeeded(si.Hierarchy.GetProperty(si.Id, (int)__VSHPROPID.VSHPROPID_HasEnumerationSideEffects, out value))) { if (value != null) { bool hasSideEffects = (bool)value; // Unless we are walking SCC projects, don't go deeper // because we don't want side effects! if (hasSideEffects) { if (depth == ProjectWalkDepth.AllDescendantsInHierarchy && IgnoreSideEffects(si.SccProject)) { return(true); } return(false); } } } if (si.SccProject == null && VSErr.Succeeded(si.Hierarchy.GetProperty(si.Id, (int)__VSHPROPID2.VSHPROPID_ChildrenEnumerated, out value))) { if (value != null) { bool childrenEnumerated = (bool)value; if (!childrenEnumerated) { return(false); } } } return(true); }
/// <summary> /// Gets the list of files specified by the hierarchy (IVsSccProject2 or IVsHierarchy) /// </summary> /// <param name="hierarchy"></param> /// <param name="id"></param> /// <param name="depth"></param> /// <returns></returns> /// <remarks>The list might contain duplicates if files are included more than once</remarks> public IEnumerable <string> GetSccFiles(IVsHierarchy hierarchy, uint id, ProjectWalkDepth depth, IDictionary <string, uint> map) { ThreadHelper.ThrowIfNotOnUIThread(); // Note: This command is not cached like the other commands on this object! if (hierarchy == null) { throw new ArgumentNullException("hierarchy"); } SelectionItem si = new SelectionItem(hierarchy, id); string[] files; if (!SelectionUtils.GetSccFiles(si, out files, depth >= ProjectWalkDepth.SpecialFiles, IncludeNoScc(depth), map)) { yield break; } foreach (string file in files) { yield return(SvnTools.GetNormalizedFullPath(file)); } if (depth > ProjectWalkDepth.SpecialFiles) { Dictionary <SelectionItem, SelectionItem> previous = new Dictionary <SelectionItem, SelectionItem>(); previous.Add(si, si); foreach (SelectionItem item in GetDescendants(si, previous, depth)) { if (!SelectionUtils.GetSccFiles(item, out files, depth >= ProjectWalkDepth.SpecialFiles, depth != ProjectWalkDepth.AllDescendantsInHierarchy, map)) { continue; } foreach (string file in files) { yield return(SvnTools.GetNormalizedFullPath(file)); } } } }
/// <summary> /// Gets the descendants of a selection item; yielding for each result to allow delay loading /// </summary> /// <param name="si"></param> /// <param name="previous"></param> /// <returns></returns> private IEnumerable <SelectionItem> GetDescendants(SelectionItem si, Dictionary <SelectionItem, SelectionItem> previous, ProjectWalkDepth depth) { if (si == null) { throw new ArgumentNullException("si"); } // A hierarchy node can have 2 identities. We only need the inner one uint subId; IntPtr hierPtr; int hr; try { hr = si.Hierarchy.GetNestedHierarchy(si.Id, ref hierarchyId, out hierPtr, out subId); } catch (Exception e) { ExternalException ee = e as ExternalException; if (ee != null && !VSErr.Succeeded(ee.ErrorCode)) { hr = ee.ErrorCode; // Should have been returned instead } else if (e is NotImplementedException) { hr = VSErr.E_NOTIMPL; // From Microsoft.VisualStudio.PerformanceTools.DummyVsUIHierarchy.GetNestedHierarchy() } else { hr = VSErr.E_FAIL; } hierPtr = IntPtr.Zero; subId = VSItemId.Nil; } if (VSErr.Succeeded(hr) && hierPtr != IntPtr.Zero) { IVsHierarchy nestedHierarchy = Marshal.GetObjectForIUnknown(hierPtr) as IVsHierarchy; Marshal.Release(hierPtr); if (nestedHierarchy == null || (nestedHierarchy == MiscellaneousProject)) { yield break; } if (depth <= ProjectWalkDepth.AllDescendantsInHierarchy) { yield break; // Don't walk into sub-hierarchies } else { si = new SelectionItem(nestedHierarchy, subId); } } if (!previous.ContainsKey(si)) { previous.Add(si, si); yield return(si); } // Note: VS2005 and earlier have all projects on the top level; from VS2008+ projects are nested // We can ignore that as we would include the projects anyway if (!RecurseInto(si, depth)) { yield break; } object value; if (!VSErr.Succeeded(si.Hierarchy.GetProperty(si.Id, (int)__VSHPROPID.VSHPROPID_FirstChild, out value))) { yield break; } uint childId = GetItemIdFromObject(value); while (childId != VSItemId.Nil) { SelectionItem i = new SelectionItem(si.Hierarchy, childId); foreach (SelectionItem ii in GetDescendants(i, previous, depth)) { yield return(ii); } if (!VSErr.Succeeded(si.Hierarchy.GetProperty(i.Id, (int)__VSHPROPID.VSHPROPID_NextSibling, out value))) { yield break; } childId = GetItemIdFromObject(value); } }
bool IncludeNoScc(ProjectWalkDepth depth) { return((depth != ProjectWalkDepth.AllDescendantsInHierarchy) && (depth != ProjectWalkDepth.SpecialFiles)); }