first commit
This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using Mono.Reflection;
|
||||
|
||||
namespace UnityEditor.TestTools.CodeCoverage.OpenCover
|
||||
{
|
||||
internal static class CyclomaticComplexity
|
||||
{
|
||||
private static List<Instruction> targets = new List<Instruction>();
|
||||
|
||||
public static int CalculateCyclomaticComplexity(this MethodBase method)
|
||||
{
|
||||
if (method == null || method.GetMethodBody() == null)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool hasSwitch = false;
|
||||
foreach (Instruction ins in method.GetInstructions())
|
||||
{
|
||||
if (ins.OpCode.OperandType == OperandType.InlineSwitch)
|
||||
{
|
||||
hasSwitch = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasSwitch)
|
||||
{
|
||||
return GetSwitchCyclomaticComplexity(method);
|
||||
}
|
||||
return GetFastCyclomaticComplexity(method);
|
||||
}
|
||||
|
||||
private static int GetFastCyclomaticComplexity(MethodBase method)
|
||||
{
|
||||
int cc = 1;
|
||||
foreach (Instruction ins in method.GetInstructions())
|
||||
{
|
||||
switch (ins.OpCode.FlowControl)
|
||||
{
|
||||
case FlowControl.Branch:
|
||||
// detect ternary pattern
|
||||
Instruction previous = ins.Previous;
|
||||
if (previous != null && previous.OpCode.Name.StartsWith("ld"))
|
||||
{
|
||||
++cc;
|
||||
}
|
||||
break;
|
||||
|
||||
case FlowControl.Cond_Branch:
|
||||
++cc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return cc;
|
||||
}
|
||||
|
||||
private static int GetSwitchCyclomaticComplexity(MethodBase method)
|
||||
{
|
||||
Instruction previous = null;
|
||||
Instruction branch = null;
|
||||
int cc = 1;
|
||||
|
||||
foreach (Instruction ins in method.GetInstructions())
|
||||
{
|
||||
switch (ins.OpCode.FlowControl)
|
||||
{
|
||||
case FlowControl.Branch:
|
||||
if (previous == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// detect ternary pattern
|
||||
previous = ins.Previous;
|
||||
if (previous.OpCode.Name.StartsWith("ld"))
|
||||
{
|
||||
cc++;
|
||||
}
|
||||
|
||||
// or 'default' (xmcs)
|
||||
if (previous.OpCode.FlowControl == FlowControl.Cond_Branch)
|
||||
{
|
||||
branch = (previous.Operand as Instruction);
|
||||
// branch can be null (e.g. switch -> Instruction[])
|
||||
if ((branch != null) && targets.Contains(branch) && !targets.Contains(ins))
|
||||
{
|
||||
targets.Add(ins);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case FlowControl.Cond_Branch:
|
||||
// note: a single switch (C#) with sparse values can be broken into several swicth (IL)
|
||||
// that will use the same 'targets' and must be counted only once
|
||||
if (ins.OpCode.OperandType == OperandType.InlineSwitch)
|
||||
{
|
||||
AccumulateSwitchTargets(ins);
|
||||
}
|
||||
else
|
||||
{
|
||||
// some conditional branch can be related to the sparse switch
|
||||
branch = (ins.Operand as Instruction);
|
||||
previous = branch.Previous;
|
||||
if ((previous != null) && previous.Previous.OpCode.OperandType != OperandType.InlineSwitch)
|
||||
{
|
||||
if (!targets.Contains(branch))
|
||||
{
|
||||
cc++;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
// count all unique targets (and default if more than one C# switch is used)
|
||||
cc += targets.Count;
|
||||
targets.Clear();
|
||||
|
||||
return cc;
|
||||
}
|
||||
|
||||
private static void AccumulateSwitchTargets(Instruction ins)
|
||||
{
|
||||
Instruction[] cases = (Instruction[])ins.Operand;
|
||||
foreach (Instruction target in cases)
|
||||
{
|
||||
// ignore targets that are the next instructions (xmcs)
|
||||
if (target != ins.Next && !targets.Contains(target))
|
||||
targets.Add(target);
|
||||
}
|
||||
// add 'default' branch (if one exists)
|
||||
Instruction next = ins.Next;
|
||||
if (next.OpCode.FlowControl == FlowControl.Branch)
|
||||
{
|
||||
Instruction unc = FindFirstUnconditionalBranchTarget(cases[0]);
|
||||
if (unc != next.Operand && !targets.Contains(next.Operand as Instruction))
|
||||
targets.Add(next.Operand as Instruction);
|
||||
}
|
||||
}
|
||||
|
||||
private static Instruction FindFirstUnconditionalBranchTarget(Instruction ins)
|
||||
{
|
||||
while (ins != null)
|
||||
{
|
||||
if (FlowControl.Branch == ins.OpCode.FlowControl)
|
||||
return ((Instruction)ins.Operand);
|
||||
|
||||
ins = ins.Next;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 74449815e747b4b1ba000bf66f12e01a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9c2ede2081f2f4c45a6f7f4c92e3a735
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,63 @@
|
||||
//
|
||||
// OpenCover - S Wilde
|
||||
//
|
||||
// This source code is released under the MIT License; see the accompanying license file.
|
||||
//
|
||||
|
||||
using System.Linq;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace OpenCover.Framework.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// a branch point
|
||||
/// </summary>
|
||||
public class BranchPoint : InstrumentationPoint, IDocumentReference
|
||||
{
|
||||
/// <summary>
|
||||
/// Line of the branching instruction
|
||||
/// </summary>
|
||||
[XmlAttribute("sl")]
|
||||
public int StartLine { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A path that can be taken
|
||||
/// </summary>
|
||||
[XmlAttribute("path")]
|
||||
public int Path { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// List of OffsetPoints between Offset and EndOffset (exclusive)
|
||||
/// </summary>
|
||||
[XmlAttribute("offsetchain")]
|
||||
public System.Collections.Generic.List<int> OffsetPoints { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Should offset points be serialized
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool ShouldSerializeOffsetPoints()
|
||||
{
|
||||
return OffsetPoints.Maybe(_ => _.Any());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Last Offset == EndOffset.
|
||||
/// Can be same as Offset
|
||||
/// </summary>
|
||||
[XmlAttribute("offsetend")]
|
||||
public int EndOffset { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The file associated with the supplied startline
|
||||
/// </summary>
|
||||
[XmlAttribute("fileid")]
|
||||
public uint FileId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The url to the document if an entry was not mapped to an id
|
||||
/// </summary>
|
||||
[XmlAttribute("url")]
|
||||
public string Document { get; set; }
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 88cac9839726d46718b126833c76c5e9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// OpenCover - S Wilde
|
||||
//
|
||||
// This source code is released under the MIT License; see the accompanying license file.
|
||||
//
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace OpenCover.Framework.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// An entity that contains methods
|
||||
/// </summary>
|
||||
public class Class : SummarySkippedEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// instantiate
|
||||
/// </summary>
|
||||
public Class()
|
||||
{
|
||||
Methods = new Method[0];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The full name of the class
|
||||
/// </summary>
|
||||
public string FullName { get; set; }
|
||||
|
||||
[XmlIgnore]
|
||||
internal File[] Files { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A list of methods that make up the class
|
||||
/// </summary>
|
||||
public Method[] Methods { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If a class was skipped by instrumentation, supply the reason why
|
||||
/// </summary>
|
||||
/// <param name="reason"></param>
|
||||
public override void MarkAsSkipped(SkippedMethod reason)
|
||||
{
|
||||
SkippedDueTo = reason;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c0d40fe321f9746dcbccb27824986511
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,54 @@
|
||||
//
|
||||
// OpenCover - S Wilde
|
||||
//
|
||||
// This source code is released under the MIT License; see the accompanying license file.
|
||||
//
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace OpenCover.Framework.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// A coverage session
|
||||
/// </summary>
|
||||
public class CoverageSession
|
||||
{
|
||||
private string _version;
|
||||
|
||||
/// <summary>
|
||||
/// initialise a coverage session
|
||||
/// </summary>
|
||||
public CoverageSession()
|
||||
{
|
||||
Modules = new Module[0];
|
||||
Summary = new Summary();
|
||||
_version = GetType().Assembly.GetName().Version.ToString();
|
||||
}
|
||||
/// <summary>
|
||||
/// A unique session identifier
|
||||
/// </summary>
|
||||
public string SessionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A Summary of results for the session
|
||||
/// </summary>
|
||||
public Summary Summary { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A list of modules that have been profiled under the session
|
||||
/// </summary>
|
||||
public Module[] Modules { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The current version
|
||||
/// </summary>
|
||||
[XmlAttribute("Version")]
|
||||
public string Version {
|
||||
get { return _version; }
|
||||
// ReSharper disable once ValueParameterNotUsed
|
||||
set { /* intentionally left blank */} }
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 561dcfbc5a4094415b3d8348f1a6b738
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,68 @@
|
||||
//
|
||||
// OpenCover - S Wilde
|
||||
//
|
||||
// This source code is released under the MIT License; see the accompanying license file.
|
||||
//
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace OpenCover.Framework.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// A file reference within the coverage session and is used to point to an existing File entity
|
||||
/// </summary>
|
||||
public class FileRef
|
||||
{
|
||||
/// <summary>
|
||||
/// The uniqueid of a file in a coverage session
|
||||
/// </summary>
|
||||
[XmlAttribute("uid")]
|
||||
public UInt32 UniqueId { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// File details of a source file
|
||||
/// </summary>
|
||||
public class File : FileRef
|
||||
{
|
||||
private static int _uId;
|
||||
|
||||
static readonly List<File> Files = new List<File>();
|
||||
|
||||
internal static void ResetAfterLoading()
|
||||
{
|
||||
_uId = (int)Files.Max(x => x.UniqueId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A standard constructor
|
||||
/// </summary>
|
||||
public File()
|
||||
{
|
||||
UniqueId = (UInt32)Interlocked.Increment(ref _uId);
|
||||
Files.Add(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The path to file
|
||||
/// </summary>
|
||||
[XmlAttribute("fullPath")]
|
||||
public string FullPath { get; set; }
|
||||
}
|
||||
|
||||
internal class FileEqualityComparer : IEqualityComparer<File>
|
||||
{
|
||||
public bool Equals(File x, File y)
|
||||
{
|
||||
return x.FullPath == y.FullPath;
|
||||
}
|
||||
|
||||
public int GetHashCode(File obj)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4ea0122a5084b4beca6bbb008fea821e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
|
||||
namespace OpenCover.Framework
|
||||
{
|
||||
internal static class HelperExtensions
|
||||
{
|
||||
public static TRet Maybe<T, TRet>(this T value, Func<T, TRet> action, TRet defValue = default(TRet))
|
||||
where T : class
|
||||
{
|
||||
return (value != null) ? action(value) : defValue;
|
||||
}
|
||||
|
||||
public static T Do<T>(this T value, Action<T> action)
|
||||
where T : class
|
||||
{
|
||||
if (value != null)
|
||||
action(value);
|
||||
return value;
|
||||
}
|
||||
|
||||
public static T Try<T>(this T value, Action<T> action)
|
||||
where T : class
|
||||
{
|
||||
try
|
||||
{
|
||||
if (value != null)
|
||||
action(value);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignore error
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0a74e938125304007a53cf9733cd1208
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,23 @@
|
||||
//
|
||||
// OpenCover - S Wilde
|
||||
//
|
||||
// This source code is released under the MIT License; see the accompanying license file.
|
||||
//
|
||||
namespace OpenCover.Framework.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// A point may have a document reference
|
||||
/// </summary>
|
||||
public interface IDocumentReference
|
||||
{
|
||||
/// <summary>
|
||||
/// The document url
|
||||
/// </summary>
|
||||
string Document { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The document id after lookup
|
||||
/// </summary>
|
||||
uint FileId { get; set; }
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ebffa2e2071ad4f79a3641b47e74b25e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,190 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace OpenCover.Framework.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// An instrumentable point
|
||||
/// </summary>
|
||||
public class InstrumentationPoint
|
||||
{
|
||||
private static int _instrumentPoint;
|
||||
private static readonly object LockObject = new object();
|
||||
private static readonly List<InstrumentationPoint> InstrumentPoints;
|
||||
|
||||
static InstrumentationPoint()
|
||||
{
|
||||
_instrumentPoint = 0;
|
||||
InstrumentPoints = new List<InstrumentationPoint>(8192) {null};
|
||||
}
|
||||
|
||||
internal static void Clear()
|
||||
{
|
||||
InstrumentPoints.Clear();
|
||||
InstrumentPoints.Add(null);
|
||||
_instrumentPoint = 0;
|
||||
}
|
||||
|
||||
internal static void ResetAfterLoading()
|
||||
{
|
||||
var points = InstrumentPoints
|
||||
.Where(x => x != null)
|
||||
.GroupBy(x => x.UniqueSequencePoint)
|
||||
.Select(g => g.OrderBy(x => x.OrigSequencePoint).First())
|
||||
.ToList();
|
||||
|
||||
var max = (int)points.Max(x => x.UniqueSequencePoint);
|
||||
|
||||
InstrumentPoints.Clear();
|
||||
InstrumentPoints.Add(null);
|
||||
|
||||
for (var i = 1; i <= max; i++)
|
||||
{
|
||||
var point = new SequencePoint();
|
||||
InstrumentPoints[i] = point;
|
||||
point.UniqueSequencePoint = (uint)i;
|
||||
}
|
||||
|
||||
foreach (var instrumentationPoint in points)
|
||||
{
|
||||
InstrumentPoints[(int)instrumentationPoint.UniqueSequencePoint] = instrumentationPoint;
|
||||
}
|
||||
|
||||
_instrumentPoint = max;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the number of visit points
|
||||
/// </summary>
|
||||
public static int Count {
|
||||
get { return InstrumentPoints.Count; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the number of recorded visit points for this identifier
|
||||
/// </summary>
|
||||
/// <param name="spid">the sequence point identifier - NOTE 0 is not used</param>
|
||||
public static int GetVisitCount(uint spid)
|
||||
{
|
||||
return InstrumentPoints[(int) spid].VisitCount;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a number of recorded visit ppints against this identifier
|
||||
/// </summary>
|
||||
/// <param name="spid">the sequence point identifier - NOTE 0 is not used</param>
|
||||
/// <param name="trackedMethodId">the id of a tracked method - Note 0 means no method currently tracking</param>
|
||||
/// <param name="amount">the number of visit points to add</param>
|
||||
public static bool AddVisitCount(uint spid, uint trackedMethodId, int amount)
|
||||
{
|
||||
if (spid != 0 && spid < InstrumentPoints.Count)
|
||||
{
|
||||
var point = InstrumentPoints[(int) spid];
|
||||
point.VisitCount += amount;
|
||||
if (point.VisitCount < 0)
|
||||
{
|
||||
point.VisitCount = int.MaxValue;
|
||||
}
|
||||
if (trackedMethodId != 0)
|
||||
{
|
||||
AddOrUpdateTrackingPoint(trackedMethodId, amount, point);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void AddOrUpdateTrackingPoint(uint trackedMethodId, int amount, InstrumentationPoint point)
|
||||
{
|
||||
point._tracked = point._tracked ?? new List<TrackedMethodRef>();
|
||||
var tracked = point._tracked.Find(x => x.UniqueId == trackedMethodId);
|
||||
if (tracked == null)
|
||||
{
|
||||
tracked = new TrackedMethodRef {UniqueId = trackedMethodId, VisitCount = amount};
|
||||
point._tracked.Add(tracked);
|
||||
}
|
||||
else
|
||||
{
|
||||
tracked.VisitCount += amount;
|
||||
if (tracked.VisitCount < 0)
|
||||
tracked.VisitCount = int.MaxValue;
|
||||
}
|
||||
}
|
||||
|
||||
private List<TrackedMethodRef> _tracked;
|
||||
|
||||
/// <summary>
|
||||
/// Initialise
|
||||
/// </summary>
|
||||
public InstrumentationPoint()
|
||||
{
|
||||
lock (LockObject)
|
||||
{
|
||||
UniqueSequencePoint = (uint)++_instrumentPoint;
|
||||
InstrumentPoints.Add(this);
|
||||
OrigSequencePoint = UniqueSequencePoint;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Store the number of visits
|
||||
/// </summary>
|
||||
[XmlAttribute("vc")]
|
||||
public int VisitCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A unique number
|
||||
/// </summary>
|
||||
[XmlAttribute("uspid")]
|
||||
public UInt32 UniqueSequencePoint { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// An order of the point within the method
|
||||
/// </summary>
|
||||
[XmlAttribute("ordinal")]
|
||||
public UInt32 Ordinal { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The IL offset of the point
|
||||
/// </summary>
|
||||
[XmlAttribute("offset")]
|
||||
public int Offset { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Used to hide an instrumentation point
|
||||
/// </summary>
|
||||
[XmlIgnore]
|
||||
public bool IsSkipped { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The list of tracked methods
|
||||
/// </summary>
|
||||
public TrackedMethodRef[] TrackedMethodRefs
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_tracked != null)
|
||||
{
|
||||
return _tracked.ToArray();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
set
|
||||
{
|
||||
_tracked = null;
|
||||
if (value == null)
|
||||
return;
|
||||
_tracked = new List<TrackedMethodRef>(value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[XmlIgnore]
|
||||
public UInt32 OrigSequencePoint { get; set; }
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 86783b018856d4f82ab6105c443f2ffa
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,195 @@
|
||||
//
|
||||
// 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
|
||||
{
|
||||
/// <summary>
|
||||
/// An method entity that can be instrumented
|
||||
/// </summary>
|
||||
public class Method : SummarySkippedEntity
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// The MetadataToken used to identify this entity within the assembly
|
||||
/// </summary>
|
||||
public int MetadataToken { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The full name of the method (method-definition), includes return-type namespace-class::call-name(argument-types)
|
||||
/// </summary>
|
||||
[XmlElement("Name")]
|
||||
public string FullName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A reference to a file in the file collection (used to help visualisation)
|
||||
/// </summary>
|
||||
public FileRef FileRef { get; set; }
|
||||
|
||||
internal UInt32 FileRefUniqueId {
|
||||
get { return FileRef == null? 0 : FileRef.UniqueId; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A list of sequence points that have been produced for this method
|
||||
/// </summary>
|
||||
public SequencePoint[] SequencePoints {
|
||||
get {
|
||||
return _sequencePoints;
|
||||
}
|
||||
set {
|
||||
_sequencePoints = value ?? new SequencePoint[0];
|
||||
}
|
||||
}
|
||||
private SequencePoint[] _sequencePoints = new SequencePoint[0];
|
||||
|
||||
/// <summary>
|
||||
/// A list of branch points that have been identified for this method
|
||||
/// </summary>
|
||||
public BranchPoint[] BranchPoints {
|
||||
get {
|
||||
return _branchPoints;
|
||||
}
|
||||
set {
|
||||
_branchPoints = value ?? new BranchPoint[0];
|
||||
}
|
||||
}
|
||||
private BranchPoint[] _branchPoints = new BranchPoint[0];
|
||||
|
||||
/// <summary>
|
||||
/// A method point to identify the entry of a method
|
||||
/// </summary>
|
||||
public InstrumentationPoint MethodPoint { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Has the method been visited
|
||||
/// </summary>
|
||||
[XmlAttribute("visited")]
|
||||
public bool Visited { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// What is the cyclomatic complexity of this method.
|
||||
/// </summary>
|
||||
/// <remarks>Calculated using the Gendarme rules library</remarks>
|
||||
[XmlAttribute("cyclomaticComplexity")]
|
||||
public int CyclomaticComplexity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// What is the NPath complexity of this method.
|
||||
/// </summary>
|
||||
/// <remarks>Product of path branches (ie:path0=2;path1=3;path2=2 =>2*3*2==12</remarks>
|
||||
[XmlAttribute("nPathComplexity")]
|
||||
public int NPathComplexity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// What is the sequence coverage of this method
|
||||
/// </summary>
|
||||
/// <remarks>Rounded for ease</remarks>
|
||||
[XmlAttribute("sequenceCoverage")]
|
||||
public decimal SequenceCoverage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// What is the branch coverage of this method
|
||||
/// </summary>
|
||||
/// <remarks>Rounded for ease</remarks>
|
||||
[XmlAttribute("branchCoverage")]
|
||||
public decimal BranchCoverage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 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)
|
||||
/// </summary>
|
||||
/// <remarks>Rounded for ease</remarks>
|
||||
[XmlAttribute("crapScore")]
|
||||
public decimal CrapScore { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Is this method a constructor
|
||||
/// </summary>
|
||||
[XmlAttribute("isConstructor")]
|
||||
public bool IsConstructor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Is this method static
|
||||
/// </summary>
|
||||
[XmlAttribute("isStatic")]
|
||||
public bool IsStatic { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Is this method a property getter
|
||||
/// </summary>
|
||||
[XmlAttribute("isGetter")]
|
||||
public bool IsGetter { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Is this method a property setter
|
||||
/// </summary>
|
||||
[XmlAttribute("isSetter")]
|
||||
public bool IsSetter { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Mark an entity as skipped
|
||||
/// </summary>
|
||||
/// <param name="reason">Provide a reason</param>
|
||||
public override void MarkAsSkipped(SkippedMethod reason)
|
||||
{
|
||||
SkippedDueTo = reason;
|
||||
if (MethodPoint != null)
|
||||
MethodPoint.IsSkipped = true;
|
||||
MethodPoint = null;
|
||||
SequencePoints = null;
|
||||
BranchPoints = null;
|
||||
}
|
||||
|
||||
#region IsGenerated & CallName
|
||||
|
||||
/// <summary>
|
||||
/// True if this.FullName matches generated-method-regex-pattern
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Method "::CallName(". (Name excluding return type, namespace and arguments)
|
||||
/// </summary>
|
||||
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
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7f1f74c5e9b1146168b87690081420c4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "Unity.TestTools.CodeCoverage.Editor.OpenCover.Model",
|
||||
"references": [],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": []
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 19c3df1967929405fba735480b3da9a7
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,77 @@
|
||||
//
|
||||
// OpenCover - S Wilde
|
||||
//
|
||||
// This source code is released under the MIT License; see the accompanying license file.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace OpenCover.Framework.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// The details of a module
|
||||
/// </summary>
|
||||
public class Module : SummarySkippedEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// simple constructor
|
||||
/// </summary>
|
||||
public Module()
|
||||
{
|
||||
Aliases = new List<string>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The full path name to the module
|
||||
/// </summary>
|
||||
public string ModulePath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// GetlastWriteTimeUtc
|
||||
/// </summary>
|
||||
public DateTime ModuleTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A list of aliases
|
||||
/// </summary>
|
||||
[XmlIgnore]
|
||||
public IList<string> Aliases { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The name of the module
|
||||
/// </summary>
|
||||
public string ModuleName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The files that make up the module
|
||||
/// </summary>
|
||||
public File[] Files { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The classes that make up the module
|
||||
/// </summary>
|
||||
public Class[] Classes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Methods that are being tracked i.e. test methods
|
||||
/// </summary>
|
||||
public TrackedMethod[] TrackedMethods { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A hash of the file used to group them together (especially when running against mstest)
|
||||
/// </summary>
|
||||
[XmlAttribute("hash")]
|
||||
public string ModuleHash { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Mark an entity as skipped
|
||||
/// </summary>
|
||||
/// <param name="reason">Provide a reason</param>
|
||||
public override void MarkAsSkipped(SkippedMethod reason)
|
||||
{
|
||||
SkippedDueTo = reason;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f7c00a2c9a9fd476c947d35ae18e21fd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,124 @@
|
||||
//
|
||||
// OpenCover - S Wilde
|
||||
//
|
||||
// This source code is released under the MIT License; see the accompanying license file.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace OpenCover.Framework.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// a sequence point
|
||||
/// </summary>
|
||||
public class SequencePoint : InstrumentationPoint, IDocumentReference
|
||||
{
|
||||
/// <summary>
|
||||
/// The start line of the sequence point
|
||||
/// </summary>
|
||||
[XmlAttribute("sl")]
|
||||
public int StartLine { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The start column of the sequence point
|
||||
/// </summary>
|
||||
[XmlAttribute("sc")]
|
||||
public int StartColumn { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The end line of the sequence point
|
||||
/// </summary>
|
||||
[XmlAttribute("el")]
|
||||
public int EndLine { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The end column of the sequence point
|
||||
/// </summary>
|
||||
[XmlAttribute("ec")]
|
||||
public int EndColumn { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Count of merged branches
|
||||
/// </summary>
|
||||
/// <summary>
|
||||
/// The number of branch exits
|
||||
/// </summary>
|
||||
[XmlAttribute("bec")]
|
||||
public int BranchExitsCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Visit count of merged branches
|
||||
/// </summary>
|
||||
[XmlAttribute("bev")]
|
||||
public int BranchExitsVisit { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The file associated with the supplied startline
|
||||
/// </summary>
|
||||
[XmlAttribute("fileid")]
|
||||
public uint FileId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The url to the document if an entry was not mapped to an id
|
||||
/// </summary>
|
||||
[XmlAttribute("url")]
|
||||
public string Document { get; set; }
|
||||
|
||||
internal List<BranchPoint> BranchPoints {
|
||||
get{
|
||||
return _branchPoints;
|
||||
}
|
||||
set{
|
||||
_branchPoints = value ?? new List<BranchPoint>();
|
||||
}
|
||||
}
|
||||
private List<BranchPoint> _branchPoints = new List<BranchPoint>();
|
||||
|
||||
/// <summary>
|
||||
/// Property
|
||||
/// </summary>
|
||||
public bool IsSingleCharSequencePoint {
|
||||
get {
|
||||
return (StartLine == EndLine) && (EndColumn - StartColumn) == 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// SonnarQube wants no more than 3 boolean conditions
|
||||
/// </summary>
|
||||
/// <param name="sp"></param>
|
||||
/// <returns></returns>
|
||||
private bool IsLineEqual (SequencePoint sp) {
|
||||
return StartLine == sp.StartLine && EndLine == sp.EndLine;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// SonnarQube wants no more than 3 boolean conditions
|
||||
/// </summary>
|
||||
/// <param name="sp"></param>
|
||||
/// <returns></returns>
|
||||
private bool IsColumnEqual (SequencePoint sp) {
|
||||
return StartColumn == sp.StartColumn && EndColumn == sp.EndColumn;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is Start/End Line/Column equal
|
||||
/// </summary>
|
||||
/// <param name="sp"></param>
|
||||
/// <returns></returns>
|
||||
public bool IsPositionEqual (SequencePoint sp) {
|
||||
return sp != null && IsLineEqual (sp) && IsColumnEqual (sp);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is FileId equal? (If FileId is 0 then file is unknown)
|
||||
/// </summary>
|
||||
/// <param name="sp"></param>
|
||||
/// <returns></returns>
|
||||
public bool IsFileIdEqual (SequencePoint sp) {
|
||||
return sp != null && FileId != 0 && FileId == sp.FileId;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 448b5b9c7773f48be878eb5f56008baf
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,33 @@
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace OpenCover.Framework.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// The entity can be skipped from coverage but needs to supply a reason
|
||||
/// </summary>
|
||||
public abstract class SkippedEntity
|
||||
{
|
||||
private SkippedMethod? _skippedDueTo;
|
||||
|
||||
/// <summary>
|
||||
/// If this class has been skipped then this value will describe why
|
||||
/// </summary>
|
||||
[XmlAttribute("skippedDueTo")]
|
||||
public SkippedMethod SkippedDueTo
|
||||
{
|
||||
get { return _skippedDueTo.GetValueOrDefault(); }
|
||||
set { _skippedDueTo = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If this class has been skipped then this value will allow the data to be serialized
|
||||
/// </summary>
|
||||
public bool ShouldSerializeSkippedDueTo() { return _skippedDueTo.HasValue; }
|
||||
|
||||
/// <summary>
|
||||
/// Mark an entity as skipped
|
||||
/// </summary>
|
||||
/// <param name="reason">Provide a reason</param>
|
||||
public abstract void MarkAsSkipped(SkippedMethod reason);
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2adfa90d9eaaa4702b2457c09db2f5e2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,64 @@
|
||||
namespace OpenCover.Framework.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// Describes how a method or class was skipped
|
||||
/// </summary>
|
||||
public enum SkippedMethod
|
||||
{
|
||||
/// <summary>
|
||||
/// Entity was skipped due to a matching exclusion attribute filter
|
||||
/// </summary>
|
||||
Attribute = 3,
|
||||
|
||||
/// <summary>
|
||||
/// Entity was skipped due to a matching exclusion file filter
|
||||
/// </summary>
|
||||
File = 4,
|
||||
|
||||
/// <summary>
|
||||
/// Entity was skipped due to a matching exclusion module/class filter
|
||||
/// </summary>
|
||||
Filter = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Entity was skipped due to a missing PDB
|
||||
/// </summary>
|
||||
MissingPdb = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Entity was skipped by inference (usually related to File filters)
|
||||
/// </summary>
|
||||
Inferred = 5,
|
||||
|
||||
/// <summary>
|
||||
/// Entity (method) was skipped as it is an auto-implemented property.
|
||||
/// </summary>
|
||||
AutoImplementedProperty = 6,
|
||||
|
||||
/// <summary>
|
||||
/// Entity (method) was skipped as it is native code.
|
||||
/// </summary>
|
||||
NativeCode = 7,
|
||||
|
||||
/// <summary>
|
||||
/// Entity (method) was skipped for other reasons.
|
||||
/// </summary>
|
||||
Unknown = 8,
|
||||
|
||||
/// <summary>
|
||||
/// Entity (dll) was skipped due to folder exclusion.
|
||||
/// </summary>
|
||||
FolderExclusion = 9,
|
||||
|
||||
/// <summary>
|
||||
/// Entity (method) was skipped due to being a delegate.
|
||||
/// </summary>
|
||||
Delegate = 10,
|
||||
|
||||
/// <summary>
|
||||
/// Entity (method) was skipped due to being an F# internal implementation
|
||||
/// detail (in either a record or discriminated union type).
|
||||
/// </summary>
|
||||
FSharpInternal = 11,
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3e49bf94f7d5348e2a48c3a09f3de201
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,103 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace OpenCover.Framework.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// A summary of results
|
||||
/// </summary>
|
||||
public class Summary
|
||||
{
|
||||
/// <summary>
|
||||
/// The number of sequence points
|
||||
/// </summary>
|
||||
[XmlAttribute("numSequencePoints")]
|
||||
public int NumSequencePoints { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The number of sequence points visited
|
||||
/// </summary>
|
||||
[XmlAttribute("visitedSequencePoints")]
|
||||
public int VisitedSequencePoints { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The number of branch points
|
||||
/// </summary>
|
||||
[XmlAttribute("numBranchPoints")]
|
||||
public int NumBranchPoints { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The number of branch points visited
|
||||
/// </summary>
|
||||
[XmlAttribute("visitedBranchPoints")]
|
||||
public int VisitedBranchPoints { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// What is the sequence coverage?
|
||||
/// </summary>
|
||||
/// <remarks>Rounded for ease</remarks>
|
||||
[XmlAttribute("sequenceCoverage")]
|
||||
public decimal SequenceCoverage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// What is the branch coverage?
|
||||
/// </summary>
|
||||
/// <remarks>Rounded for ease</remarks>
|
||||
[XmlAttribute("branchCoverage")]
|
||||
public decimal BranchCoverage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// What is the maximum cyclomatic complexity.
|
||||
/// </summary>
|
||||
/// <remarks>Calculated using the Gendarme rules library</remarks>
|
||||
[XmlAttribute("maxCyclomaticComplexity")]
|
||||
public int MaxCyclomaticComplexity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// What is the minimum cyclomatic complexity.
|
||||
/// </summary>
|
||||
/// <remarks>Calculated using the Gendarme rules library</remarks>
|
||||
[XmlAttribute("minCyclomaticComplexity")]
|
||||
public int MinCyclomaticComplexity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// What is the maximum crap score
|
||||
/// </summary>
|
||||
[XmlAttribute("maxCrapScore")]
|
||||
public decimal MaxCrapScore { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// What is the minimum crap score.
|
||||
/// </summary>
|
||||
[XmlAttribute("minCrapScore")]
|
||||
public decimal MinCrapScore { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// What is the number of visited classes
|
||||
/// </summary>
|
||||
[XmlAttribute("visitedClasses")]
|
||||
public int VisitedClasses { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// What is the total number of classes
|
||||
/// </summary>
|
||||
[XmlAttribute("numClasses")]
|
||||
public int NumClasses { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// What is the number of visited methods
|
||||
/// </summary>
|
||||
[XmlAttribute("visitedMethods")]
|
||||
public int VisitedMethods { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// What is the total number of methods
|
||||
/// </summary>
|
||||
[XmlAttribute("numMethods")]
|
||||
public int NumMethods { get; set; }
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f84724c9beb0444b0b1a7166317d7262
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,28 @@
|
||||
namespace OpenCover.Framework.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// A skipped entity that also carries a Summary object which is not
|
||||
/// always serialized
|
||||
/// </summary>
|
||||
public abstract class SummarySkippedEntity : SkippedEntity
|
||||
{
|
||||
/// <summary>
|
||||
/// Initialise
|
||||
/// </summary>
|
||||
protected SummarySkippedEntity()
|
||||
{
|
||||
Summary = new Summary();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A Summary of results for a entity
|
||||
/// </summary>
|
||||
public Summary Summary { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Control serialization of the Summary object
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool ShouldSerializeSummary() { return !ShouldSerializeSkippedDueTo(); }
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b1b80d503cba7422cb21829a6891cde2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,61 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace OpenCover.Framework.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// A reference to a tracked method
|
||||
/// </summary>
|
||||
public class TrackedMethodRef
|
||||
{
|
||||
/// <summary>
|
||||
/// unique id assigned
|
||||
/// </summary>
|
||||
[XmlAttribute("uid")]
|
||||
public UInt32 UniqueId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The visit count
|
||||
/// </summary>
|
||||
[XmlAttribute("vc")]
|
||||
public int VisitCount { get; set; }
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A method being tracked
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public sealed class TrackedMethod
|
||||
{
|
||||
/// <summary>
|
||||
/// unique id assigned
|
||||
/// </summary>
|
||||
[XmlAttribute("uid")]
|
||||
public UInt32 UniqueId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The MetadataToken used to identify this entity within the assembly
|
||||
/// </summary>
|
||||
[XmlAttribute("token")]
|
||||
public int MetadataToken { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The name of the method being tracked
|
||||
/// </summary>
|
||||
[XmlAttribute("name")]
|
||||
public string FullName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The reason/plugin why the method is being tracked
|
||||
/// </summary>
|
||||
[XmlAttribute("strategy")]
|
||||
public string Strategy { get; set; }
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d7c779bb30ff546c08fce46737f83ec5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b6c4c078b09304bfeaae896e2e4ffa9e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,130 @@
|
||||
//
|
||||
// ByteBuffer.cs
|
||||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@novell.com)
|
||||
//
|
||||
// (C) 2009 - 2010 Novell, Inc. (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace Mono.Reflection {
|
||||
|
||||
class ByteBuffer {
|
||||
|
||||
internal byte [] buffer;
|
||||
internal int position;
|
||||
|
||||
public ByteBuffer (byte [] buffer)
|
||||
{
|
||||
this.buffer = buffer;
|
||||
}
|
||||
|
||||
public byte ReadByte ()
|
||||
{
|
||||
CheckCanRead (1);
|
||||
return buffer [position++];
|
||||
}
|
||||
|
||||
public byte [] ReadBytes (int length)
|
||||
{
|
||||
CheckCanRead (length);
|
||||
var value = new byte [length];
|
||||
Buffer.BlockCopy (buffer, position, value, 0, length);
|
||||
position += length;
|
||||
return value;
|
||||
}
|
||||
|
||||
public short ReadInt16 ()
|
||||
{
|
||||
CheckCanRead (2);
|
||||
short value = (short) (buffer [position]
|
||||
| (buffer [position + 1] << 8));
|
||||
position += 2;
|
||||
return value;
|
||||
}
|
||||
|
||||
public int ReadInt32 ()
|
||||
{
|
||||
CheckCanRead (4);
|
||||
int value = buffer [position]
|
||||
| (buffer [position + 1] << 8)
|
||||
| (buffer [position + 2] << 16)
|
||||
| (buffer [position + 3] << 24);
|
||||
position += 4;
|
||||
return value;
|
||||
}
|
||||
|
||||
public long ReadInt64 ()
|
||||
{
|
||||
CheckCanRead (8);
|
||||
uint low = (uint) (buffer [position]
|
||||
| (buffer [position + 1] << 8)
|
||||
| (buffer [position + 2] << 16)
|
||||
| (buffer [position + 3] << 24));
|
||||
|
||||
uint high = (uint) (buffer [position + 4]
|
||||
| (buffer [position + 5] << 8)
|
||||
| (buffer [position + 6] << 16)
|
||||
| (buffer [position + 7] << 24));
|
||||
|
||||
long value = (((long) high) << 32) | low;
|
||||
position += 8;
|
||||
return value;
|
||||
}
|
||||
|
||||
public float ReadSingle ()
|
||||
{
|
||||
if (!BitConverter.IsLittleEndian) {
|
||||
var bytes = ReadBytes (4);
|
||||
Array.Reverse (bytes);
|
||||
return BitConverter.ToSingle (bytes, 0);
|
||||
}
|
||||
|
||||
CheckCanRead (4);
|
||||
float value = BitConverter.ToSingle (buffer, position);
|
||||
position += 4;
|
||||
return value;
|
||||
}
|
||||
|
||||
public double ReadDouble ()
|
||||
{
|
||||
if (!BitConverter.IsLittleEndian) {
|
||||
var bytes = ReadBytes (8);
|
||||
Array.Reverse (bytes);
|
||||
return BitConverter.ToDouble (bytes, 0);
|
||||
}
|
||||
|
||||
CheckCanRead (8);
|
||||
double value = BitConverter.ToDouble (buffer, position);
|
||||
position += 8;
|
||||
return value;
|
||||
}
|
||||
|
||||
void CheckCanRead (int count)
|
||||
{
|
||||
if (position + count > buffer.Length)
|
||||
throw new ArgumentOutOfRangeException ();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 68735f878b89447b4925a73a9074dfe9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,45 @@
|
||||
//
|
||||
// Disassembler.cs
|
||||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@novell.com)
|
||||
//
|
||||
// (C) 2009 - 2010 Novell, Inc. (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Mono.Reflection {
|
||||
|
||||
public static class Disassembler {
|
||||
|
||||
public static IList<Instruction> GetInstructions (this MethodBase self)
|
||||
{
|
||||
if (self == null)
|
||||
throw new ArgumentNullException ("self");
|
||||
|
||||
return MethodBodyReader.GetInstructions (self).AsReadOnly ();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f2c36198237a34870a85b171e9097887
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,156 @@
|
||||
//
|
||||
// Instruction.cs
|
||||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@novell.com)
|
||||
//
|
||||
// (C) 2009 - 2010 Novell, Inc. (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Reflection.Emit;
|
||||
using System.Text;
|
||||
|
||||
namespace Mono.Reflection {
|
||||
|
||||
public sealed class Instruction {
|
||||
|
||||
int offset;
|
||||
OpCode opcode;
|
||||
object operand;
|
||||
|
||||
Instruction previous;
|
||||
Instruction next;
|
||||
|
||||
public int Offset {
|
||||
get { return offset; }
|
||||
}
|
||||
|
||||
public OpCode OpCode {
|
||||
get { return opcode; }
|
||||
}
|
||||
|
||||
public object Operand {
|
||||
get { return operand; }
|
||||
internal set { operand = value; }
|
||||
}
|
||||
|
||||
public Instruction Previous {
|
||||
get { return previous; }
|
||||
internal set { previous = value; }
|
||||
}
|
||||
|
||||
public Instruction Next {
|
||||
get { return next; }
|
||||
internal set { next = value; }
|
||||
}
|
||||
|
||||
public int Size {
|
||||
get {
|
||||
int size = opcode.Size;
|
||||
|
||||
switch (opcode.OperandType) {
|
||||
case OperandType.InlineSwitch:
|
||||
size += (1 + ((Instruction []) operand).Length) * 4;
|
||||
break;
|
||||
case OperandType.InlineI8:
|
||||
case OperandType.InlineR:
|
||||
size += 8;
|
||||
break;
|
||||
case OperandType.InlineBrTarget:
|
||||
case OperandType.InlineField:
|
||||
case OperandType.InlineI:
|
||||
case OperandType.InlineMethod:
|
||||
case OperandType.InlineString:
|
||||
case OperandType.InlineTok:
|
||||
case OperandType.InlineType:
|
||||
case OperandType.ShortInlineR:
|
||||
size += 4;
|
||||
break;
|
||||
case OperandType.InlineVar:
|
||||
size += 2;
|
||||
break;
|
||||
case OperandType.ShortInlineBrTarget:
|
||||
case OperandType.ShortInlineI:
|
||||
case OperandType.ShortInlineVar:
|
||||
size += 1;
|
||||
break;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
internal Instruction (int offset, OpCode opcode)
|
||||
{
|
||||
this.offset = offset;
|
||||
this.opcode = opcode;
|
||||
}
|
||||
|
||||
public override string ToString ()
|
||||
{
|
||||
var instruction = new StringBuilder ();
|
||||
|
||||
AppendLabel (instruction, this);
|
||||
instruction.Append (':');
|
||||
instruction.Append (' ');
|
||||
instruction.Append (opcode.Name);
|
||||
|
||||
if (operand == null)
|
||||
return instruction.ToString ();
|
||||
|
||||
instruction.Append (' ');
|
||||
|
||||
switch (opcode.OperandType) {
|
||||
case OperandType.ShortInlineBrTarget:
|
||||
case OperandType.InlineBrTarget:
|
||||
AppendLabel (instruction, (Instruction) operand);
|
||||
break;
|
||||
case OperandType.InlineSwitch:
|
||||
var labels = (Instruction []) operand;
|
||||
for (int i = 0; i < labels.Length; i++) {
|
||||
if (i > 0)
|
||||
instruction.Append (',');
|
||||
|
||||
AppendLabel (instruction, labels [i]);
|
||||
}
|
||||
break;
|
||||
case OperandType.InlineString:
|
||||
instruction.Append ('\"');
|
||||
instruction.Append (operand);
|
||||
instruction.Append ('\"');
|
||||
break;
|
||||
default:
|
||||
instruction.Append (operand);
|
||||
break;
|
||||
}
|
||||
|
||||
return instruction.ToString ();
|
||||
}
|
||||
|
||||
static void AppendLabel (StringBuilder builder, Instruction instruction)
|
||||
{
|
||||
builder.Append ("IL_");
|
||||
builder.Append (instruction.offset.ToString ("x4"));
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0c54348b43e9e464fa20499d8315beed
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,306 @@
|
||||
//
|
||||
// MethodBodyReader.cs
|
||||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@novell.com)
|
||||
//
|
||||
// (C) 2009 - 2010 Novell, Inc. (http://www.novell.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Mono.Reflection {
|
||||
|
||||
class MethodBodyReader {
|
||||
|
||||
static readonly OpCode [] one_byte_opcodes;
|
||||
static readonly OpCode [] two_bytes_opcodes;
|
||||
|
||||
static MethodBodyReader ()
|
||||
{
|
||||
one_byte_opcodes = new OpCode [0xe1];
|
||||
two_bytes_opcodes = new OpCode [0x1f];
|
||||
|
||||
var fields = typeof (OpCodes).GetFields (
|
||||
BindingFlags.Public | BindingFlags.Static);
|
||||
|
||||
foreach (var field in fields) {
|
||||
var opcode = (OpCode) field.GetValue (null);
|
||||
if (opcode.OpCodeType == OpCodeType.Nternal)
|
||||
continue;
|
||||
|
||||
if (opcode.Size == 1)
|
||||
one_byte_opcodes [opcode.Value] = opcode;
|
||||
else
|
||||
two_bytes_opcodes [opcode.Value & 0xff] = opcode;
|
||||
}
|
||||
}
|
||||
|
||||
readonly MethodBase method;
|
||||
readonly MethodBody body;
|
||||
readonly Module module;
|
||||
readonly Type [] type_arguments;
|
||||
readonly Type [] method_arguments;
|
||||
readonly ByteBuffer il;
|
||||
readonly ParameterInfo this_parameter;
|
||||
readonly ParameterInfo [] parameters;
|
||||
readonly IList<LocalVariableInfo> locals;
|
||||
readonly List<Instruction> instructions;
|
||||
|
||||
MethodBodyReader (MethodBase method)
|
||||
{
|
||||
this.method = method;
|
||||
|
||||
this.body = method.GetMethodBody ();
|
||||
if (this.body == null)
|
||||
throw new ArgumentException ("Method has no body");
|
||||
|
||||
var bytes = body.GetILAsByteArray ();
|
||||
if (bytes == null)
|
||||
throw new ArgumentException ("Can not get the body of the method");
|
||||
|
||||
if (!(method is ConstructorInfo))
|
||||
method_arguments = method.GetGenericArguments ();
|
||||
|
||||
if (method.DeclaringType != null)
|
||||
type_arguments = method.DeclaringType.GetGenericArguments ();
|
||||
|
||||
if (!method.IsStatic)
|
||||
this.this_parameter = new ThisParameter (method);
|
||||
this.parameters = method.GetParameters ();
|
||||
this.locals = body.LocalVariables;
|
||||
this.module = method.Module;
|
||||
this.il = new ByteBuffer (bytes);
|
||||
this.instructions = new List<Instruction> ((bytes.Length + 1) / 2);
|
||||
}
|
||||
|
||||
void ReadInstructions ()
|
||||
{
|
||||
Instruction previous = null;
|
||||
|
||||
while (il.position < il.buffer.Length) {
|
||||
var instruction = new Instruction (il.position, ReadOpCode ());
|
||||
|
||||
ReadOperand (instruction);
|
||||
|
||||
if (previous != null) {
|
||||
instruction.Previous = previous;
|
||||
previous.Next = instruction;
|
||||
}
|
||||
|
||||
instructions.Add (instruction);
|
||||
previous = instruction;
|
||||
}
|
||||
|
||||
ResolveBranches ();
|
||||
}
|
||||
|
||||
void ReadOperand (Instruction instruction)
|
||||
{
|
||||
switch (instruction.OpCode.OperandType) {
|
||||
case OperandType.InlineNone:
|
||||
break;
|
||||
case OperandType.InlineSwitch:
|
||||
int length = il.ReadInt32 ();
|
||||
int base_offset = il.position + (4 * length);
|
||||
int [] branches = new int [length];
|
||||
for (int i = 0; i < length; i++)
|
||||
branches [i] = il.ReadInt32 () + base_offset;
|
||||
|
||||
instruction.Operand = branches;
|
||||
break;
|
||||
case OperandType.ShortInlineBrTarget:
|
||||
instruction.Operand = (((sbyte) il.ReadByte ()) + il.position);
|
||||
break;
|
||||
case OperandType.InlineBrTarget:
|
||||
instruction.Operand = il.ReadInt32 () + il.position;
|
||||
break;
|
||||
case OperandType.ShortInlineI:
|
||||
if (instruction.OpCode == OpCodes.Ldc_I4_S)
|
||||
instruction.Operand = (sbyte) il.ReadByte ();
|
||||
else
|
||||
instruction.Operand = il.ReadByte ();
|
||||
break;
|
||||
case OperandType.InlineI:
|
||||
instruction.Operand = il.ReadInt32 ();
|
||||
break;
|
||||
case OperandType.ShortInlineR:
|
||||
instruction.Operand = il.ReadSingle ();
|
||||
break;
|
||||
case OperandType.InlineR:
|
||||
instruction.Operand = il.ReadDouble ();
|
||||
break;
|
||||
case OperandType.InlineI8:
|
||||
instruction.Operand = il.ReadInt64 ();
|
||||
break;
|
||||
case OperandType.InlineSig:
|
||||
instruction.Operand = module.ResolveSignature (il.ReadInt32 ());
|
||||
break;
|
||||
case OperandType.InlineString:
|
||||
instruction.Operand = module.ResolveString (il.ReadInt32 ());
|
||||
break;
|
||||
case OperandType.InlineTok:
|
||||
{
|
||||
int metaDataToken = il.ReadInt32 ();
|
||||
try
|
||||
{
|
||||
instruction.Operand = module.ResolveMember (metaDataToken, type_arguments, method_arguments);
|
||||
}
|
||||
catch(BadImageFormatException)
|
||||
{
|
||||
instruction.Operand = module.ResolveMember (metaDataToken);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OperandType.InlineType:
|
||||
instruction.Operand = module.ResolveType (il.ReadInt32 (), type_arguments, method_arguments);
|
||||
break;
|
||||
case OperandType.InlineMethod:
|
||||
{
|
||||
int metaDataToken = il.ReadInt32 ();
|
||||
try
|
||||
{
|
||||
instruction.Operand = module.ResolveMethod (metaDataToken, type_arguments, method_arguments);
|
||||
}
|
||||
catch(TypeLoadException)
|
||||
{
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OperandType.InlineField:
|
||||
instruction.Operand = module.ResolveField (il.ReadInt32 (), type_arguments, method_arguments);
|
||||
break;
|
||||
case OperandType.ShortInlineVar:
|
||||
instruction.Operand = GetVariable (instruction, il.ReadByte ());
|
||||
break;
|
||||
case OperandType.InlineVar:
|
||||
instruction.Operand = GetVariable (instruction, il.ReadInt16 ());
|
||||
break;
|
||||
default:
|
||||
throw new NotSupportedException ();
|
||||
}
|
||||
}
|
||||
|
||||
void ResolveBranches ()
|
||||
{
|
||||
foreach (var instruction in instructions) {
|
||||
switch (instruction.OpCode.OperandType) {
|
||||
case OperandType.ShortInlineBrTarget:
|
||||
case OperandType.InlineBrTarget:
|
||||
instruction.Operand = GetInstruction (instructions, (int) instruction.Operand);
|
||||
break;
|
||||
case OperandType.InlineSwitch:
|
||||
var offsets = (int []) instruction.Operand;
|
||||
var branches = new Instruction [offsets.Length];
|
||||
for (int j = 0; j < offsets.Length; j++)
|
||||
branches [j] = GetInstruction (instructions, offsets [j]);
|
||||
|
||||
instruction.Operand = branches;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Instruction GetInstruction (List<Instruction> instructions, int offset)
|
||||
{
|
||||
var size = instructions.Count;
|
||||
if (offset < 0 || offset > instructions [size - 1].Offset)
|
||||
return null;
|
||||
|
||||
int min = 0;
|
||||
int max = size - 1;
|
||||
while (min <= max) {
|
||||
int mid = min + ((max - min) / 2);
|
||||
var instruction = instructions [mid];
|
||||
var instruction_offset = instruction.Offset;
|
||||
|
||||
if (offset == instruction_offset)
|
||||
return instruction;
|
||||
|
||||
if (offset < instruction_offset)
|
||||
max = mid - 1;
|
||||
else
|
||||
min = mid + 1;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
object GetVariable (Instruction instruction, int index)
|
||||
{
|
||||
return TargetsLocalVariable (instruction.OpCode)
|
||||
? (object) GetLocalVariable (index)
|
||||
: (object) GetParameter (index);
|
||||
}
|
||||
|
||||
static bool TargetsLocalVariable (OpCode opcode)
|
||||
{
|
||||
return opcode.Name.Contains ("loc");
|
||||
}
|
||||
|
||||
LocalVariableInfo GetLocalVariable (int index)
|
||||
{
|
||||
return locals [index];
|
||||
}
|
||||
|
||||
ParameterInfo GetParameter (int index)
|
||||
{
|
||||
if (method.IsStatic)
|
||||
return parameters [index];
|
||||
|
||||
if (index == 0)
|
||||
return this_parameter;
|
||||
|
||||
return parameters [index - 1];
|
||||
}
|
||||
|
||||
OpCode ReadOpCode ()
|
||||
{
|
||||
byte op = il.ReadByte ();
|
||||
return op != 0xfe
|
||||
? one_byte_opcodes [op]
|
||||
: two_bytes_opcodes [il.ReadByte ()];
|
||||
}
|
||||
|
||||
public static List<Instruction> GetInstructions (MethodBase method)
|
||||
{
|
||||
var reader = new MethodBodyReader (method);
|
||||
reader.ReadInstructions ();
|
||||
return reader.instructions;
|
||||
}
|
||||
|
||||
class ThisParameter : ParameterInfo
|
||||
{
|
||||
public ThisParameter (MethodBase method)
|
||||
{
|
||||
this.MemberImpl = method;
|
||||
this.ClassImpl = method.DeclaringType;
|
||||
this.NameImpl = "this";
|
||||
this.PositionImpl = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1a8056948ac804bf891bd101b3216a55
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "Unity.TestTools.CodeCoverage.Editor.OpenCover.Mono.Reflection",
|
||||
"references": [],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": []
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eecdf9bdfcb2949619db458f3e24c5e2
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 258e29582df66a741937fe410463ad97
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,75 @@
|
||||
namespace UnityEditor.TestTools.CodeCoverage.OpenCover
|
||||
{
|
||||
internal class OpenCoverReporterFilter : ICoverageReporterFilter
|
||||
{
|
||||
private AssemblyFiltering m_AssemblyFiltering;
|
||||
private PathFiltering m_PathFiltering;
|
||||
|
||||
public void SetupFiltering()
|
||||
{
|
||||
if (!CommandLineManager.instance.runFromCommandLine || !CommandLineManager.instance.assemblyFiltersSpecified)
|
||||
{
|
||||
m_AssemblyFiltering = new AssemblyFiltering();
|
||||
|
||||
string includeAssemblies = CoveragePreferences.instance.GetString("IncludeAssemblies", AssemblyFiltering.GetUserOnlyAssembliesString());
|
||||
m_AssemblyFiltering.Parse(includeAssemblies, string.Empty);
|
||||
}
|
||||
|
||||
if (!CommandLineManager.instance.runFromCommandLine || !CommandLineManager.instance.pathFiltersSpecified)
|
||||
{
|
||||
m_PathFiltering = new PathFiltering();
|
||||
|
||||
string pathsToInclude = CoveragePreferences.instance.GetStringForPaths("PathsToInclude", string.Empty);
|
||||
string pathsToExclude = CoveragePreferences.instance.GetStringForPaths("PathsToExclude", string.Empty);
|
||||
|
||||
m_PathFiltering.Parse(pathsToInclude, pathsToExclude);
|
||||
}
|
||||
}
|
||||
|
||||
public AssemblyFiltering GetAssemblyFiltering()
|
||||
{
|
||||
if (CommandLineManager.instance.batchmode && !CommandLineManager.instance.useProjectSettings)
|
||||
return CommandLineManager.instance.assemblyFiltering;
|
||||
else
|
||||
return CommandLineManager.instance.assemblyFiltersSpecified ?
|
||||
CommandLineManager.instance.assemblyFiltering :
|
||||
m_AssemblyFiltering;
|
||||
}
|
||||
|
||||
public bool ShouldProcessAssembly(string assemblyName)
|
||||
{
|
||||
return GetAssemblyFiltering().IsAssemblyIncluded(assemblyName);
|
||||
}
|
||||
|
||||
public PathFiltering GetPathFiltering()
|
||||
{
|
||||
if (CommandLineManager.instance.batchmode && !CommandLineManager.instance.useProjectSettings)
|
||||
return CommandLineManager.instance.pathFiltering;
|
||||
else
|
||||
return CommandLineManager.instance.pathFiltersSpecified ?
|
||||
CommandLineManager.instance.pathFiltering :
|
||||
m_PathFiltering;
|
||||
}
|
||||
|
||||
public bool ShouldProcessFile(string filename)
|
||||
{
|
||||
return GetPathFiltering().IsPathIncluded(filename);
|
||||
}
|
||||
|
||||
public bool ShouldGenerateAdditionalMetrics()
|
||||
{
|
||||
if (CommandLineManager.instance.batchmode && !CommandLineManager.instance.useProjectSettings)
|
||||
return CommandLineManager.instance.generateAdditionalMetrics;
|
||||
else
|
||||
return CommandLineManager.instance.generateAdditionalMetrics || CoveragePreferences.instance.GetBool("GenerateAdditionalMetrics", false);
|
||||
}
|
||||
|
||||
public bool ShouldGenerateTestReferences()
|
||||
{
|
||||
if (CommandLineManager.instance.batchmode && !CommandLineManager.instance.useProjectSettings)
|
||||
return CommandLineManager.instance.generateTestReferences;
|
||||
else
|
||||
return CommandLineManager.instance.generateTestReferences || CoveragePreferences.instance.GetBool("GenerateTestReferences", false);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 04c157fc0c43e40708bcbe2aa8738140
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user