Dragan 12 years ago
parent
commit
0d3d409975
  1. 816
      src/AddIns/Analysis/CodeCoverage/Project/Src/CodeCoverageMethodElement.cs

816
src/AddIns/Analysis/CodeCoverage/Project/Src/CodeCoverageMethodElement.cs

@ -27,412 +27,412 @@ using System.Xml.Linq;
namespace ICSharpCode.CodeCoverage namespace ICSharpCode.CodeCoverage
{ {
public class CodeCoverageMethodElement public class CodeCoverageMethodElement
{ {
XElement element; XElement element;
CodeCoverageResults parent; CodeCoverageResults parent;
public CodeCoverageMethodElement(XElement element, CodeCoverageResults parent) public CodeCoverageMethodElement(XElement element, CodeCoverageResults parent)
{ {
this.parent = parent; this.parent = parent;
this.element = element; this.element = element;
this.SequencePoints = new List<CodeCoverageSequencePoint>(); this.SequencePoints = new List<CodeCoverageSequencePoint>();
this.BranchPoints = new List<CodeCoverageBranchPoint>(); this.BranchPoints = new List<CodeCoverageBranchPoint>();
Init(); Init();
} }
private static string cacheFileName = String.Empty; private static string cacheFileName = String.Empty;
private static CodeCoverageStringTextSource cacheDocument = null; private static CodeCoverageStringTextSource cacheDocument = null;
public string FileID { get; private set; } public string FileID { get; private set; }
public string FileName { get; private set; } public string FileName { get; private set; }
public bool IsVisited { get; private set; } public bool IsVisited { get; private set; }
public int CyclomaticComplexity { get; private set; } public int CyclomaticComplexity { get; private set; }
public decimal SequenceCoverage { get; private set; } public decimal SequenceCoverage { get; private set; }
public int SequencePointsCount { get; private set; } public int SequencePointsCount { get; private set; }
public decimal BranchCoverage { get; private set; } public decimal BranchCoverage { get; private set; }
public Tuple<int,int> BranchCoverageRatio { get; private set; } public Tuple<int,int> BranchCoverageRatio { get; private set; }
public bool IsConstructor { get; private set; } public bool IsConstructor { get; private set; }
public bool IsStatic { get; private set; } public bool IsStatic { get; private set; }
public List<CodeCoverageSequencePoint> SequencePoints { get; private set; } public List<CodeCoverageSequencePoint> SequencePoints { get; private set; }
public CodeCoverageSequencePoint BodyStartSP { get; private set; } public CodeCoverageSequencePoint BodyStartSP { get; private set; }
public CodeCoverageSequencePoint BodyFinalSP { get; private set; } public CodeCoverageSequencePoint BodyFinalSP { get; private set; }
public List<CodeCoverageBranchPoint> BranchPoints { get; private set; } public List<CodeCoverageBranchPoint> BranchPoints { get; private set; }
public bool IsGetter { get; private set; } public bool IsGetter { get; private set; }
public bool IsSetter { get; private set; } public bool IsSetter { get; private set; }
public string MethodName { get; private set; } public string MethodName { get; private set; }
public bool IsProperty { public bool IsProperty {
get { return IsGetter || IsSetter; } get { return IsGetter || IsSetter; }
} }
void Init() void Init()
{ {
MethodName = GetMethodName(); MethodName = GetMethodName();
IsGetter = GetBooleanAttributeValue("isGetter"); IsGetter = GetBooleanAttributeValue("isGetter");
IsSetter = GetBooleanAttributeValue("isSetter"); IsSetter = GetBooleanAttributeValue("isSetter");
this.FileID = GetFileRef(); this.FileID = GetFileRef();
this.FileName = String.Empty; this.FileName = String.Empty;
if (!String.IsNullOrEmpty(this.FileID)) { if (!String.IsNullOrEmpty(this.FileID)) {
this.FileName = parent.GetFileName(this.FileID); this.FileName = parent.GetFileName(this.FileID);
if ( File.Exists(this.FileName) ) { if ( File.Exists(this.FileName) ) {
if (cacheFileName != this.FileName) { if (cacheFileName != this.FileName) {
cacheFileName = this.FileName; cacheFileName = this.FileName;
cacheDocument = null; cacheDocument = null;
try { try {
using (Stream stream = new FileStream(this.FileName, FileMode.Open, FileAccess.Read)) { using (Stream stream = new FileStream(this.FileName, FileMode.Open, FileAccess.Read)) {
try { try {
stream.Position = 0; stream.Position = 0;
string textSource = ICSharpCode.AvalonEdit.Utils.FileReader.ReadFileContent(stream, Encoding.Default); string textSource = ICSharpCode.AvalonEdit.Utils.FileReader.ReadFileContent(stream, Encoding.Default);
cacheDocument = new CodeCoverageStringTextSource(textSource); cacheDocument = new CodeCoverageStringTextSource(textSource);
} catch {} } catch {}
} }
} catch {} } catch {}
} }
} }
} }
this.IsVisited = this.GetBooleanAttributeValue("visited"); this.IsVisited = this.GetBooleanAttributeValue("visited");
this.CyclomaticComplexity = (int)this.GetDecimalAttributeValue("cyclomaticComplexity"); this.CyclomaticComplexity = (int)this.GetDecimalAttributeValue("cyclomaticComplexity");
this.SequencePointsCount = this.GetSequencePointsCount(); this.SequencePointsCount = this.GetSequencePointsCount();
this.SequenceCoverage = (int)this.GetDecimalAttributeValue("sequenceCoverage"); this.SequenceCoverage = (int)this.GetDecimalAttributeValue("sequenceCoverage");
this.IsConstructor = this.GetBooleanAttributeValue("isConstructor"); this.IsConstructor = this.GetBooleanAttributeValue("isConstructor");
this.IsStatic = this.GetBooleanAttributeValue("isStatic"); this.IsStatic = this.GetBooleanAttributeValue("isStatic");
if ( !String.IsNullOrEmpty( this.FileID ) ) { if ( !String.IsNullOrEmpty( this.FileID ) ) {
this.SequencePoints = this.GetSequencePoints(); this.SequencePoints = this.GetSequencePoints();
// SP's are originaly ordered by CIL offset // SP's are originaly ordered by CIL offset
// but ccrewrite can move offset of // but ccrewrite can move offset of
// Contract.Requires before method signature SP { and // Contract.Requires before method signature SP { and
// Contract.Ensures after method closing SP } // Contract.Ensures after method closing SP }
// So sort SP's back by line/column // So sort SP's back by line/column
this.SequencePoints.OrderBy(item => item.Line).OrderBy(item => item.Column); this.SequencePoints.OrderBy(item => item.Line).OrderBy(item => item.Column);
this.BodyStartSP = getBodyStartSP(this.SequencePoints); this.BodyStartSP = getBodyStartSP(this.SequencePoints);
this.BodyFinalSP = getBodyFinalSP(this.SequencePoints); this.BodyFinalSP = getBodyFinalSP(this.SequencePoints);
this.SequencePoints = this.FilterSequencePoints(this.SequencePoints); this.SequencePoints = this.FilterSequencePoints(this.SequencePoints);
this.BranchPoints = this.GetBranchPoints(); this.BranchPoints = this.GetBranchPoints();
this.BranchCoverageRatio = this.GetBranchRatio(); this.BranchCoverageRatio = this.GetBranchRatio();
this.BranchCoverage = this.GetBranchCoverage(); this.BranchCoverage = this.GetBranchCoverage();
} }
} }
List<CodeCoverageSequencePoint> GetSequencePoints() { List<CodeCoverageSequencePoint> GetSequencePoints() {
List<CodeCoverageSequencePoint> sps = new List<CodeCoverageSequencePoint>(); List<CodeCoverageSequencePoint> sps = new List<CodeCoverageSequencePoint>();
var xSPoints = this.element var xSPoints = this.element
.Elements("SequencePoints") .Elements("SequencePoints")
.Elements("SequencePoint"); .Elements("SequencePoint");
foreach (XElement xSPoint in xSPoints) { foreach (XElement xSPoint in xSPoints) {
CodeCoverageSequencePoint sp = new CodeCoverageSequencePoint(); CodeCoverageSequencePoint sp = new CodeCoverageSequencePoint();
sp.FileID = this.FileID; sp.FileID = this.FileID;
sp.Document = this.FileName; sp.Document = this.FileName;
sp.Line = (int)GetDecimalAttributeValue(xSPoint.Attribute("sl")); sp.Line = (int)GetDecimalAttributeValue(xSPoint.Attribute("sl"));
sp.EndLine = (int)GetDecimalAttributeValue(xSPoint.Attribute("el")); sp.EndLine = (int)GetDecimalAttributeValue(xSPoint.Attribute("el"));
sp.Column = (int)GetDecimalAttributeValue(xSPoint.Attribute("sc")); sp.Column = (int)GetDecimalAttributeValue(xSPoint.Attribute("sc"));
sp.EndColumn = (int)GetDecimalAttributeValue(xSPoint.Attribute("ec")); sp.EndColumn = (int)GetDecimalAttributeValue(xSPoint.Attribute("ec"));
sp.VisitCount = (int)GetDecimalAttributeValue(xSPoint.Attribute("vc")); sp.VisitCount = (int)GetDecimalAttributeValue(xSPoint.Attribute("vc"));
if (cacheFileName == sp.Document && cacheDocument != null) { if (cacheFileName == sp.Document && cacheDocument != null) {
sp.Content = cacheDocument.GetText(sp); sp.Content = cacheDocument.GetText(sp);
if (sp.Line != sp.EndLine) { if (sp.Line != sp.EndLine) {
sp.Content = Regex.Replace (sp.Content, @"\s+", " "); sp.Content = Regex.Replace (sp.Content, @"\s+", " ");
} }
sp.Length = Regex.Replace (sp.Content, @"\s", "").Length; // ignore white-space for coverage% sp.Length = Regex.Replace (sp.Content, @"\s", "").Length; // ignore white-space for coverage%
} else { } else {
sp.Content = String.Empty; sp.Content = String.Empty;
sp.Length = 0; sp.Length = 0;
} }
sp.Offset = (int)GetDecimalAttributeValue(xSPoint.Attribute("offset")); sp.Offset = (int)GetDecimalAttributeValue(xSPoint.Attribute("offset"));
sp.BranchCoverage = true; sp.BranchCoverage = true;
sps.Add(sp); sps.Add(sp);
} }
return sps; return sps;
} }
// Find method-body start SequencePoint "{" // Find method-body start SequencePoint "{"
// Sequence points are ordered by Line/Column // Sequence points are ordered by Line/Column
// Cannot just get first one because of ccrewrite&ContractClassFor // Cannot just get first one because of ccrewrite&ContractClassFor
// For same reason must abandon constructor method signature SP // For same reason must abandon constructor method signature SP
public static CodeCoverageSequencePoint getBodyStartSP(IEnumerable<CodeCoverageSequencePoint> sPoints) { public static CodeCoverageSequencePoint getBodyStartSP(IEnumerable<CodeCoverageSequencePoint> sPoints) {
CodeCoverageSequencePoint startSeqPoint = null; CodeCoverageSequencePoint startSeqPoint = null;
foreach (CodeCoverageSequencePoint sPoint in sPoints) { foreach (CodeCoverageSequencePoint sPoint in sPoints) {
if ( sPoint.Content == "{") { if ( sPoint.Content == "{") {
startSeqPoint = sPoint; startSeqPoint = sPoint;
break; break;
} }
} }
return startSeqPoint; return startSeqPoint;
} }
// Find method-body final SequencePoint "}" // Find method-body final SequencePoint "}"
// Sequence points are ordered by Line/Column // Sequence points are ordered by Line/Column
public static CodeCoverageSequencePoint getBodyFinalSP(IEnumerable<CodeCoverageSequencePoint> sps) { public static CodeCoverageSequencePoint getBodyFinalSP(IEnumerable<CodeCoverageSequencePoint> sps) {
CodeCoverageSequencePoint finalSeqPoint = null; CodeCoverageSequencePoint finalSeqPoint = null;
foreach (CodeCoverageSequencePoint sp in Enumerable.Reverse(sps)) { foreach (CodeCoverageSequencePoint sp in Enumerable.Reverse(sps)) {
if ( sp.Content == "}") { if ( sp.Content == "}") {
if (finalSeqPoint == null) { if (finalSeqPoint == null) {
finalSeqPoint = sp; finalSeqPoint = sp;
} }
// check for ccrewrite duplicate // check for ccrewrite duplicate
else if (sp.Line == finalSeqPoint.Line && else if (sp.Line == finalSeqPoint.Line &&
sp.Column == finalSeqPoint.Column && sp.Column == finalSeqPoint.Column &&
sp.EndLine == finalSeqPoint.EndLine && sp.EndLine == finalSeqPoint.EndLine &&
sp.EndColumn == finalSeqPoint.EndColumn && sp.EndColumn == finalSeqPoint.EndColumn &&
sp.Offset < finalSeqPoint.Offset) { sp.Offset < finalSeqPoint.Offset) {
finalSeqPoint = sp; finalSeqPoint = sp;
} }
else if (sp.Line < finalSeqPoint.Line) { else if (sp.Line < finalSeqPoint.Line) {
break; break;
} }
} }
} }
return finalSeqPoint; return finalSeqPoint;
} }
List<CodeCoverageSequencePoint> FilterSequencePoints(List<CodeCoverageSequencePoint> sps) { List<CodeCoverageSequencePoint> FilterSequencePoints(List<CodeCoverageSequencePoint> sps) {
List<CodeCoverageSequencePoint> returnList = sps; List<CodeCoverageSequencePoint> returnList = sps;
if (sps.Count > 2 && if (sps.Count > 2 &&
this.BodyStartSP != null && this.BodyStartSP != null &&
this.BodyFinalSP != null ) { this.BodyFinalSP != null ) {
// After ccrewrite ContractClass/ContractClassFor // After ccrewrite ContractClass/ContractClassFor
// sequence point(s) from another file/class/method // sequence point(s) from another file/class/method
// is inserted into this method sequence points // is inserted into this method sequence points
// //
// To remove alien sequence points, all sequence points on lines // To remove alien sequence points, all sequence points on lines
// before method signature and after end-brackets xxx{} are removed // before method signature and after end-brackets xxx{} are removed
// If ContractClassFor is in another file but interleaves this method lines // If ContractClassFor is in another file but interleaves this method lines
// then, afaik, not much can be done to remove inserted alien SP's // then, afaik, not much can be done to remove inserted alien SP's
List<CodeCoverageSequencePoint> selected = new List<CodeCoverageSequencePoint>(); List<CodeCoverageSequencePoint> selected = new List<CodeCoverageSequencePoint>();
foreach (var point in sps) { foreach (var point in sps) {
if ( if (
(point.Line > BodyStartSP.Line || (point.Line == BodyStartSP.Line && point.Column >= BodyStartSP.Column)) && (point.Line > BodyStartSP.Line || (point.Line == BodyStartSP.Line && point.Column >= BodyStartSP.Column)) &&
(point.Line < BodyFinalSP.Line || (point.Line == BodyFinalSP.Line && point.Column < BodyFinalSP.Column)) (point.Line < BodyFinalSP.Line || (point.Line == BodyFinalSP.Line && point.Column < BodyFinalSP.Column))
) { ) {
selected.Add (point); selected.Add (point);
} }
// After ccrewrite ContractClass/ContractClassFor // After ccrewrite ContractClass/ContractClassFor
// duplicate method end-sequence-point (}) is added // duplicate method end-sequence-point (}) is added
// //
// Add first finalSP (can be a duplicate) // Add first finalSP (can be a duplicate)
// Note: IL.Offset of second duplicate finalSP will // Note: IL.Offset of second duplicate finalSP will
// extend branch coverage outside method-end "}", // extend branch coverage outside method-end "}",
// and that can lead to wrong branch coverage display! // and that can lead to wrong branch coverage display!
if (object.ReferenceEquals (point, this.BodyFinalSP)) { if (object.ReferenceEquals (point, this.BodyFinalSP)) {
selected.Add (point); selected.Add (point);
} }
} }
returnList = selected; returnList = selected;
} }
return returnList; return returnList;
} }
int GetSequencePointsCount() { int GetSequencePointsCount() {
XElement summary = this.element.Element("Summary"); XElement summary = this.element.Element("Summary");
if ( summary != null ) { if ( summary != null ) {
XAttribute nsp = summary.Attribute("numSequencePoints"); XAttribute nsp = summary.Attribute("numSequencePoints");
if ( nsp != null ) { if ( nsp != null ) {
return (int)GetDecimalAttributeValue( nsp ); return (int)GetDecimalAttributeValue( nsp );
} }
} }
return 0; return 0;
} }
List<CodeCoverageBranchPoint> GetBranchPoints() { List<CodeCoverageBranchPoint> GetBranchPoints() {
// get all BranchPoints // get all BranchPoints
List<CodeCoverageBranchPoint> bps = new List<CodeCoverageBranchPoint>(); List<CodeCoverageBranchPoint> bps = new List<CodeCoverageBranchPoint>();
var xBPoints = this.element var xBPoints = this.element
.Elements("BranchPoints") .Elements("BranchPoints")
.Elements("BranchPoint"); .Elements("BranchPoint");
foreach (XElement xBPoint in xBPoints) { foreach (XElement xBPoint in xBPoints) {
CodeCoverageBranchPoint bp = new CodeCoverageBranchPoint(); CodeCoverageBranchPoint bp = new CodeCoverageBranchPoint();
bp.VisitCount = (int)GetDecimalAttributeValue(xBPoint.Attribute("vc")); bp.VisitCount = (int)GetDecimalAttributeValue(xBPoint.Attribute("vc"));
bp.Offset = (int)GetDecimalAttributeValue(xBPoint.Attribute("offset")); bp.Offset = (int)GetDecimalAttributeValue(xBPoint.Attribute("offset"));
bp.Path = (int)GetDecimalAttributeValue(xBPoint.Attribute("path")); bp.Path = (int)GetDecimalAttributeValue(xBPoint.Attribute("path"));
bp.OffsetEnd = (int)GetDecimalAttributeValue(xBPoint.Attribute("offsetend")); bp.OffsetEnd = (int)GetDecimalAttributeValue(xBPoint.Attribute("offsetend"));
bps.Add(bp); bps.Add(bp);
} }
return bps; return bps;
} }
Tuple<int,int> GetBranchRatio () { Tuple<int,int> GetBranchRatio () {
// goal: Get branch ratio and exclude (rewriten) Code Contracts branches // goal: Get branch ratio and exclude (rewriten) Code Contracts branches
if ( this.BranchPoints == null if ( this.BranchPoints == null
|| this.BranchPoints.Count() == 0 || this.BranchPoints.Count() == 0
|| this.SequencePoints == null || this.SequencePoints == null
|| this.SequencePoints.Count == 0 || this.SequencePoints.Count == 0
) )
{ {
return null; return null;
} }
// This sequence point offset is used to skip CCRewrite(n) BranchPoint's (Requires) // This sequence point offset is used to skip CCRewrite(n) BranchPoint's (Requires)
// and '{' branches at static methods // and '{' branches at static methods
if (this.BodyStartSP == null) { return null; } // empty body if (this.BodyStartSP == null) { return null; } // empty body
// This sequence point offset is used to skip CCRewrite(n) BranchPoint's (Ensures) // This sequence point offset is used to skip CCRewrite(n) BranchPoint's (Ensures)
if (this.BodyFinalSP == null) { return null; } // empty body if (this.BodyFinalSP == null) { return null; } // empty body
// Connect Sequence & Branches // Connect Sequence & Branches
IEnumerator<CodeCoverageSequencePoint> SPEnumerator = this.SequencePoints.GetEnumerator(); IEnumerator<CodeCoverageSequencePoint> SPEnumerator = this.SequencePoints.GetEnumerator();
CodeCoverageSequencePoint currSeqPoint = BodyStartSP; CodeCoverageSequencePoint currSeqPoint = BodyStartSP;
int nextSeqPointOffset = BodyStartSP.Offset; int nextSeqPointOffset = BodyStartSP.Offset;
foreach (var bp in this.BranchPoints) { foreach (var bp in this.BranchPoints) {
// ignore branches outside of method body offset range // ignore branches outside of method body offset range
if (bp.Offset < BodyStartSP.Offset) if (bp.Offset < BodyStartSP.Offset)
continue; continue;
if (bp.Offset > BodyFinalSP.Offset) if (bp.Offset > BodyFinalSP.Offset)
break; break;
// Sync with SequencePoint // Sync with SequencePoint
while ( nextSeqPointOffset < bp.Offset ) { while ( nextSeqPointOffset < bp.Offset ) {
currSeqPoint = SPEnumerator.Current; currSeqPoint = SPEnumerator.Current;
if ( SPEnumerator.MoveNext() ) { if ( SPEnumerator.MoveNext() ) {
nextSeqPointOffset = SPEnumerator.Current.Offset; nextSeqPointOffset = SPEnumerator.Current.Offset;
} else { } else {
nextSeqPointOffset = int.MaxValue; nextSeqPointOffset = int.MaxValue;
} }
} }
if (currSeqPoint.Branches == null) { if (currSeqPoint.Branches == null) {
currSeqPoint.Branches = new List<CodeCoverageBranchPoint>(); currSeqPoint.Branches = new List<CodeCoverageBranchPoint>();
} }
// Add Branch to Branches // Add Branch to Branches
currSeqPoint.Branches.Add(bp); currSeqPoint.Branches.Add(bp);
} }
// Merge sp.Branches on exit-offset // Merge sp.Branches on exit-offset
// Calculate Method Branch coverage // Calculate Method Branch coverage
int totalBranchVisit = 0; int totalBranchVisit = 0;
int totalBranchCount = 0; int totalBranchCount = 0;
int pointBranchVisit = 0; int pointBranchVisit = 0;
int pointBranchCount = 0; int pointBranchCount = 0;
Dictionary<int, CodeCoverageBranchPoint> bpExits = new Dictionary<int, CodeCoverageBranchPoint>(); Dictionary<int, CodeCoverageBranchPoint> bpExits = new Dictionary<int, CodeCoverageBranchPoint>();
foreach (var sp in this.SequencePoints) { foreach (var sp in this.SequencePoints) {
// SequencePoint covered & has branches? // SequencePoint covered & has branches?
if (sp.VisitCount != 0 && sp.Branches != null) { if (sp.VisitCount != 0 && sp.Branches != null) {
// 1) Generated "in" code for IEnumerables contains hidden "try/catch/finally" branches that // 1) Generated "in" code for IEnumerables contains hidden "try/catch/finally" branches that
// one do not want or cannot cover by test-case because is handled earlier at same method. // one do not want or cannot cover by test-case because is handled earlier at same method.
// ie: NullReferenceException in foreach loop is pre-handled at method entry, ie. by Contract.Require(items!=null) // ie: NullReferenceException in foreach loop is pre-handled at method entry, ie. by Contract.Require(items!=null)
// 2) Branches within sequence points "{" and "}" are not source branches but compiler generated branches // 2) Branches within sequence points "{" and "}" are not source branches but compiler generated branches
// ie: static methods start sequence point "{" contains compiler generated branches // ie: static methods start sequence point "{" contains compiler generated branches
// 3) Exclude Contract class (EnsuresOnThrow/Assert/Assume is inside method body) // 3) Exclude Contract class (EnsuresOnThrow/Assert/Assume is inside method body)
// 4) Exclude NUnit Assert(.Throws) class // 4) Exclude NUnit Assert(.Throws) class
if (sp.Content == "in" || sp.Content == "{" || sp.Content == "}" || if (sp.Content == "in" || sp.Content == "{" || sp.Content == "}" ||
sp.Content.StartsWith("Assert.") || sp.Content.StartsWith("Assert.") ||
sp.Content.StartsWith("Assert ") || sp.Content.StartsWith("Assert ") ||
sp.Content.StartsWith("Contract.") || sp.Content.StartsWith("Contract.") ||
sp.Content.StartsWith("Contract ") sp.Content.StartsWith("Contract ")
) { ) {
sp.Branches = null; sp.Branches = null;
continue; // skip continue; // skip
} }
// Merge sp.Branches on OffsetEnd using bpExits key // Merge sp.Branches on OffsetEnd using bpExits key
bpExits.Clear(); bpExits.Clear();
foreach (var bp in sp.Branches) { foreach (var bp in sp.Branches) {
if (!bpExits.ContainsKey(bp.OffsetEnd)) { if (!bpExits.ContainsKey(bp.OffsetEnd)) {
bpExits[bp.OffsetEnd] = bp; // insert branch bpExits[bp.OffsetEnd] = bp; // insert branch
} else { } else {
bpExits[bp.OffsetEnd].VisitCount += bp.VisitCount; // update branch bpExits[bp.OffsetEnd].VisitCount += bp.VisitCount; // update branch
} }
} }
// Compute branch coverage // Compute branch coverage
pointBranchVisit = 0; pointBranchVisit = 0;
pointBranchCount = 0; pointBranchCount = 0;
foreach (var bp in bpExits.Values) { foreach (var bp in bpExits.Values) {
pointBranchVisit += bp.VisitCount == 0? 0 : 1 ; pointBranchVisit += bp.VisitCount == 0? 0 : 1 ;
pointBranchCount += 1; pointBranchCount += 1;
} }
// Not full coverage? // Not full coverage?
if (pointBranchVisit != pointBranchCount) { if (pointBranchVisit != pointBranchCount) {
sp.BranchCoverage = false; // => part-covered sp.BranchCoverage = false; // => part-covered
} }
totalBranchVisit += pointBranchVisit; totalBranchVisit += pointBranchVisit;
totalBranchCount += pointBranchCount; totalBranchCount += pointBranchCount;
} }
if (sp.Branches != null) if (sp.Branches != null)
sp.Branches = null; // release memory sp.Branches = null; // release memory
} }
return (totalBranchCount!=0) ? new Tuple<int,int>(totalBranchVisit,totalBranchCount) : null; return (totalBranchCount!=0) ? new Tuple<int,int>(totalBranchVisit,totalBranchCount) : null;
} }
decimal GetBranchCoverage () { decimal GetBranchCoverage () {
return this.BranchCoverageRatio == null ? 0m : ((decimal)(this.BranchCoverageRatio.Item1*100))/((decimal)this.BranchCoverageRatio.Item2); return this.BranchCoverageRatio == null ? 0m : ((decimal)(this.BranchCoverageRatio.Item1*100))/((decimal)this.BranchCoverageRatio.Item2);
} }
decimal GetDecimalAttributeValue(string name) decimal GetDecimalAttributeValue(string name)
{ {
return GetDecimalAttributeValue(element.Attribute(name)); return GetDecimalAttributeValue(element.Attribute(name));
} }
decimal GetDecimalAttributeValue(XAttribute attribute) decimal GetDecimalAttributeValue(XAttribute attribute)
{ {
if (attribute != null) { if (attribute != null) {
decimal value = 0; decimal value = 0;
if (Decimal.TryParse(attribute.Value, out value)) { if (Decimal.TryParse(attribute.Value, out value)) {
return value; return value;
} }
} }
return 0; return 0;
} }
bool GetBooleanAttributeValue(string name) bool GetBooleanAttributeValue(string name)
{ {
return GetBooleanAttributeValue(element.Attribute(name)); return GetBooleanAttributeValue(element.Attribute(name));
} }
bool GetBooleanAttributeValue(XAttribute attribute) bool GetBooleanAttributeValue(XAttribute attribute)
{ {
if (attribute != null) { if (attribute != null) {
bool value = false; bool value = false;
if (Boolean.TryParse(attribute.Value, out value)) { if (Boolean.TryParse(attribute.Value, out value)) {
return value; return value;
} }
} }
return false; return false;
} }
string GetFileRef() { string GetFileRef() {
XElement fileId = element.Element("FileRef"); XElement fileId = element.Element("FileRef");
if (fileId != null) { if (fileId != null) {
return fileId.Attribute("uid").Value; return fileId.Attribute("uid").Value;
} }
return String.Empty; return String.Empty;
} }
string GetMethodName() string GetMethodName()
{ {
XElement nameElement = element.Element("Name"); XElement nameElement = element.Element("Name");
if (nameElement != null) { if (nameElement != null) {
return GetMethodName(nameElement.Value); return GetMethodName(nameElement.Value);
} }
return String.Empty; return String.Empty;
} }
string GetMethodName(string methodSignature) string GetMethodName(string methodSignature)
{ {
int startIndex = methodSignature.IndexOf("::"); int startIndex = methodSignature.IndexOf("::");
int endIndex = methodSignature.IndexOf('(', startIndex); int endIndex = methodSignature.IndexOf('(', startIndex);
return methodSignature return methodSignature
.Substring(startIndex, endIndex - startIndex) .Substring(startIndex, endIndex - startIndex)
.Substring(2); .Substring(2);
} }
} }
} }

Loading…
Cancel
Save