/// <summary> /// Returns solution projects. /// </summary> /// <param name="flags">Processor flags.</param> /// <param name="filter">Code model filter.</param> /// <returns>Projects.</returns> public SolutionModel GetProjects(ProcessorFlags flags, CodeModelFilterFlags filter = CodeModelFilterFlags.All) { ThreadHelper.ThrowIfNotOnUIThread(); var model = new SolutionModel(); GetProjectsInternal(model, flags, filter); return(model); }
/// <summary> /// Returns solution projects. /// </summary> private void GetProjectsInternal(SolutionModel model, ProcessorFlags flags, CodeModelFilterFlags filter) { ThreadHelper.ThrowIfNotOnUIThread(); var dte = _shellProjectService.GetDTE() as DTE; _log.LogMessage("Collecting solution projects"); var projects = dte.Solution.Projects; for (int index = 1; index <= projects.Count; index++) { Project project = projects.Item(index); if (_shellProjectService.IsProjectLoadDeferred(project, out bool loaded)) { continue; } // Reacquire project reference if it's been reloaded if (loaded) { project = projects.Item(index); } if (ProcessProject(project, model.Projects, flags, filter)) { ProcessProjectRecursively(project, model.Projects, flags, filter); } } model.Files = model.Projects.SelectMany(p => p.Files).ToList(); if (flags.HasFlag(ProcessorFlags.GroupLinkedFiles)) { // Get all grouped, ie duplicate, files, keep the first code file and remove the rest var groupedFiles = model.Files.GroupBy(f => f.FileNameWithPath).Where(g => g.Count() > 1).Select(g => g); foreach (var group in groupedFiles) { var file = group.FirstOrDefault(f => f.Project.Language.SupportsCompileBuildAction && _shellProjectService.CompileBuildAction(f.ProjectItem)); if (file != null) { group.ForEach(f => { if (f != file) { model.Files.Remove(f); f.Project.Files.Remove(f); AddProjectName(file, f.ProjectName); } }); } } } _log.LogMessage($"Collected {model.Projects.Count} solution projects"); }
/// <summary> /// Returns solution projects. /// </summary> private void GetProjectsInternal(SolutionModel model, ProcessorFlags flags, CodeModelFilterFlags filter) { ThreadHelper.ThrowIfNotOnUIThread(); _log.LogMessage("Collecting solution projects", LOG_CATEGORY); var dte = _shellProjectService.GetDTE() as DTE; var serviceProvider = new Microsoft.VisualStudio.Shell.ServiceProvider(dte as Microsoft.VisualStudio.OLE.Interop.IServiceProvider); var solutionService = serviceProvider.GetService <IVsSolution, SVsSolution>(false); Guid guid = Guid.Empty; if (solutionService.GetProjectEnum((uint)__VSENUMPROJFLAGS.EPF_LOADEDINSOLUTION, ref guid, out IEnumHierarchies enumHierarchies) != VSConstants.S_OK) { return; } IVsHierarchy[] hierarchy = new IVsHierarchy[1]; List <Project> projects = new List <Project>(); while ((enumHierarchies.Next((uint)hierarchy.Length, hierarchy, out uint fetched) == VSConstants.S_OK) && (fetched == hierarchy.Length)) { if ((hierarchy.Length > 0) && (hierarchy[0] != null)) { IVsHierarchy projectHierarchy = hierarchy[0]; if ((projectHierarchy.GetProperty((uint)VSConstants.VSITEMID.Root, (int)__VSHPROPID.VSHPROPID_ExtObject, out object project) == VSConstants.S_OK) && (project is Project dteProject) && _shellProjectService.IsProject(project)) { projects.Add(dteProject); } } } _log.LogMessage("Resolving solution name", LOG_CATEGORY); var solution = dte.Solution?.FileName; if (!string.IsNullOrEmpty(solution)) { solution = Path.GetFileNameWithoutExtension(solution); } model.SolutionName = solution; _log.LogMessage($"Processing {projects.Count} collected solution projects", LOG_CATEGORY); foreach (Project project in projects) { if (_shellProjectService.IsProjectLoadDeferred(project, out _)) { continue; } if (ProcessProject(project, model.Projects, flags, filter)) { ProcessProjectRecursively(project, model.Projects, flags, filter); } } model.Files = model.Projects.SelectMany(p => p.Files).ToList(); if (flags.HasFlag(ProcessorFlags.GroupLinkedFiles)) { // Get all grouped, ie duplicate, files, keep the first code file and remove the rest var groupedFiles = model.Files.GroupBy(f => f.FileNameWithPath).Where(g => g.Count() > 1).Select(g => g); foreach (var group in groupedFiles) { var file = group.FirstOrDefault(f => f.Project.Language.SupportsCompileBuildAction && _shellProjectService.CompileBuildAction(f.ProjectItem)); if (file != null) { group.ForEach(f => { if (f != file) { model.Files.Remove(f); f.Project.Files.Remove(f); AddProjectName(file, f.ProjectName); } }); } } } _log.LogMessage($"Processed {model.Projects.Count} qualified solution projects", LOG_CATEGORY); }