private static IEnumerable <VsItem> FindSolutionsAndProjects(string rootPath)
        {
            var dirsToCheck = new Queue <string>();

            dirsToCheck.Enqueue(rootPath);

            while (dirsToCheck.Any())
            {
                var dir = dirsToCheck.Dequeue();

                foreach (var filename in Directory.EnumerateFiles(dir))
                {
                    if (IsSolution(filename))
                    {
                        var item = new VsItem(Path.GetFileName(filename), filename, VsItemType.Solution);
                        item.Dependencies.AddRange(FindSolutionDependencies(item.Path));
                        yield return(item);
                    }
                    else if (IsProject(filename))
                    {
                        var item = new VsItem(Path.GetFileName(filename), filename, VsItemType.Project);
                        item.Dependencies.AddRange(FindProjectDependencies(item.Path));
                        yield return(item);
                    }
                    // Don't add a call to IsDll() here.  Doing so will include a LOT of irrelevant DLLs.  DLLs that are
                    // actually called out are added in PopulateDependencyOf().
                }

                foreach (var subDir in Directory.GetDirectories(dir))
                {
                    dirsToCheck.Enqueue(subDir);
                }
            }
        }
        private static IEnumerable <VsItem> PopulateDependencyOf(List <VsItem> items)
        {
            var nonExistantItems = new List <VsItem>();
            var mapping          = items.ToDictionary(i => CanonicalPath(i.Path), i => i);

            foreach (var item in items)
            {
                foreach (var dep in item.Dependencies)
                {
                    var depCanPath = CanonicalPath(dep.Path);
                    if (!mapping.ContainsKey(depCanPath))
                    {
                        var type    = IsDll(dep.Path) ? VsItemType.Dll : VsItemType.Project;
                        var newItem = new VsItem(Path.GetFileName(dep.Path), dep.Path, type, dep.Exists);
                        mapping[depCanPath] = newItem;

                        if (!dep.Exists || IsDll(dep.Path))
                        {
                            nonExistantItems.Add(newItem);
                        }
                    }
                    mapping[depCanPath].DependencyOf.Add(new FilePath(item.Path));
                }
            }
            return(nonExistantItems);
        }
        private static string GetClassName(VsItem item)
        {
            var directDllPaths = new[] { @"\bin\Debug\", @"\bin\Release\" };

            if (item.Type == VsItemType.Dll && directDllPaths.Any(item.Path.Contains))
            {
                return("direct-dll");
            }

            if (!item.Exists)
            {
                return("nonexistant");
            }

            if (item.Type != VsItemType.Solution && item.IsOrphan)
            {
                return("orphan");
            }

            var hasNonexistantDeps = item.Dependencies.Any(d => !d.Exists);

            if (hasNonexistantDeps)
            {
                return("nonexistant-deps");
            }

            return(String.Empty);
        }