/// <summary> /// Creates a module coverage statistics based on given coverage buffer. /// </summary> /// <param name="files">List to which instrumented files are added.</param> /// <param name="module">Information about module coverage.</param> /// <param name="lineStartId">Starting identification number for method lines.</param> /// <returns>New <see cref="ModuleStatistics"/> instance.</returns> internal static ModuleStatistics Create(FileSpecList files, ICoverageModule module, ref long lineStartId) { var moduleStats = new ModuleStatistics(module.Name, module.Signature, module.ImageSize, module.ImageLinkTime); var lines = new List<BlockLineRange>(); var coverageBuffer = module.GetCoverageBuffer(null /* tests */); using (var symbolReader = module.Symbols.CreateReader()) { uint methodId; string methodName; string undecoratedMethodName; string className; string namespaceName; while (symbolReader.GetNextMethod(out methodId, out methodName, out undecoratedMethodName, out className, out namespaceName, lines)) { var namespaceStats = moduleStats.GetOrAddNamespace(namespaceName); var classStats = namespaceStats.GetOrAddClass(className); var methodStats = MethodStatistics.Create(methodId, methodName, undecoratedMethodName, coverageBuffer, lines, files, ref lineStartId); classStats.AddMethod(methodStats); // Clear the method list to be ready for next method. lines.Clear(); } } return moduleStats; }
/// <summary> /// Creates a block coverage information list for a single method represented by a set of lines. /// </summary> /// <param name="coverageBuffer">Buffer containing all coverage information.</param> /// <param name="lines">Lines representing a single method.</param> /// <param name="files">List to which instrumented files are added.</param> /// <param name="startId">Starting identification number for blocks.</param> internal static IEnumerable<BlockCoverage> CreateForMethod(byte[] coverageBuffer, IList<BlockLineRange> lines, FileSpecList files) { if (coverageBuffer == null) throw new ArgumentNullException("coverageBuffer"); if (lines == null) throw new ArgumentNullException("lines"); if (files == null) throw new ArgumentNullException("files"); // First generate block coverage map based on the coverage buffer ... var blockCoverageMap = GetBlockCoverageMap(coverageBuffer, lines); // Then create coverage information for all lines of the method. var blocks = new List<BlockCoverage>(); foreach (var line in lines.Where(line => line.IsValid)) { var file = files.GetOrAdd(line.SourceFile); blocks.Add(new BlockCoverage(file, line.StartLine, line.EndLine, line.StartColumn, line.EndColumn, blockCoverageMap[line])); } return blocks; }
/// <summary> /// Creates a method coverage statistics based on given coverage buffer. /// </summary> /// <param name="id">Identification assigned to the method.</param> /// <param name="name">Method name.</param> /// <param name="fullName">Method full name.</param> /// <param name="coverageBuffer">Coverage buffer.</param> /// <param name="lines">Lines representing the method.</param> /// <param name="files">List to which instrumented files are added.</param> /// <param name="lineStartId">Starting identification number for lines.</param> /// <returns>New <see cref="MethodStatistics"/> instance.</returns> internal static MethodStatistics Create(uint id, string name, string fullName, byte[] coverageBuffer, IList<BlockLineRange> lines, FileSpecList files, ref long lineStartId) { var coverageStats = CoverageInfo.GetMethodStatistics(coverageBuffer, lines); var methodStats = new MethodStatistics(id, name, fullName, coverageStats); foreach (var block in BlockCoverage.CreateForMethod(coverageBuffer, lines, files)) if (methodStats.AddBlock(block)) block.Id = lineStartId++; return methodStats; }