/// <summary> /// Gets a ComplexityData object for the given source file, or creates it if it does not exist. /// </summary> /// <param name="SourceFile">The source file to check for</param> /// <param name="FileToComplexityData">Mapping of source file to complexity data</param> /// <returns>The complexity data object for the given file</returns> static ComplexityData FindOrAddComplexityData(SourceFile SourceFile, Dictionary <SourceFile, ComplexityData> FileToComplexityData) { ComplexityData ReportData; if (!FileToComplexityData.TryGetValue(SourceFile, out ReportData)) { // Add the new data ReportData = new ComplexityData(); FileToComplexityData.Add(SourceFile, ReportData); } return(ReportData); }
/// <summary> /// Generate a report showing the number of preprocessed lines in the selected files /// </summary> /// <param name="Files">The files to include in the report</param> /// <param name="ReportFileLocation">Output file for the report</param> /// <param name="Log">Writer for log output</param> public static void Generate(FileReference ReportFileLocation, IEnumerable <SourceFile> Files, LineBasedTextWriter Log) { Log.WriteLine("Writing {0}...", ReportFileLocation.FullName); // Build a list of all the files in the report SourceFile[] AllFiles = Files.SelectMany(x => FindIncludedFiles(x)).Distinct().ToArray(); // Find a map of file to the number of preprocessed lines in it Dictionary <SourceFile, ComplexityData> FileToReportData = new Dictionary <SourceFile, ComplexityData>(); foreach (SourceFile File in AllFiles) { // Create the complexity data for this file ComplexityData ReportData = FindOrAddComplexityData(File, FileToReportData); Debug.Assert(ReportData.NumPreprocessedLines == 0); // Calculate the preprocessed line count, and update each file it includes with this file foreach (SourceFile IncludedFile in FindIncludedFiles(File)) { ComplexityData IncludedFileReportData = FindOrAddComplexityData(IncludedFile, FileToReportData); IncludedFileReportData.IncludedBy.Add(File); ReportData.NumPreprocessedLines += IncludedFile.Text.Lines.Length; } // Add this file to each file it directly includes foreach (PreprocessorMarkup Markup in File.Markup) { if (Markup.Type == PreprocessorMarkupType.Include && Markup.IsActive) { foreach (SourceFile IncludedFile in Markup.OutputIncludedFiles) { ComplexityData IncludedFileReportData = FindOrAddComplexityData(IncludedFile, FileToReportData); IncludedFileReportData.DirectlyIncludedBy.Add(File); } } } } // Write out a CSV report containing the list of files and their line counts using (StreamWriter Writer = new StreamWriter(ReportFileLocation.FullName)) { Writer.WriteLine("File,Line Count,Num Indirect Includes,Num Direct Includes,Direct Includes"); foreach (KeyValuePair <SourceFile, ComplexityData> Pair in FileToReportData.OrderByDescending(x => x.Value.NumPreprocessedLines)) { string IncludedByList = String.Join(", ", Pair.Value.DirectlyIncludedBy.Select(x => GetDisplayName(x)).OrderBy(x => x)); Writer.WriteLine("{0},{1},{2},{3},\"{4}\"", GetDisplayName(Pair.Key), Pair.Value.NumPreprocessedLines, Pair.Value.IncludedBy.Count, Pair.Value.DirectlyIncludedBy.Count, IncludedByList); } } }