// Looks at the project item. If it's a supported file type it's added to the list, and if it's a filter it keeps digging into it.
        private async Task scanProjectItemForSourceFilesAsync(ProjectItem item, SourceFilesWithConfiguration configuredFiles, Configuration configuration, Project project)
        {
            await JoinableTaskFactory.SwitchToMainThreadAsync();

            var itemType = await getTypeOfProjectItemAsync(item);

            if (itemType == ProjectItemType.folder)
            {
                foreach (ProjectItem subItem in item.ProjectItems)
                {
                    await scanProjectItemForSourceFilesAsync(subItem, configuredFiles, configuration, project);
                }
            }
            else if (itemType == ProjectItemType.headerFile || itemType == ProjectItemType.cFile || itemType == ProjectItemType.cppFile)
            {
                var document = item.Document;
                if (document == null)
                {
                    Debug.Fail("isCppFileAsync(item) is true, but item.Document is null!");
                    return;
                }

                SourceFile sourceFile = await createSourceFileAsync(document.FullName, configuration, project);

                configuredFiles.addFileIfDoesntExistAlready(sourceFile);
            }
        }
        private void runSavedFileAnalysis(SourceFile file, Configuration currentConfig)
        {
            Debug.Assert(currentConfig != null);

            var configuredFiles = new SourceFilesWithConfiguration();

            configuredFiles.addFileIfDoesntExistAlready(file);
            configuredFiles.Configuration = currentConfig;

            _ = System.Threading.Tasks.Task.Run(async delegate
            {
                await System.Threading.Tasks.Task.Delay(750);
                await JoinableTaskFactory.SwitchToMainThreadAsync();
                runAnalysis(new List <SourceFilesWithConfiguration> {
                    configuredFiles
                }, true);
            });
        }
        private async Task <SourceFilesWithConfiguration> getAllSupportedFilesFromProjectAsync(Project project)
        {
            var sourceFiles = new SourceFilesWithConfiguration();

            sourceFiles.Configuration = await getConfigurationAsync(project);

            await JoinableTaskFactory.SwitchToMainThreadAsync();

            foreach (ProjectItem item in project.ProjectItems)
            {
                ProjectItemType itemType = await getTypeOfProjectItemAsync(item);

                if (itemType == ProjectItemType.cFile || itemType == ProjectItemType.cppFile || itemType == ProjectItemType.headerFile)
                {
                    //List<SourceFile> projectSourceFileList = await getProjectFilesAsync(project, configuration);
                    //foreach (SourceFile projectSourceFile in projectSourceFileList)
                    //	addEntry(currentConfiguredFiles, projectSourceFileList, project);
                }
            }

            return(sourceFiles);
        }
        private async Task checkProjectsAsync(List <Project> projects)
        {
            Debug.Assert(projects.Any());

            List <SourceFilesWithConfiguration> allConfiguredFiles = new List <SourceFilesWithConfiguration>();

            foreach (var project in projects)
            {
                await JoinableTaskFactory.SwitchToMainThreadAsync();

                Configuration config = await getConfigurationAsync(project);

                if (config == null)
                {
                    MessageBox.Show("No valid configuration in project " + project.Name);
                    continue;
                }

                SourceFilesWithConfiguration sourceFiles = new SourceFilesWithConfiguration();
                sourceFiles.Configuration = config;

                foreach (ProjectItem projectItem in project.ProjectItems)
                {
                    await scanProjectItemForSourceFilesAsync(projectItem, sourceFiles, config, project);
                }

                allConfiguredFiles.Add(sourceFiles);
            }

            _ = JoinableTaskFactory.RunAsync(async() => {
                await JoinableTaskFactory.SwitchToMainThreadAsync();

                MainToolWindow.Instance.ContentsType = ICodeAnalyzer.AnalysisType.ProjectAnalysis;
                MainToolWindow.Instance.showIfWindowNotCreated();
            });

            runAnalysis(allConfiguredFiles, false);
        }
        // Looks at the project item. If it's a supported file type it's added to the list, and if it's a filter it keeps digging into it.
        private async Task scanProjectItemForSourceFilesAsync(ProjectItem item, SourceFilesWithConfiguration configuredFiles, Configuration configuration, Project project)
        {
            await JoinableTaskFactory.SwitchToMainThreadAsync();

            var itemType = await getTypeOfProjectItemAsync(item);

            if (itemType == ProjectItemType.folder)
            {
                foreach (ProjectItem subItem in item.ProjectItems)
                {
                    await scanProjectItemForSourceFilesAsync(subItem, configuredFiles, configuration, project);
                }
            }
            else if (itemType == ProjectItemType.headerFile || itemType == ProjectItemType.cFile || itemType == ProjectItemType.cppFile)
            {
                var itemName = item.Name;

                if (item.FileCount == 0)
                {
                    Debug.Fail("isCppFileAsync(item) is true, but item.FileCount is null!");
                    return;
                }

                var itemFileName = item.FileNames[1];
                if (!configuredFiles.Exists(itemFileName))
                {
                    // Don't bother rebuilding the entire definition if it already exists.
                    SourceFile sourceFile = await createSourceFileAsync(item);

                    if (sourceFile != null)
                    {
                        configuredFiles.addOrUpdateFile(sourceFile);
                        scanProgressUpdated(configuredFiles.Count());
                    }
                }
            }
        }
示例#6
0
        private string getCPPCheckArgs(SourceFilesWithConfiguration configuredFiles, bool analysisOnSavedFile, string tempFileName)
        {
            if (!configuredFiles.Any())
            {
                Debug.Fail("Empty files list!");
                return("");
            }

            Debug.Assert(_numCores > 0);
            String cppheckargs = Properties.Settings.Default.DefaultArguments;

            if (Properties.Settings.Default.SeveritiesString.Length != 0)
            {
                cppheckargs += " --enable=" + Properties.Settings.Default.SeveritiesString;
            }

            HashSet <string> suppressions = new HashSet <string>(Properties.Settings.Default.SuppressionsString.Split(','));

            suppressions.Add("unmatchedSuppression");

            HashSet <string> skippedFilesMask   = new HashSet <string>();
            HashSet <string> skippedIncludeMask = new HashSet <string>();

            SuppressionsInfo unitedSuppressionsInfo = readSuppressions(ICodeAnalyzer.SuppressionStorage.Global);

            unitedSuppressionsInfo.UnionWith(readSuppressions(ICodeAnalyzer.SuppressionStorage.Solution));

            var filesToAnalyze = configuredFiles.Files;
            // Creating the list of all different project locations (no duplicates)
            HashSet <string> projectPaths = new HashSet <string>();           // enforce uniqueness on the list of project paths

            foreach (var file in filesToAnalyze)
            {
                projectPaths.Add(file.BaseProjectPath);
            }

            Debug.Assert(projectPaths.Count == 1);
            _projectBasePath = projectPaths.First();
            _projectName     = filesToAnalyze.First().ProjectName;

            // Creating the list of all different suppressions (no duplicates)
            foreach (var path in projectPaths)
            {
                unitedSuppressionsInfo.UnionWith(readSuppressions(SuppressionStorage.Project, path, filesToAnalyze.First().ProjectName));
            }

            cppheckargs += (" --relative-paths=\"" + _projectBasePath + "\"");
            cppheckargs += (" -j " + _numCores.ToString());
            if (Properties.Settings.Default.InconclusiveChecksEnabled)
            {
                cppheckargs += " --inconclusive ";
            }

            suppressions.UnionWith(unitedSuppressionsInfo.SuppressionLines);
            foreach (string suppression in suppressions)
            {
                if (!String.IsNullOrWhiteSpace(suppression))
                {
                    cppheckargs += (" --suppress=" + suppression);
                }
            }

            if (!(analysisOnSavedFile && Properties.Settings.Default.IgnoreIncludePaths))
            {
                // We only add include paths once, and then specify a set of files to check
                HashSet <string> includePaths = new HashSet <string>();
                foreach (var file in filesToAnalyze)
                {
                    if (!matchMasksList(file.FilePath, unitedSuppressionsInfo.SkippedFilesMask))
                    {
                        includePaths.UnionWith(file.IncludePaths);
                    }
                }

                includePaths.Add(filesToAnalyze.First().BaseProjectPath);                 // Fix for #60

                foreach (string path in includePaths)
                {
                    if (!matchMasksList(path, unitedSuppressionsInfo.SkippedIncludesMask))
                    {
                        String includeArgument = " -I\"" + path + "\"";
                        cppheckargs = cppheckargs + " " + includeArgument;
                    }
                }
            }

            using (StreamWriter tempFile = new StreamWriter(tempFileName))
            {
                foreach (SourceFile file in filesToAnalyze)
                {
                    if (!matchMasksList(file.FilePath, unitedSuppressionsInfo.SkippedFilesMask))
                    {
                        tempFile.WriteLine(file.FilePath);
                    }
                }
            }

            cppheckargs += " --file-list=\"" + tempFileName + "\"";

            if ((analysisOnSavedFile && Properties.Settings.Default.FileOnlyCheckCurrentConfig) ||
                (!analysisOnSavedFile && Properties.Settings.Default.ProjectOnlyCheckCurrentConfig))                 // Only checking current macros configuration (for speed)
            {
                cppheckargs = cppheckargs.Replace("--force", "");
                // Creating the list of all different macros (no duplicates)
                HashSet <string> macros = new HashSet <string>();
                // TODO: handle /Zc:__cplusplus
                // https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/
                macros.Add("__cplusplus=199711L");                 // At least in VS2012, this is still 199711L
                // Assuming all files passed here are from the same project / same toolset, which should be true, so peeking the first file for global settings
                switch (filesToAnalyze.First().vcCompilerVersion)
                {
                case SourceFile.VCCompilerVersion.vc2003:
                    macros.Add("_MSC_VER=1310");
                    break;

                case SourceFile.VCCompilerVersion.vc2005:
                    macros.Add("_MSC_VER=1400");
                    break;

                case SourceFile.VCCompilerVersion.vc2008:
                    macros.Add("_MSC_VER=1500");
                    break;

                case SourceFile.VCCompilerVersion.vc2010:
                    macros.Add("_MSC_VER=1600");
                    break;

                case SourceFile.VCCompilerVersion.vc2012:
                    macros.Add("_MSC_VER=1700");
                    break;

                case SourceFile.VCCompilerVersion.vc2013:
                    macros.Add("_MSC_VER=1800");
                    break;

                case SourceFile.VCCompilerVersion.vc2015:
                    macros.Add("_MSC_VER=1900");
                    break;

                case SourceFile.VCCompilerVersion.vc2017:
                    macros.Add("_MSC_VER=1916");
                    break;

                case SourceFile.VCCompilerVersion.vc2019:
                    macros.Add("_MSC_VER=1926");
                    macros.Add("_MSC_FULL_VER=192628808");
                    break;
                }

                foreach (var file in filesToAnalyze)
                {
                    macros.UnionWith(file.Macros);
                }
                macros.Add("WIN32");
                macros.Add("_WIN32");

                CPPCheckPluginPackage.Instance.JoinableTaskFactory.Run(async() =>
                {
                    if (await configuredFiles.is64bitConfigurationAsync())
                    {
                        macros.Add("_M_X64");
                        macros.Add("_WIN64");
                    }
                    else
                    {
                        macros.Add("_M_IX86");
                    }

                    if (await configuredFiles.isDebugConfigurationAsync())
                    {
                        macros.Add("_DEBUG");
                    }
                });

                foreach (string macro in macros)
                {
                    if (!String.IsNullOrEmpty(macro) && !macro.Contains(" ") /* macros with spaces are invalid in VS */)
                    {
                        String macroArgument = " -D" + macro;
                        cppheckargs += macroArgument;
                    }
                }

                HashSet <string> macrosToUndefine = new HashSet <string>();
                foreach (var file in filesToAnalyze)
                {
                    macrosToUndefine.UnionWith(file.MacrosToUndefine);
                }

                foreach (string macro in macrosToUndefine)
                {
                    if (!String.IsNullOrEmpty(macro) && !macro.Contains(" ") /* macros with spaces are invalid in VS */)
                    {
                        String macroUndefArgument = " -U" + macro;
                        cppheckargs += macroUndefArgument;
                    }
                }
            }
            else if (!cppheckargs.Contains("--force"))
            {
                cppheckargs += " --force";
            }

            return(cppheckargs);
        }
        private async Task checkProjectsAsync(List <Project> projects)
        {
            Debug.Assert(projects.Any());
            setMenuState(true);

            List <SourceFilesWithConfiguration> allConfiguredFiles = new List <SourceFilesWithConfiguration>();

            foreach (var project in projects)
            {
                await JoinableTaskFactory.SwitchToMainThreadAsync();

                Configuration config = await getConfigurationAsync(project);

                if (config == null)
                {
                    MessageBox.Show("No valid configuration in project " + project.Name);
                    continue;
                }

                SourceFilesWithConfiguration sourceFiles = new SourceFilesWithConfiguration();
                sourceFiles.Configuration = config;

                foreach (ProjectItem projectItem in project.ProjectItems)
                {
                    await scanProjectItemForSourceFilesAsync(projectItem, sourceFiles, config, project);
                }

                // Although we're using the same base configuration, it's possible for each file to override that.
                // Group files into separate configs based on actual parameters. We'll be iterating in reverse order so
                // reverse the list first to keep the final order the same.
                List <SourceFile> allSourceFiles = sourceFiles.Files.ToList();
                allSourceFiles.Reverse();

                while (allSourceFiles.Any())
                {
                    SourceFilesWithConfiguration newConfig = new SourceFilesWithConfiguration();
                    newConfig.Configuration = config;

                    SourceFile templateFile = allSourceFiles.Last();
                    newConfig.addOrUpdateFile(templateFile);
                    allSourceFiles.RemoveAt(allSourceFiles.Count - 1);

                    for (int i = allSourceFiles.Count - 1; i >= 0; i--)
                    {
                        SourceFile otherFile = allSourceFiles[i];

                        if (otherFile.Macros.All(templateFile.Macros.Contains) && templateFile.Macros.All(otherFile.Macros.Contains) &&
                            otherFile.MacrosToUndefine.All(templateFile.MacrosToUndefine.Contains) && templateFile.MacrosToUndefine.All(otherFile.MacrosToUndefine.Contains) &&
                            otherFile.IncludePaths.All(templateFile.IncludePaths.Contains) && templateFile.IncludePaths.All(otherFile.IncludePaths.Contains) &&
                            otherFile.ProjectName == templateFile.ProjectName
                            )
                        {
                            newConfig.addOrUpdateFile(otherFile);
                            allSourceFiles.RemoveAt(i);
                        }
                    }

                    if (newConfig.Any())
                    {
                        allConfiguredFiles.Add(newConfig);
                    }
                }
            }

            _ = JoinableTaskFactory.RunAsync(async() => {
                await JoinableTaskFactory.SwitchToMainThreadAsync();

                MainToolWindow.Instance.ContentsType = ICodeAnalyzer.AnalysisType.ProjectAnalysis;
                MainToolWindow.Instance.showIfWindowNotCreated();
            });

            scanProgressUpdated(-1);
            runAnalysis(allConfiguredFiles, false);
        }