private void ProcessMethod(MethodDefinition monoMethod, MethodEntry entry, ClassCoverageItem klass, string methodName, string cov_info) #endif { if (entry == null) { // Compiler generated, abstract method etc. return; } LineNumberEntry[] lines = entry.LineNumbers; // DEBUG //if( cov_info == null ) // Console.WriteLine( lines.Length ); // DEBUG if (lines.Length == 0) { return; } int start_line = lines [0].Row; int end_line = lines [lines.Length - 1].Row; MethodCoverageItem method = new MethodCoverageItem(klass, methodName); method.startLine = start_line; method.endLine = end_line; #if USE_REFLECTION method.filtered = IsFiltered("[" + monoMethod.DeclaringType.Assembly + "]" + monoMethod.DeclaringType + "::" + monoMethod.Name); #else method.filtered = IsFiltered("[" + monoMethod.DeclaringType.Module.Name + "]" + monoMethod.DeclaringType + "::" + monoMethod.Name); #endif klass.methodsByMethod [monoMethod] = method; if (klass.sourceFile == null) { string sourceFile = entry.SourceFile.FileName; SourceFileCoverageData source = (SourceFileCoverageData)sources [sourceFile]; //Console.WriteLine( source ); if (source == null) { source = new SourceFileCoverageData(sourceFile); sources [sourceFile] = source; } klass.sourceFile = source; } computeMethodCoverage(method, lines, cov_info); }
private void ProcessMethod (MethodDefinition monoMethod, MethodEntry entry, ClassCoverageItem klass, string methodName, string cov_info) #endif { if (entry == null) // Compiler generated, abstract method etc. return; LineNumberEntry[] lines = entry.GetLineNumberTable ().LineNumbers; if (lines.Length == 0) return; int start_line = lines [0].Row; int end_line = lines [lines.Length - 1].Row; MethodCoverageItem method = new MethodCoverageItem (klass, methodName); method.startLine = start_line; method.endLine = end_line; #if USE_REFLECTION method.filtered = IsFiltered ("[" + monoMethod.DeclaringType.Assembly + "]" + monoMethod.DeclaringType + "::" + monoMethod.Name); #else method.filtered = IsFiltered ("[" + monoMethod.DeclaringType.Module.Name + "]" + monoMethod.DeclaringType + "::" + monoMethod.Name); #endif klass.methodsByMethod [monoMethod] = method; if (klass.sourceFile == null) { string sourceFile = entry.CompileUnit.SourceFile.FileName; SourceFileCoverageData source = (SourceFileCoverageData)sources [sourceFile]; if (source == null) { source = new SourceFileCoverageData (sourceFile); sources [sourceFile] = source; } klass.sourceFile = source; } computeMethodCoverage (method, lines, cov_info); }
private void computeMethodCoverage(MethodCoverageItem method, LineNumberEntry[] lines, string cov_info) { ClassCoverageItem klass = method.Class; SourceFileCoverageData source = klass.sourceFile; source.AddMethod(method); int nlines = method.endLine - method.startLine + 1; int[] coverage = new int [nlines]; if (cov_info == null) { for (int i = 0; i < nlines; ++i) { coverage [i] = 0; } } else { for (int i = 0; i < nlines; ++i) { coverage [i] = -1; } // Hand crafted parsing code since this is performance critical int pos = 0; int prev_offset = 0; while (pos < cov_info.Length) { int pos2 = cov_info.IndexOfAny(digits, pos); if (pos2 == -1) { break; } pos = cov_info.IndexOfAny(ws, pos2); if (pos == -1) { break; } int offset = parsePositiveInteger(cov_info, pos2); pos2 = cov_info.IndexOfAny(digits, pos); if (pos2 == -1) { break; } pos = cov_info.IndexOfAny(ws, pos2); int count = parsePositiveInteger(cov_info, pos2); offset += prev_offset; prev_offset = offset; int line1 = 0; int line2 = 0; bool found = GetSourceRangeFor(offset, method, lines, ref line1, ref line2); /* * if (found && (entry.Name.IndexOf ("Find") != -1)) { * Console.WriteLine ("OFFSET: " + offset + " " + line1 + ":" + line2); * } */ if (found) { for (int i = line1; i < line2 + 1; ++i) { if ((i >= method.startLine) && (i <= method.endLine)) { if (coverage [i - method.startLine] < count) { coverage [i - method.startLine] = count; } } } } } } int hit = 0; int missed = 0; for (int i = 0; i < nlines; ++i) { int count = coverage [i]; if (count > 0) { hit++; } else if (count == 0) { missed++; } } method.setCoverage(hit, missed); method.lineCoverage = coverage; }
public static void Export(CoverageModel model, string path) { using (TextWriter writer = new StreamWriter(path, false, Encoding.ASCII)) { foreach (ClassCoverageItem klass in model.Classes.Values) { if (klass.filtered || klass.hit + klass.missed == 0) { continue; } SourceFileCoverageData file = klass.sourceFile; writer.WriteLine("TN:{0}", ""); // TODO relative path writer.WriteLine("SF:{0}", file.sourceFile); // FN records int fnCount = 0; int fnHitted = 0; foreach (MethodCoverageItem fn in file.methods) { if (fn.Class.filtered || fn.Class.hit + fn.Class.missed == 0) { continue; } fnCount++; if (fn.hit > 0) { fnHitted++; } string name = fn.FullName; writer.WriteLine("FN:{0},{1}", fn.startLine, name); writer.WriteLine("FNDA:{0},{1}", fn.hit, name); } writer.WriteLine("FNF:{0}", fnCount); writer.WriteLine("FNH:{0}", fnHitted); // lines coverage int[] coverage = file.Coverage; int ln = 0; int lh = 0; for (int i = 0; i < coverage.Length; i++) { int hits = coverage[i]; if (hits < 0) { continue; // comment } writer.WriteLine("DA:{0},{1}", i + 1, hits); ln++; if (hits > 0) { lh++; } } writer.WriteLine("LF:{0}", ln); writer.WriteLine("LH:{0}", lh); writer.WriteLine("end_of_record"); } } }