// // 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 } }