Browse Source

Code Coverage: more refactoring,

Refactoring methods to less responsibility
pull/67/head
Dragan 12 years ago
parent
commit
a8dec47e2f
  1. 796
      src/AddIns/Analysis/CodeCoverage/Project/Src/CodeCoverageMethodElement.cs

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

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

Loading…
Cancel
Save