Browse Source

Merge remote-tracking branch 'origin/4.x'

pull/67/head
Dragan 12 years ago
parent
commit
34ed6848bc
  1. 2
      src/AddIns/Analysis/CodeCoverage/Project/Src/CodeCoverageBranchPoint.cs
  2. 131
      src/AddIns/Analysis/CodeCoverage/Project/Src/CodeCoverageMethodElement.cs
  3. 2
      src/AddIns/Analysis/CodeCoverage/Project/Src/CodeCoverageStringTextSource.cs

2
src/AddIns/Analysis/CodeCoverage/Project/Src/CodeCoverageBranchPoint.cs

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
// Copyright (c) https://github.com/ddur
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
// This code is distributed under the MIT license
using System;

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

@ -54,6 +54,8 @@ namespace ICSharpCode.CodeCoverage @@ -54,6 +54,8 @@ namespace ICSharpCode.CodeCoverage
public bool IsConstructor { get; private set; }
public bool IsStatic { get; private set; }
public List<CodeCoverageSequencePoint> SequencePoints { get; private set; }
public CodeCoverageSequencePoint BodyStartSP { get; private set; }
public CodeCoverageSequencePoint BodyFinalSP { get; private set; }
public List<CodeCoverageBranchPoint> BranchPoints { get; private set; }
public bool IsGetter { get; private set; }
@ -99,6 +101,9 @@ namespace ICSharpCode.CodeCoverage @@ -99,6 +101,9 @@ namespace ICSharpCode.CodeCoverage
this.IsStatic = this.GetBooleanAttributeValue("isStatic");
if ( !String.IsNullOrEmpty( this.FileID ) ) {
this.SequencePoints = this.GetSequencePoints();
this.BodyStartSP = getBodyStartSP(this.SequencePoints);
this.BodyFinalSP = getBodyFinalSP(this.SequencePoints);
this.SequencePoints = this.FilterSequencePoints(this.SequencePoints);
this.BranchPoints = this.GetBranchPoints();
this.BranchCoverageRatio = this.GetBranchRatio();
this.BranchCoverage = this.GetBranchCoverage();
@ -136,9 +141,95 @@ namespace ICSharpCode.CodeCoverage @@ -136,9 +141,95 @@ namespace ICSharpCode.CodeCoverage
sps.Add(sp);
}
// SP's are originaly ordered by CIL offset
// but ccrewrite can move offset of
// Contract.Requires before method signature SP (xxx{) and
// Contract.Ensures after method closing SP (})
// So sort SP's back by line/column
sps.OrderBy(item => item.Line).OrderBy(item => item.Column);
return sps;
}
// Find method-body start SequencePoint "xxxx {"
public static CodeCoverageSequencePoint getBodyStartSP(IEnumerable<CodeCoverageSequencePoint> sPoints) {
CodeCoverageSequencePoint startSeqPoint = null;
bool startFound = false;
foreach (CodeCoverageSequencePoint sPoint in sPoints) {
if ( sPoint.Content == "{") {
if (startSeqPoint == null) startSeqPoint = sPoint;
startFound = true;
break;
}
startSeqPoint = sPoint;
}
return startFound == true? startSeqPoint : null;
}
// Find method-body final SequencePoint "}"
public static CodeCoverageSequencePoint getBodyFinalSP(IEnumerable<CodeCoverageSequencePoint> sps) {
CodeCoverageSequencePoint finalSeqPoint = null;
foreach (CodeCoverageSequencePoint sp in Enumerable.Reverse(sps)) {
if ( sp.Content == "}") {
if (finalSeqPoint == null) {
finalSeqPoint = sp;
}
// check for ccrewrite duplicate
else if (sp.Line == finalSeqPoint.Line &&
sp.Column == finalSeqPoint.Column &&
sp.EndLine == finalSeqPoint.EndLine &&
sp.EndColumn == finalSeqPoint.EndColumn &&
sp.Offset < finalSeqPoint.Offset) {
finalSeqPoint = sp;
}
}
}
return finalSeqPoint;
}
List<CodeCoverageSequencePoint> FilterSequencePoints(List<CodeCoverageSequencePoint> sps) {
List<CodeCoverageSequencePoint> returnList = sps;
if (sps.Count > 2 &&
this.BodyStartSP != null &&
this.BodyFinalSP != null ) {
// After ccrewrite ContractClass/ContractClassFor
// sequence point(s) from another file/class/method
// is inserted into this method sequence points
//
// To remove alien sequence points, all sequence points on lines
// before method signature and after end-brackets xxx{} are removed
// If ContractClassFor is in another file but matches this method lines
// then, afaik, not much can be done to remove inserted alien SP's
List<CodeCoverageSequencePoint> selected = new List<CodeCoverageSequencePoint>();
foreach (var point in sps) {
if (
(point.Line > BodyStartSP.Line || (point.Line == BodyStartSP.Line && point.Column >= BodyStartSP.Column)) &&
(point.Line < BodyFinalSP.Line || (point.Line == BodyFinalSP.Line && point.Column < BodyFinalSP.Column))
) {
selected.Add (point);
}
// After ccrewrite ContractClass/ContractClassFor
// duplicate method end-sequence-point (}) is added
//
// Add first finalSP (can be a duplicate)
// Note: IL.Offset of second duplicate finalSP will
// extend branch coverage outside method-end "}",
// and that can lead to wrong branch coverage display!
if (object.ReferenceEquals (point, this.BodyFinalSP)) {
selected.Add (point);
}
}
returnList = selected;
}
return returnList;
}
int GetSequencePointsCount() {
XElement summary = this.element.Element("Summary");
if ( summary != null ) {
@ -167,30 +258,6 @@ namespace ICSharpCode.CodeCoverage @@ -167,30 +258,6 @@ namespace ICSharpCode.CodeCoverage
return bps;
}
// Find method-body start SequencePoint "{"
public static CodeCoverageSequencePoint getBodyStartSP(IEnumerable<CodeCoverageSequencePoint> sps) {
CodeCoverageSequencePoint startSeqPoint = null;
foreach (CodeCoverageSequencePoint sp in sps) {
if ( sp.Content == "{") {
startSeqPoint = sp;
break;
}
}
return startSeqPoint;
}
// Find method-body final SequencePoint "}"
public static CodeCoverageSequencePoint getBodyFinalSP(IEnumerable<CodeCoverageSequencePoint> sps) {
CodeCoverageSequencePoint finalSeqPoint = null;
foreach (CodeCoverageSequencePoint sp in Enumerable.Reverse(sps)) {
if ( sp.Content == "}") {
finalSeqPoint = sp;
break;
}
}
return finalSeqPoint;
}
Tuple<int,int> GetBranchRatio () {
// goal: Get branch ratio and exclude (rewriten) Code Contracts branches
@ -206,24 +273,22 @@ namespace ICSharpCode.CodeCoverage @@ -206,24 +273,22 @@ namespace ICSharpCode.CodeCoverage
// This sequence point offset is used to skip CCRewrite(n) BranchPoint's (Requires)
// and '{' branches at static methods
CodeCoverageSequencePoint startSeqPoint = getBodyStartSP(this.SequencePoints);
if (Object.ReferenceEquals(null, startSeqPoint)) { return null; }
if (this.BodyStartSP == null) { return null; } // empty body
// This sequence point offset is used to skip CCRewrite(n) BranchPoint's (Ensures)
CodeCoverageSequencePoint finalSeqPoint = getBodyFinalSP(this.SequencePoints);
if (Object.ReferenceEquals(null, finalSeqPoint)) { return null; }
if (this.BodyFinalSP == null) { return null; } // empty body
// Connect Sequence & Branches
IEnumerator<CodeCoverageSequencePoint> SPEnumerator = this.SequencePoints.GetEnumerator();
CodeCoverageSequencePoint currSeqPoint = startSeqPoint;
int nextSeqPointOffset = startSeqPoint.Offset;
CodeCoverageSequencePoint currSeqPoint = BodyStartSP;
int nextSeqPointOffset = BodyStartSP.Offset;
foreach (var bp in this.BranchPoints) {
// ignore branches outside of method body
if (bp.Offset < startSeqPoint.Offset)
// ignore branches outside of method body offset range
if (bp.Offset < BodyStartSP.Offset)
continue;
if (bp.Offset > finalSeqPoint.Offset)
if (bp.Offset > BodyFinalSP.Offset)
break;
// Sync with SequencePoint

2
src/AddIns/Analysis/CodeCoverage/Project/Src/CodeCoverageStringTextSource.cs

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
// Copyright (c) https://github.com/ddur
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
// This code is distributed under MIT license
using System;
using System.Collections.Generic;

Loading…
Cancel
Save