From 199f74e3dc83f0dc6ec2b59b1129ef8461906882 Mon Sep 17 00:00:00 2001 From: Oluwatoni Solarin-Sodara Date: Sun, 20 May 2018 18:16:43 +0100 Subject: [PATCH 1/2] ensure autogenerated delegate types are also excluded --- src/coverlet.core/Attributes/ExcludeFromCoverage.cs | 2 +- src/coverlet.core/Instrumentation/Instrumenter.cs | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/coverlet.core/Attributes/ExcludeFromCoverage.cs b/src/coverlet.core/Attributes/ExcludeFromCoverage.cs index e2ac0e523..0fb1ef097 100644 --- a/src/coverlet.core/Attributes/ExcludeFromCoverage.cs +++ b/src/coverlet.core/Attributes/ExcludeFromCoverage.cs @@ -2,6 +2,6 @@ namespace Coverlet.Core.Attributes { - [AttributeUsage(AttributeTargets.Property | AttributeTargets.Method | AttributeTargets.Constructor)] + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class)] public sealed class ExcludeFromCoverageAttribute : Attribute { } } \ No newline at end of file diff --git a/src/coverlet.core/Instrumentation/Instrumenter.cs b/src/coverlet.core/Instrumentation/Instrumenter.cs index dfc853204..65f1b6e57 100644 --- a/src/coverlet.core/Instrumentation/Instrumenter.cs +++ b/src/coverlet.core/Instrumentation/Instrumenter.cs @@ -74,8 +74,12 @@ private void InstrumentModule() private void InstrumentType(TypeDefinition type) { - if (type.CustomAttributes.Any(IsExcludeAttribute) - || InstrumentationHelper.IsTypeExcluded(_module, type.FullName, _filters)) + TypeDefinition actualType = type; + if (type.FullName.Contains("/")) + actualType = type.Module.GetTypes().FirstOrDefault(t => t.FullName == type.FullName.Split('/')[0]); + + if (actualType.CustomAttributes.Any(IsExcludeAttribute) + || InstrumentationHelper.IsTypeExcluded(_module, actualType.FullName, _filters)) return; foreach (var method in type.Methods) @@ -116,7 +120,7 @@ private void InstrumentIL(MethodDefinition method) var instruction = processor.Body.Instructions[index]; var sequencePoint = method.DebugInformation.GetSequencePoint(instruction); var targetedBranchPoints = branchPoints.Where(p => p.EndOffset == instruction.Offset); - + if (sequencePoint != null && !sequencePoint.IsHidden) { var target = AddInstrumentationCode(method, processor, instruction, sequencePoint); @@ -139,7 +143,7 @@ private void InstrumentIL(MethodDefinition method) */ if (_branchTarget.StartLine == -1 || _branchTarget.Document == null) continue; - + var target = AddInstrumentationCode(method, processor, instruction, _branchTarget); foreach (var _instruction in processor.Body.Instructions) ReplaceInstructionTarget(_instruction, instruction, target); From b0817715307a47d817c8eff173b30443a42ec25a Mon Sep 17 00:00:00 2001 From: Oluwatoni Solarin-Sodara Date: Sat, 26 May 2018 22:43:09 +0100 Subject: [PATCH 2/2] exclude local methods in excluded methods --- .../Helpers/InstrumentationHelper.cs | 3 ++ .../Instrumentation/Instrumenter.cs | 29 +++++++++++-------- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/coverlet.core/Helpers/InstrumentationHelper.cs b/src/coverlet.core/Helpers/InstrumentationHelper.cs index 5319da9a2..f870ef042 100644 --- a/src/coverlet.core/Helpers/InstrumentationHelper.cs +++ b/src/coverlet.core/Helpers/InstrumentationHelper.cs @@ -165,6 +165,9 @@ public static bool IsTypeExcluded(string module, string type, string[] filters) return false; } + public static bool IsLocalMethod(string method) + => new Regex(WildcardToRegex("<*>*__*|*")).IsMatch(method); + public static string[] GetExcludedFiles(string[] rules) { const string RELATIVE_KEY = nameof(RELATIVE_KEY); diff --git a/src/coverlet.core/Instrumentation/Instrumenter.cs b/src/coverlet.core/Instrumentation/Instrumenter.cs index 65f1b6e57..fdbd56c97 100644 --- a/src/coverlet.core/Instrumentation/Instrumenter.cs +++ b/src/coverlet.core/Instrumentation/Instrumenter.cs @@ -60,11 +60,19 @@ private void InstrumentModule() { resolver.AddSearchDirectory(Path.GetDirectoryName(_module)); var parameters = new ReaderParameters { ReadSymbols = true, AssemblyResolver = resolver }; + using (var module = ModuleDefinition.ReadModule(stream, parameters)) { - foreach (var type in module.GetTypes()) + var types = module.GetTypes(); + foreach (var type in types) { - InstrumentType(type); + TypeDefinition actualType = type; + if (type.FullName.Contains("/")) + actualType = types.FirstOrDefault(t => t.FullName == type.FullName.Split('/')[0]); + + if (!actualType.CustomAttributes.Any(IsExcludeAttribute) + && !InstrumentationHelper.IsTypeExcluded(_module, actualType.FullName, _filters)) + InstrumentType(type); } module.Write(stream); @@ -74,17 +82,14 @@ private void InstrumentModule() private void InstrumentType(TypeDefinition type) { - TypeDefinition actualType = type; - if (type.FullName.Contains("/")) - actualType = type.Module.GetTypes().FirstOrDefault(t => t.FullName == type.FullName.Split('/')[0]); - - if (actualType.CustomAttributes.Any(IsExcludeAttribute) - || InstrumentationHelper.IsTypeExcluded(_module, actualType.FullName, _filters)) - return; - - foreach (var method in type.Methods) + var methods = type.GetMethods(); + foreach (var method in methods) { - if (!method.CustomAttributes.Any(IsExcludeAttribute)) + MethodDefinition actualMethod = method; + if (InstrumentationHelper.IsLocalMethod(method.Name)) + actualMethod = methods.FirstOrDefault(m => m.Name == method.Name.Split('>')[0].Substring(1)) ?? method; + + if (!actualMethod.CustomAttributes.Any(IsExcludeAttribute)) InstrumentMethod(method); } }