private IEnumerable <HistoricCoverage> ParseHistoricFile(IDictionary <string, Class> classes, XDocument document, DateTime date, string tag) { ConcurrentBag <HistoricCoverage> historicCoverages = new ConcurrentBag <HistoricCoverage>(); Parallel.ForEach(document.Root.Elements("assembly").ToArray(), assemblyElement => { string assemblyName = assemblyElement.Attribute("name").Value; foreach (var classElement in assemblyElement.Elements("class")) { HistoricCoverage historicCoverage = new HistoricCoverage(date, tag) { CoveredLines = int.Parse(classElement.Attribute("coveredlines").Value, CultureInfo.InvariantCulture), CoverableLines = int.Parse(classElement.Attribute("coverablelines").Value, CultureInfo.InvariantCulture), TotalLines = int.Parse(classElement.Attribute("totallines").Value, CultureInfo.InvariantCulture), CoveredBranches = int.Parse(classElement.Attribute("coveredbranches").Value, CultureInfo.InvariantCulture), TotalBranches = int.Parse(classElement.Attribute("totalbranches").Value, CultureInfo.InvariantCulture) }; historicCoverages.Add(historicCoverage); if (classes.TryGetValue(this.GetFullClassName(assemblyName, classElement.Attribute("name").Value), out var @class)) { @class.AddHistoricCoverage(historicCoverage); } } }); return(historicCoverages); }
/// <summary> /// Reads all historic coverage files created by <see cref="HistoryReportGenerator"/> and adds the information to all classes. /// </summary> internal void ApplyHistoricCoverage() { Logger.Info(Resources.ReadingHistoricReports); var files = Directory .EnumerateFiles(this.historyDirectory, "*_CoverageHistory.xml") .OrderByDescending(f => f) .Take(Settings.Default.MaximumOfHistoricCoverageFiles) .Reverse(); foreach (var file in files) { try { XDocument document = XDocument.Load(file); DateTime date = DateTime.ParseExact(document.Root.Attribute("date").Value, "yyyy-MM-dd_HH-mm-ss", CultureInfo.InvariantCulture); foreach (var assemblyElement in document.Root.Elements("assembly")) { Assembly assembly = this.assemblies .SingleOrDefault(a => a.Name == assemblyElement.Attribute("name").Value); if (assembly == null) { continue; } foreach (var classElement in assemblyElement.Elements("class")) { Class @class = assembly.Classes .SingleOrDefault(c => c.Name == classElement.Attribute("name").Value); if (@class == null) { continue; } HistoricCoverage historicCoverage = new HistoricCoverage(date) { CoveredLines = int.Parse(classElement.Attribute("coveredlines").Value, CultureInfo.InvariantCulture), CoverableLines = int.Parse(classElement.Attribute("coverablelines").Value, CultureInfo.InvariantCulture), TotalLines = int.Parse(classElement.Attribute("totallines").Value, CultureInfo.InvariantCulture), CoveredBranches = int.Parse(classElement.Attribute("coveredbranches").Value, CultureInfo.InvariantCulture), TotalBranches = int.Parse(classElement.Attribute("totalbranches").Value, CultureInfo.InvariantCulture) }; @class.AddHistoricCoverage(historicCoverage); } } } catch (Exception ex) { Logger.ErrorFormat(" " + Resources.ErrorDuringReadingHistoricReport, file, ex.Message); } } }
/// <summary> /// Reads all historic coverage files created by <see cref="HistoryReportGenerator" /> and adds the information to all classes. /// </summary> /// <param name="assemblies">The assemblies.</param> internal void ApplyHistoricCoverage(IEnumerable <Assembly> assemblies) { if (assemblies == null) { throw new ArgumentNullException(nameof(assemblies)); } Logger.Info(Resources.ReadingHistoricReports); IEnumerable <string> files = null; try { files = this.historyStorage.GetHistoryFilePaths() .OrderByDescending(f => f) .Take(Settings.Default.MaximumOfHistoricCoverageFiles) .Reverse() .ToArray(); } catch (Exception ex) { Logger.ErrorFormat(" " + Resources.ErrorDuringReadingHistoricReports, ex.Message); return; } foreach (var file in files) { try { XDocument document = null; using (var stream = this.historyStorage.LoadFile(file)) { document = XDocument.Load(stream); } DateTime date = DateTime.ParseExact(document.Root.Attribute("date").Value, "yyyy-MM-dd_HH-mm-ss", CultureInfo.InvariantCulture); string tag = document.Root.Attribute("tag")?.Value; tag = string.IsNullOrEmpty(tag) ? null : tag; foreach (var assemblyElement in document.Root.Elements("assembly")) { Assembly assembly = assemblies .SingleOrDefault(a => a.Name == assemblyElement.Attribute("name").Value); if (assembly == null) { continue; } foreach (var classElement in assemblyElement.Elements("class")) { Class @class = assembly.Classes .SingleOrDefault(c => c.Name == classElement.Attribute("name").Value); if (@class == null) { continue; } HistoricCoverage historicCoverage = new HistoricCoverage(date, tag) { CoveredLines = int.Parse(classElement.Attribute("coveredlines").Value, CultureInfo.InvariantCulture), CoverableLines = int.Parse(classElement.Attribute("coverablelines").Value, CultureInfo.InvariantCulture), TotalLines = int.Parse(classElement.Attribute("totallines").Value, CultureInfo.InvariantCulture), CoveredBranches = int.Parse(classElement.Attribute("coveredbranches").Value, CultureInfo.InvariantCulture), TotalBranches = int.Parse(classElement.Attribute("totalbranches").Value, CultureInfo.InvariantCulture) }; @class.AddHistoricCoverage(historicCoverage); } } } catch (Exception ex) { Logger.ErrorFormat(" " + Resources.ErrorDuringReadingHistoricReport, file, ex.Message); } } }
/// <summary> /// Starts the generation of the report. /// </summary> /// <param name="addHistoricCoverage">if set to <c>true</c> historic coverage information is added to classes.</param> /// <param name="overallHistoricCoverages">All historic coverage elements.</param> /// <param name="executionTime">The execution time.</param> /// <param name="tag">The custom tag (e.g. build number).</param> internal void CreateReport(bool addHistoricCoverage, List <HistoricCoverage> overallHistoricCoverages, DateTime executionTime, string tag) { int numberOfClasses = this.parserResult.Assemblies.Sum(a => a.Classes.Count()); Logger.InfoFormat(Resources.AnalyzingClasses, numberOfClasses); int counter = 0; foreach (var assembly in this.parserResult.Assemblies) { foreach (var @class in assembly.Classes) { counter++; Logger.DebugFormat( " " + Resources.CreatingReport, counter, numberOfClasses, @class.Assembly.ShortName, @class.Name); var fileAnalyses = @class.Files.Select(f => f.AnalyzeFile()).ToArray(); if (addHistoricCoverage) { var historicCoverage = new HistoricCoverage(@class, executionTime, tag); @class.AddHistoricCoverage(historicCoverage); overallHistoricCoverages.Add(historicCoverage); } Parallel.ForEach( this.renderers, renderer => { try { renderer.CreateClassReport(@class, fileAnalyses); } catch (Exception ex) { Logger.ErrorFormat( " " + Resources.ErrorDuringRenderingClassReport, @class.Name, renderer.ReportType, ex.GetExceptionMessageForDisplay()); } }); } } Logger.Debug(" " + Resources.CreatingSummary); SummaryResult summaryResult = new SummaryResult(this.parserResult.Assemblies, this.parserResult.ParserName, this.parserResult.SupportsBranchCoverage, this.parserResult.SourceDirectories); foreach (var renderer in this.renderers) { try { renderer.CreateSummaryReport(summaryResult); } catch (Exception ex) { Logger.ErrorFormat( " " + Resources.ErrorDuringRenderingSummaryReport, renderer.ReportType, ex.GetExceptionMessageForDisplay()); } } }
/// <summary> /// Starts the generation of the report. /// </summary> /// <param name="addHistoricCoverage">if set to <c>true</c> historic coverage information is added to classes.</param> /// <param name="overallHistoricCoverages">All historic coverage elements.</param> /// <param name="executionTime">The execution time.</param> /// <param name="tag">The custom tag (e.g. build number).</param> /// <returns>The filters assemblies.</returns> internal IEnumerable <Assembly> CreateReport(bool addHistoricCoverage, List <HistoricCoverage> overallHistoricCoverages, DateTime executionTime, string tag) { var filteredAssemblies = this.parser.Assemblies .Where(a => this.assemblyFilter.IsElementIncludedInReport(a.Name)) .Select(a => { var newAssembly = new Assembly(a.Name); foreach (var @class in a.Classes) { if (classFilter.IsElementIncludedInReport(@class.Name)) { newAssembly.AddClass(@class); foreach (var file in @class.Files.Where(f => !this.fileFilter.IsElementIncludedInReport(f.Path))) { @class.RemoveFile(file); } } } return(newAssembly); }); int numberOfClasses = filteredAssemblies.Sum(a => a.Classes.Count()); Logger.InfoFormat(Resources.AnalyzingClasses, numberOfClasses); int counter = 0; foreach (var assembly in filteredAssemblies) { foreach (var @class in assembly.Classes) { counter++; Logger.DebugFormat( " " + Resources.CreatingReport, counter, numberOfClasses, @class.Assembly.ShortName, @class.Name); var fileAnalyses = @class.Files.Select(f => f.AnalyzeFile()).ToArray(); if (addHistoricCoverage) { var historicCoverage = new HistoricCoverage(@class, executionTime, tag); @class.AddHistoricCoverage(historicCoverage); overallHistoricCoverages.Add(historicCoverage); } foreach (var renderer in this.renderers) { try { renderer.CreateClassReport(@class, fileAnalyses); } catch (Exception ex) { Logger.ErrorFormat( " " + Resources.ErrorDuringRenderingClassReport, @class.Name, renderer.ReportType, ex.Message); } } } } Logger.Debug(" " + Resources.CreatingSummary); SummaryResult summaryResult = new SummaryResult(filteredAssemblies, this.parser.ToString(), this.parser.SupportsBranchCoverage); foreach (var renderer in this.renderers) { try { renderer.CreateSummaryReport(summaryResult); } catch (Exception ex) { Logger.ErrorFormat( " " + Resources.ErrorDuringRenderingSummaryReport, renderer.ReportType, ex.Message); } } return(filteredAssemblies); }