//
// OpenCover - S Wilde
//
// This source code is released under the MIT License; see the accompanying license file.
//
using System;
using System.Text.RegularExpressions;
using System.Xml.Serialization;
namespace OpenCover.Framework.Model
{
///
/// An method entity that can be instrumented
///
public class Method : SummarySkippedEntity
{
///
/// The MetadataToken used to identify this entity within the assembly
///
public int MetadataToken { get; set; }
///
/// The full name of the method (method-definition), includes return-type namespace-class::call-name(argument-types)
///
[XmlElement("Name")]
public string FullName { get; set; }
///
/// A reference to a file in the file collection (used to help visualisation)
///
public FileRef FileRef { get; set; }
internal UInt32 FileRefUniqueId {
get { return FileRef == null? 0 : FileRef.UniqueId; }
}
///
/// A list of sequence points that have been produced for this method
///
public SequencePoint[] SequencePoints {
get {
return _sequencePoints;
}
set {
_sequencePoints = value ?? new SequencePoint[0];
}
}
private SequencePoint[] _sequencePoints = new SequencePoint[0];
///
/// A list of branch points that have been identified for this method
///
public BranchPoint[] BranchPoints {
get {
return _branchPoints;
}
set {
_branchPoints = value ?? new BranchPoint[0];
}
}
private BranchPoint[] _branchPoints = new BranchPoint[0];
///
/// A method point to identify the entry of a method
///
public InstrumentationPoint MethodPoint { get; set; }
///
/// Has the method been visited
///
[XmlAttribute("visited")]
public bool Visited { get; set; }
///
/// What is the cyclomatic complexity of this method.
///
/// Calculated using the Gendarme rules library
[XmlAttribute("cyclomaticComplexity")]
public int CyclomaticComplexity { get; set; }
///
/// What is the NPath complexity of this method.
///
/// Product of path branches (ie:path0=2;path1=3;path2=2 =>2*3*2==12
[XmlAttribute("nPathComplexity")]
public int NPathComplexity { get; set; }
///
/// What is the sequence coverage of this method
///
/// Rounded for ease
[XmlAttribute("sequenceCoverage")]
public decimal SequenceCoverage { get; set; }
///
/// What is the branch coverage of this method
///
/// Rounded for ease
[XmlAttribute("branchCoverage")]
public decimal BranchCoverage { get; set; }
///
/// What is the crap score of this method
/// based on the following calculation
/// CRAP1(m) = comp(m)^2 * (1 – cov(m)/100)^3 + comp(m)
///
/// Rounded for ease
[XmlAttribute("crapScore")]
public decimal CrapScore { get; set; }
///
/// Is this method a constructor
///
[XmlAttribute("isConstructor")]
public bool IsConstructor { get; set; }
///
/// Is this method static
///
[XmlAttribute("isStatic")]
public bool IsStatic { get; set; }
///
/// Is this method a property getter
///
[XmlAttribute("isGetter")]
public bool IsGetter { get; set; }
///
/// Is this method a property setter
///
[XmlAttribute("isSetter")]
public bool IsSetter { get; set; }
///
/// Mark an entity as skipped
///
/// Provide a reason
public override void MarkAsSkipped(SkippedMethod reason)
{
SkippedDueTo = reason;
if (MethodPoint != null)
MethodPoint.IsSkipped = true;
MethodPoint = null;
SequencePoints = null;
BranchPoints = null;
}
#region IsGenerated & CallName
///
/// True if this.FullName matches generated-method-regex-pattern
///
internal bool IsGenerated {
get {
if (_resolvedIsGenerated == null) {
_resolvedIsGenerated = !(string.IsNullOrEmpty(FullName) || FullName.Trim().Length == 0)
&& FullName.Contains("__") // quick test before using regex heavy weapon
&& IsGeneratedMethodRegex.IsMatch(FullName);
}
return _resolvedIsGenerated == true;
}
}
///
/// Method "::CallName(". (Name excluding return type, namespace and arguments)
///
internal string CallName {
get {
if (_resolvedCallName != null)
return _resolvedCallName;
_resolvedCallName = string.Empty; // init resolve value
if (!(string.IsNullOrEmpty(FullName) || FullName.Trim().Length == 0)) {
var startIndex = FullName.IndexOf("::", StringComparison.Ordinal);
startIndex += 2;
var finalIndex = FullName.IndexOf('(', startIndex);
if (startIndex > 1 && finalIndex > startIndex) {
_resolvedCallName = FullName // resolve cache
.Substring(startIndex, finalIndex - startIndex);
}
}
return _resolvedCallName;
}
}
private bool? _resolvedIsGenerated;
private string _resolvedCallName;
private const RegexOptions RegexOptions = System.Text.RegularExpressions.RegexOptions.Compiled | System.Text.RegularExpressions.RegexOptions.Singleline | System.Text.RegularExpressions.RegexOptions.ExplicitCapture;
private static readonly Regex IsGeneratedMethodRegex = new Regex(@"(<[^\s:>]+>\w__\w)", RegexOptions);
#endregion
}
}