From a397b9e97fb529ba5005d6fc2d2c89ad1f5a6894 Mon Sep 17 00:00:00 2001 From: Dragan Date: Mon, 26 May 2014 14:11:12 +0200 Subject: [PATCH 1/3] CodeCoverage: Apply C# filter only to .cs files --- .../Project/Src/CodeCoverageMethodElement.cs | 43 +++++++++++-------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/src/AddIns/Analysis/CodeCoverage/Project/Src/CodeCoverageMethodElement.cs b/src/AddIns/Analysis/CodeCoverage/Project/Src/CodeCoverageMethodElement.cs index 3b19dba9b2..36ed616511 100644 --- a/src/AddIns/Analysis/CodeCoverage/Project/Src/CodeCoverageMethodElement.cs +++ b/src/AddIns/Analysis/CodeCoverage/Project/Src/CodeCoverageMethodElement.cs @@ -58,6 +58,7 @@ namespace ICSharpCode.CodeCoverage public string FileID { get; private set; } public string FileName { get; private set; } + public string FileNameExt { get; private set; } public bool IsVisited { get; private set; } public int CyclomaticComplexity { get; private set; } public decimal SequenceCoverage { get; private set; } @@ -86,9 +87,14 @@ namespace ICSharpCode.CodeCoverage this.FileID = GetFileRef(); this.FileName = String.Empty; + this.FileNameExt = String.Empty; if (!String.IsNullOrEmpty(this.FileID)) { if (results != null) { this.FileName = results.GetFileName(this.FileID); + try { + this.FileNameExt = Path.GetExtension(this.FileName); + } + catch {} if (cacheFileName != this.FileName) { cacheFileName = this.FileName; cacheDocument = GetSource (cacheFileName); @@ -303,23 +309,26 @@ namespace ICSharpCode.CodeCoverage 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) - // 2) Branches within sequence points "{" and "}" are not source branches but compiler generated branches - // 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.BranchCoverage = true; - continue; // skip + if (this.FileNameExt == ".cs") { + // 0) Only for C# + // 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) + // 2) Branches within sequence points "{" and "}" are not source branches but compiler generated branches + // 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.BranchCoverage = true; + continue; // skip + } } totalBranchCount += sp.BranchExitsCount; From db31ee80d6f1d3db77b4a3e064fe1418815f4eb0 Mon Sep 17 00:00:00 2001 From: Dragan Date: Thu, 12 Jun 2014 09:13:11 +0200 Subject: [PATCH 2/3] CodeCoverage: Apply ccrewrite filter on C# only Apply Branch-Coverage Code-Contract ccrewrite filter only to C#(.cs) files --- .../Project/Src/CodeCoverageMethodElement.cs | 96 +++++++++++-------- 1 file changed, 54 insertions(+), 42 deletions(-) diff --git a/src/AddIns/Analysis/CodeCoverage/Project/Src/CodeCoverageMethodElement.cs b/src/AddIns/Analysis/CodeCoverage/Project/Src/CodeCoverageMethodElement.cs index 36ed616511..9f47b35148 100644 --- a/src/AddIns/Analysis/CodeCoverage/Project/Src/CodeCoverageMethodElement.cs +++ b/src/AddIns/Analysis/CodeCoverage/Project/Src/CodeCoverageMethodElement.cs @@ -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 // -> 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 // 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 return 0; } + const string @assert = "Assert"; + const string @contract = "Contract"; + void GetBranchRatio () { this.BranchCoverageRatio = null; @@ -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 // 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 From 97d65bd39970ac7385e9a80f3c69d964a389c79c Mon Sep 17 00:00:00 2001 From: ddur Date: Thu, 10 Dec 2015 23:24:55 +0100 Subject: [PATCH 3/3] Reveal compiler generated methods Some user methods (enumerators) are uncovered without compiler generated methods --- .../Project/Src/CodeCoverageClassTreeNode.cs | 13 +++++-------- .../Project/Src/CodeCoverageMethodsTreeNode.cs | 3 --- .../CodeCoverage/Project/Src/CodeCoverageResults.cs | 5 +---- 3 files changed, 6 insertions(+), 15 deletions(-) diff --git a/src/AddIns/Analysis/CodeCoverage/Project/Src/CodeCoverageClassTreeNode.cs b/src/AddIns/Analysis/CodeCoverage/Project/Src/CodeCoverageClassTreeNode.cs index ad70ea1695..0a26162419 100644 --- a/src/AddIns/Analysis/CodeCoverage/Project/Src/CodeCoverageClassTreeNode.cs +++ b/src/AddIns/Analysis/CodeCoverage/Project/Src/CodeCoverageClassTreeNode.cs @@ -66,14 +66,11 @@ namespace ICSharpCode.CodeCoverage // Add methods. CodeCoveragePropertyCollection properties = new CodeCoveragePropertyCollection(); foreach (CodeCoverageMethod method in Methods) { - // method name that is generated by compiler, contains "__" (double underscore) - if ( !method.Name.Contains("__") ) { - if (method.IsProperty) { - properties.Add(method); - } else { - CodeCoverageMethodTreeNode node = new CodeCoverageMethodTreeNode(method); - node.AddTo(this); - } + if (method.IsProperty) { + properties.Add(method); + } else { + CodeCoverageMethodTreeNode node = new CodeCoverageMethodTreeNode(method); + node.AddTo(this); } } diff --git a/src/AddIns/Analysis/CodeCoverage/Project/Src/CodeCoverageMethodsTreeNode.cs b/src/AddIns/Analysis/CodeCoverage/Project/Src/CodeCoverageMethodsTreeNode.cs index 590fe3f641..f371de8d14 100644 --- a/src/AddIns/Analysis/CodeCoverage/Project/Src/CodeCoverageMethodsTreeNode.cs +++ b/src/AddIns/Analysis/CodeCoverage/Project/Src/CodeCoverageMethodsTreeNode.cs @@ -41,9 +41,6 @@ namespace ICSharpCode.CodeCoverage decimal branchCoverage = 0; int branchCoverageCount = 0; foreach (CodeCoverageMethod method in methods) { - if (method.Name.Contains("__")) { - continue; - } visitedCodeLength += method.GetVisitedCodeLength(); unvisitedCodeLength += method.GetUnvisitedCodeLength(); if ( method.IsVisited ) { diff --git a/src/AddIns/Analysis/CodeCoverage/Project/Src/CodeCoverageResults.cs b/src/AddIns/Analysis/CodeCoverage/Project/Src/CodeCoverageResults.cs index e03986a8e6..7efddd2462 100644 --- a/src/AddIns/Analysis/CodeCoverage/Project/Src/CodeCoverageResults.cs +++ b/src/AddIns/Analysis/CodeCoverage/Project/Src/CodeCoverageResults.cs @@ -78,7 +78,6 @@ namespace ICSharpCode.CodeCoverage var classNames = assembly.Elements("Classes").Elements("Class").Where( c => - !c.Element("FullName").Value.Contains("__") && c.Attribute("skippedDueTo") == null).Select( c => c.Element("FullName").Value).Distinct().OrderBy(name => name); foreach (string className in classNames) { @@ -130,9 +129,7 @@ namespace ICSharpCode.CodeCoverage CodeCoverageMethod AddMethod(CodeCoverageModule module, string className, XElement reader) { var method = new CodeCoverageMethod(className, reader, this); - if (!method.Name.Contains("__")) { - module.Methods.Add(method); - } + module.Methods.Add(method); return method; }