private void FindMissingFiles(Project proj)
        {
            Debug.WriteLine($"Project {proj.Name}");

            IDictionary <string, string> dict = new Dictionary <string, string>();

            dict.Add("Configuration", proj.ConfigurationManager.ActiveConfiguration.ConfigurationName);
            using (var projectCollection = new ProjectCollection(dict))
            {
                var buildProject = projectCollection.LoadProject(proj.FullName);

                var physicalFiles          = new HashSet <string>(StringComparer.OrdinalIgnoreCase);
                var logicalFiles           = new HashSet <string>(StringComparer.OrdinalIgnoreCase);
                var physicalFileProjectMap = new Dictionary <string, string>();

                NavigateProjectItems(proj.ProjectItems, buildProject, physicalFiles, logicalFiles,
                                     new HashSet <string>(), physicalFileProjectMap);

                if (Options.NotIncludedFiles)
                {
                    var errorCategory = Options.MessageLevel;

                    physicalFiles.ExceptWith(logicalFiles);

                    foreach (var file in physicalFiles)
                    {
                        Debug.WriteLine($"Physical file: {file}");

                        if (_filters.Any(f => f.IsMatch(file)) || (CheckIgnored(file)))
                        {
                            Debug.WriteLine("\tIgnored by filter");
                            continue;
                        }

                        IVsHierarchy hierarchyItem;
                        string       physicalFileProject = physicalFileProjectMap[file];
                        _solution.GetProjectOfUniqueName(physicalFileProject, out hierarchyItem);

                        var newError = new MissingErrorTask()
                        {
                            ErrorCategory = errorCategory,
                            Category      = TaskCategory.BuildCompile,
                            Text          = "File on disk is not included in project",
                            Code          = Constants.FileOnDiskNotInProject,
                            Document      = file,
                            HierarchyItem = hierarchyItem,
                            ProjectPath   = physicalFileProject,
                        };

                        newError.Navigate += SelectParentProjectInSolution;
                        Debug.WriteLine("\t\t** Missing");

                        _errorListProvider.Tasks.Add(newError);
                    }
                }
            }
        }
 protected override bool VisibleExpression(MissingErrorTask task)
 {
     return(task != null && task.Code == Constants.FileOnDiskNotInProject);
 }
        private void NavigateProjectItems(ProjectItems projectItems, Microsoft.Build.Evaluation.Project buildProject, ISet <string> projectPhysicalFiles, ISet <string> projectLogicalFiles, ISet <string> processedPhysicalDirectories, IDictionary <string, string> physicalFileProjectMap)
        {
            if (projectItems == null)
            {
                return;
            }

            var projectDirectory = buildProject.DirectoryPath + Path.DirectorySeparatorChar;
            var projectFilename  = buildProject.FullPath;

            var errorCategory = Options.MessageLevel;

            foreach (ProjectItem item in projectItems)
            {
                NavigateProjectItems(item.ProjectItems, buildProject, projectPhysicalFiles, projectLogicalFiles, processedPhysicalDirectories, physicalFileProjectMap);

                if (item.Kind != "{6BB5F8EE-4483-11D3-8BCF-00C04F8EC28C}") // VSConstants.GUID_ItemType_PhysicalFile
                {
                    continue;
                }

                string itemName = item.Name;
                Debug.WriteLine("\t" + itemName + item.Kind);

                for (short i = 0; i < item.FileCount; i++)
                {
                    var filePath = item.FileNames[i];

                    // Skip if this is a linked file
                    if (!filePath.StartsWith(projectDirectory, StringComparison.InvariantCultureIgnoreCase))
                    {
                        continue;
                    }

                    projectLogicalFiles.Add(filePath);

                    if (!File.Exists(filePath))
                    {
                        var relativePath = filePath.Replace(buildProject.DirectoryPath + @"\", "");

                        var found = buildProject.Items.Any(x => x.EvaluatedInclude == relativePath);

                        if (!found)
                        {
                            Debug.WriteLine("\t\tFile excluded due to Condition evaluation");
                            return;
                        }

                        IVsHierarchy hierarchyItem;
                        _solution.GetProjectOfUniqueName(projectFilename, out hierarchyItem);

                        var newError = new MissingErrorTask()
                        {
                            ErrorCategory = errorCategory,
                            Category      = TaskCategory.BuildCompile,
                            Text          = "File referenced in project does not exist",
                            Code          = "MI0001",
                            Document      = filePath,
                            HierarchyItem = hierarchyItem,
                            ProjectPath   = projectFilename
                        };

                        newError.Navigate += NewErrorOnNavigate;
                        Debug.WriteLine("\t\t** Missing");

                        _errorListProvider.Tasks.Add(newError);
                    }

                    string directoryName = Path.GetDirectoryName(filePath);

                    // If we haven't seen this directory before, find the files inside it
                    if (processedPhysicalDirectories.Add(directoryName))
                    {
                        AddGitIgnoreFromDirectory(directoryName);

                        var physicalFiles =
                            new DirectoryInfo(directoryName).GetFiles()
                            .Where(
                                f => f.Attributes != FileAttributes.Hidden && f.Attributes != FileAttributes.System)
                            .Where(f => !f.Name.EndsWith(".user", StringComparison.InvariantCultureIgnoreCase) &&
                                   !f.Name.EndsWith("proj", StringComparison.InvariantCultureIgnoreCase))
                            .Select(f => f.FullName)
                            .ToList();

                        foreach (var physicalFile in physicalFiles)
                        {
                            projectPhysicalFiles.Add(physicalFile);
                            physicalFileProjectMap.Add(physicalFile, projectFilename);
                        }
                    }
                }
            }
        }
 protected abstract bool VisibleExpression(MissingErrorTask task);
Beispiel #5
0
        private void FindMissingFiles()
        {
            // unhook event handlers to reduce risk of memory leaks
            foreach (MissingErrorTask task in _errorListProvider.Tasks)
            {
                task.Navigate -= SelectParentProjectInSolution;
                task.Navigate -= NewErrorOnNavigate;
            }

            _errorListProvider.Tasks.Clear();

            var projects = _dte.AllProjects();

            var solutionDirectory = Path.GetDirectoryName(_dte.Solution.FullName);

            var        gitIgnoreFile = Path.Combine(solutionDirectory, ".gitignore");
            IgnoreList gitignores    = null;

            if (Options.UseGitIgnore && File.Exists(gitIgnoreFile))
            {
                gitignores = new IgnoreList(gitIgnoreFile);
            }

            var filters = new List <Regex>();

            if (!string.IsNullOrEmpty(Options.IgnorePhysicalFiles))
            {
                filters.AddRange(Options.IgnorePhysicalFiles.Split(new[] { "\r\n" },
                                                                   StringSplitOptions.RemoveEmptyEntries).Select(p => FindFilesPatternToRegex.Convert(p.Trim())));
            }

            foreach (Project proj in projects)
            {
                Debug.WriteLine(proj.Name);

                IDictionary <string, string> dict = new Dictionary <string, string>();
                dict.Add("Configuration", proj.ConfigurationManager.ActiveConfiguration.ConfigurationName);
                using (var projectCollection = new ProjectCollection(dict))
                {
                    var buildProject = projectCollection.LoadProject(proj.FullName);

                    var physicalFiles          = new HashSet <string>(StringComparer.OrdinalIgnoreCase);
                    var logicalFiles           = new HashSet <string>(StringComparer.OrdinalIgnoreCase);
                    var physicalFileProjectMap = new Dictionary <string, string>();

                    NavigateProjectItems(proj.ProjectItems, buildProject, physicalFiles, logicalFiles,
                                         new HashSet <string>(), physicalFileProjectMap);

                    if (Options.NotIncludedFiles)
                    {
                        var errorCategory = Options.MessageLevel;

                        physicalFiles.ExceptWith(logicalFiles);

                        foreach (var file in physicalFiles)
                        {
                            Debug.WriteLine($"Physical file: {file}");

                            if (filters.Any(f => f.IsMatch(file)) || (gitignores != null && gitignores.IsIgnored(file, false)))
                            {
                                Debug.WriteLine("\tIgnored by filter");
                                continue;
                            }

                            IVsHierarchy hierarchyItem;
                            string       physicalFileProject = physicalFileProjectMap[file];
                            _solution.GetProjectOfUniqueName(physicalFileProject, out hierarchyItem);

                            var newError = new MissingErrorTask()
                            {
                                ErrorCategory = errorCategory,
                                Category      = TaskCategory.BuildCompile,
                                Text          = "File on disk is not included in project",
                                Code          = Constants.FileOnDiskNotInProject,
                                Document      = file,
                                HierarchyItem = hierarchyItem,
                                ProjectPath   = physicalFileProject,
                            };

                            newError.Navigate += SelectParentProjectInSolution;
                            Debug.WriteLine("\t\t** Missing");

                            _errorListProvider.Tasks.Add(newError);
                        }
                    }
                }
            }

            if (_errorListProvider.Tasks.Count > 0)
            {
                _errorListProvider.Show();

                if (Options.FailBuildOnError && Options.Timing == RunWhen.BeforeBuild)
                {
                    _dte.ExecuteCommand("Build.Cancel");
                }
            }
        }