|
|
|
@ -92,7 +92,7 @@ namespace ICSharpCode.CodeCoverage
@@ -92,7 +92,7 @@ namespace ICSharpCode.CodeCoverage
|
|
|
|
|
if (results != null) { |
|
|
|
|
this.FileName = results.GetFileName(this.FileID); |
|
|
|
|
try { |
|
|
|
|
this.FileNameExt = Path.GetExtension(this.FileName); |
|
|
|
|
this.FileNameExt = Path.GetExtension(this.FileName).ToLowerInvariant(); |
|
|
|
|
} |
|
|
|
|
catch {} |
|
|
|
|
if (cacheFileName != this.FileName) { |
|
|
|
@ -226,14 +226,19 @@ namespace ICSharpCode.CodeCoverage
@@ -226,14 +226,19 @@ namespace ICSharpCode.CodeCoverage
|
|
|
|
|
// -> this method SP with lowest Line/Column
|
|
|
|
|
void getBodyStartSP() { |
|
|
|
|
if (this.SequencePoints.Count != 0) { |
|
|
|
|
foreach (CodeCoverageSequencePoint sp in this.SequencePoints) { |
|
|
|
|
if (sp.FileID != this.FileID) continue; |
|
|
|
|
if (this.BodyStartSP == null || (sp.Line < this.BodyStartSP.Line) || |
|
|
|
|
(sp.Line == this.BodyStartSP.Line && sp.Column < this.BodyStartSP.Column) |
|
|
|
|
) { |
|
|
|
|
this.BodyStartSP = sp; |
|
|
|
|
if (this.FileNameExt == ".cs") { |
|
|
|
|
foreach (CodeCoverageSequencePoint sp in this.SequencePoints) { |
|
|
|
|
if (sp.FileID != this.FileID) continue; |
|
|
|
|
if (this.BodyStartSP == null || (sp.Line < this.BodyStartSP.Line) || |
|
|
|
|
(sp.Line == this.BodyStartSP.Line && sp.Column < this.BodyStartSP.Column) |
|
|
|
|
) { |
|
|
|
|
this.BodyStartSP = sp; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
this.BodyStartSP = this.SequencePoints.First(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -242,29 +247,34 @@ namespace ICSharpCode.CodeCoverage
@@ -242,29 +247,34 @@ namespace ICSharpCode.CodeCoverage
|
|
|
|
|
// and lowest Offset (when duplicated bw ccrewrite)
|
|
|
|
|
void getBodyFinalSP() { |
|
|
|
|
if (this.SequencePoints.Count != 0) { |
|
|
|
|
for (int i = this.SequencePoints.Count-1; i > 0; i--) { |
|
|
|
|
var sp = this.SequencePoints[i]; |
|
|
|
|
if (sp.FileID != this.FileID) continue; |
|
|
|
|
if (sp.Content != "}") continue; |
|
|
|
|
if (this.BodyFinalSP == null || (sp.Line > this.BodyFinalSP.Line) || |
|
|
|
|
(sp.Line == this.BodyFinalSP.Line && sp.Column >= this.BodyFinalSP.Column) |
|
|
|
|
) { |
|
|
|
|
// ccrewrite ContractClass/ContractClassFor
|
|
|
|
|
// adds duplicate method end-sequence-point "}"
|
|
|
|
|
//
|
|
|
|
|
// Take duplicate BodyFinalSP with lower Offset
|
|
|
|
|
// Because IL.Offset of second duplicate
|
|
|
|
|
// will extend branch coverage of this method
|
|
|
|
|
// by coverage of ContractClassFor inserted SequencePoint!
|
|
|
|
|
if (this.BodyFinalSP != null && |
|
|
|
|
sp.Line == this.BodyFinalSP.Line && |
|
|
|
|
sp.Column == this.BodyFinalSP.Column && |
|
|
|
|
sp.Offset < this.BodyFinalSP.Offset) { |
|
|
|
|
this.SequencePoints.Remove(this.BodyFinalSP); // remove duplicate
|
|
|
|
|
if (this.FileNameExt == ".cs") { |
|
|
|
|
for (int i = this.SequencePoints.Count-1; i > 0; i--) { |
|
|
|
|
var sp = this.SequencePoints[i]; |
|
|
|
|
if (sp.FileID != this.FileID) continue; |
|
|
|
|
if (sp.Content != "}") continue; |
|
|
|
|
if (this.BodyFinalSP == null || (sp.Line > this.BodyFinalSP.Line) || |
|
|
|
|
(sp.Line == this.BodyFinalSP.Line && sp.Column >= this.BodyFinalSP.Column) |
|
|
|
|
) { |
|
|
|
|
// ccrewrite ContractClass/ContractClassFor
|
|
|
|
|
// adds duplicate method end-sequence-point "}"
|
|
|
|
|
//
|
|
|
|
|
// Take duplicate BodyFinalSP with lower Offset
|
|
|
|
|
// Because IL.Offset of second duplicate
|
|
|
|
|
// will extend branch coverage of this method
|
|
|
|
|
// by coverage of ContractClassFor inserted SequencePoint!
|
|
|
|
|
if (this.BodyFinalSP != null && |
|
|
|
|
sp.Line == this.BodyFinalSP.Line && |
|
|
|
|
sp.Column == this.BodyFinalSP.Column && |
|
|
|
|
sp.Offset < this.BodyFinalSP.Offset) { |
|
|
|
|
this.SequencePoints.Remove(this.BodyFinalSP); // remove duplicate
|
|
|
|
|
} |
|
|
|
|
this.BodyFinalSP = sp; |
|
|
|
|
} |
|
|
|
|
this.BodyFinalSP = sp; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
this.BodyFinalSP = this.SequencePoints.Last(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -279,6 +289,9 @@ namespace ICSharpCode.CodeCoverage
@@ -279,6 +289,9 @@ namespace ICSharpCode.CodeCoverage
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const string @assert = "Assert"; |
|
|
|
|
const string @contract = "Contract"; |
|
|
|
|
|
|
|
|
|
void GetBranchRatio () { |
|
|
|
|
|
|
|
|
|
this.BranchCoverageRatio = null; |
|
|
|
@ -301,16 +314,17 @@ namespace ICSharpCode.CodeCoverage
@@ -301,16 +314,17 @@ namespace ICSharpCode.CodeCoverage
|
|
|
|
|
// SequencePoint is visited and belongs to this method?
|
|
|
|
|
if (sp.VisitCount != 0 && sp.FileID == this.FileID) { |
|
|
|
|
|
|
|
|
|
// Don't want branch coverage of ccrewrite(n)
|
|
|
|
|
// SequencePoint's with offset before and after method body
|
|
|
|
|
if (sp.Offset < BodyStartSP.Offset || |
|
|
|
|
sp.Offset > BodyFinalSP.Offset) { |
|
|
|
|
sp.BranchCoverage = true; |
|
|
|
|
continue; // skip
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (this.FileNameExt == ".cs") { |
|
|
|
|
// 0) Only for C#
|
|
|
|
|
// Only for C#
|
|
|
|
|
|
|
|
|
|
// Don't want branch coverage of ccrewrite(n)
|
|
|
|
|
// SequencePoint(s) with offset before and after method body
|
|
|
|
|
if (sp.Offset < BodyStartSP.Offset || |
|
|
|
|
sp.Offset > BodyFinalSP.Offset) { |
|
|
|
|
sp.BranchCoverage = true; |
|
|
|
|
continue; // skip
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 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.
|
|
|
|
|
// ie: NullReferenceException in foreach loop is pre-handled at method entry, ie. by Contract.Require(items!=null)
|
|
|
|
@ -318,13 +332,11 @@ namespace ICSharpCode.CodeCoverage
@@ -318,13 +332,11 @@ namespace ICSharpCode.CodeCoverage
|
|
|
|
|
// ie: static methods start sequence point "{" contains compiler generated branches
|
|
|
|
|
// 3) Exclude Contract class (EnsuresOnThrow/Assert/Assume is inside method body)
|
|
|
|
|
// 4) Exclude NUnit Assert(.Throws) class
|
|
|
|
|
const string assert = "Assert"; |
|
|
|
|
const string contract = "Contract"; |
|
|
|
|
if (sp.Content == "in" || sp.Content == "{" || sp.Content == "}" || |
|
|
|
|
sp.Content.StartsWith(assert + ".", StringComparison.Ordinal) || |
|
|
|
|
sp.Content.StartsWith(assert + " ", StringComparison.Ordinal) || |
|
|
|
|
sp.Content.StartsWith(contract + ".", StringComparison.Ordinal) || |
|
|
|
|
sp.Content.StartsWith(contract + " ", StringComparison.Ordinal) |
|
|
|
|
sp.Content.StartsWith(@assert + ".", StringComparison.Ordinal) || |
|
|
|
|
sp.Content.StartsWith(@assert + " ", StringComparison.Ordinal) || |
|
|
|
|
sp.Content.StartsWith(@contract + ".", StringComparison.Ordinal) || |
|
|
|
|
sp.Content.StartsWith(@contract + " ", StringComparison.Ordinal) |
|
|
|
|
) { |
|
|
|
|
sp.BranchCoverage = true; |
|
|
|
|
continue; // skip
|
|
|
|
|