Skip to content
This repository was archived by the owner on Nov 15, 2021. It is now read-only.

Commit 4ce5341

Browse files
committed
#169 - skip auto implemented properties
1 parent 73f7432 commit 4ce5341

File tree

12 files changed

+327
-176
lines changed

12 files changed

+327
-176
lines changed
1.49 KB
Binary file not shown.

main/OpenCover.Documentation/Usage.rtf

+174-160
Large diffs are not rendered by default.

main/OpenCover.Framework/CommandLineParser.cs

+31
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,29 @@
1616

1717
namespace OpenCover.Framework
1818
{
19+
/// <summary>
20+
/// What registration method
21+
/// </summary>
1922
public enum Registration
2023
{
24+
/// <summary>
25+
/// normal
26+
/// </summary>
2127
Normal,
28+
29+
/// <summary>
30+
/// user
31+
/// </summary>
2232
User,
33+
34+
/// <summary>
35+
/// use path to 32 bit profiler
36+
/// </summary>
2337
Path32,
38+
39+
/// <summary>
40+
/// use path to 64 bit profiler
41+
/// </summary>
2442
Path64
2543
}
2644

@@ -74,6 +92,7 @@ public string Usage()
7492
builder.AppendLine(" [-service]");
7593
builder.AppendLine(" [-threshold:<max count>]");
7694
builder.AppendLine(" [-enableperformancecounters]");
95+
builder.AppendLine(" [-skipautoprops]");
7796
builder.AppendLine(" [-oldStyle]");
7897
builder.AppendLine("or");
7998
builder.AppendLine(" -?");
@@ -177,6 +196,9 @@ public void ExtractAndValidateArguments()
177196
Threshold = ExtractValue<ulong>("threshold", () =>
178197
{ throw new InvalidOperationException("The threshold must be an integer"); });
179198
break;
199+
case "skipautoprops":
200+
SkipAutoImplementedProperties = true;
201+
break;
180202
case "?":
181203
PrintUsage = true;
182204
break;
@@ -235,6 +257,7 @@ private static List<SkippedMethod> ExtractSkipped(string skipped)
235257
list.Add(SkippedMethod.File);
236258
list.Add(SkippedMethod.Filter);
237259
list.Add(SkippedMethod.MissingPdb);
260+
list.Add(SkippedMethod.AutoImplementedProperty);
238261
break;
239262
default:
240263
SkippedMethod result;
@@ -259,6 +282,11 @@ private static List<SkippedMethod> ExtractSkipped(string skipped)
259282
/// </summary>
260283
public Registration Registration { get; private set; }
261284

285+
/// <summary>
286+
/// whether auto-implemented properties sould be skipped
287+
/// </summary>
288+
public bool SkipAutoImplementedProperties { get; private set; }
289+
262290
/// <summary>
263291
/// The target executable that is to be profiles
264292
/// </summary>
@@ -344,6 +372,9 @@ private static List<SkippedMethod> ExtractSkipped(string skipped)
344372
/// </summary>
345373
public ulong Threshold { get; private set; }
346374

375+
/// <summary>
376+
/// activate trace by test feature
377+
/// </summary>
347378
public bool TraceByTest { get; private set; }
348379

349380
/// <summary>

main/OpenCover.Framework/Filter.cs

+16
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System.Collections.Generic;
88
using System.Diagnostics;
99
using System.Linq;
10+
using System.Runtime.CompilerServices;
1011
using System.Text;
1112
using System.Text.RegularExpressions;
1213
using Mono.Cecil;
@@ -80,6 +81,13 @@ public interface IFilter
8081
/// </summary>
8182
/// <param name="testFilters"></param>
8283
void AddTestFileFilters(string[] testFilters);
84+
85+
/// <summary>
86+
/// Is the method an auto-implemented property get/set
87+
/// </summary>
88+
/// <param name="method"></param>
89+
/// <returns></returns>
90+
bool IsAutoImplementedProperty(MethodDefinition method);
8391
}
8492

8593
internal static class FilterHelper
@@ -328,5 +336,13 @@ public void AddTestFileFilters(string[] testFilters)
328336
}
329337
}
330338

339+
public bool IsAutoImplementedProperty(MethodDefinition method)
340+
{
341+
if ((method.IsSetter || method.IsGetter) && method.HasCustomAttributes)
342+
{
343+
return method.CustomAttributes.Any(x => x.AttributeType.FullName == typeof(CompilerGeneratedAttribute).FullName);
344+
}
345+
return false;
346+
}
331347
}
332348
}

main/OpenCover.Framework/ICommandLine.cs

+5
Original file line numberDiff line numberDiff line change
@@ -48,5 +48,10 @@ public interface ICommandLine
4848
/// The type of profiler registration
4949
/// </summary>
5050
Registration Registration { get; }
51+
52+
/// <summary>
53+
/// Should auto implemented properties be skipped
54+
/// </summary>
55+
bool SkipAutoImplementedProperties { get; }
5156
}
5257
}

main/OpenCover.Framework/Model/SkippedMethod.cs

+5
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,10 @@ public enum SkippedMethod
2929
/// Entity was skipped by inference (usually related to File filters)
3030
/// </summary>
3131
Inferred = 5,
32+
33+
/// <summary>
34+
/// Entity (method) was skipped as it is an auto-implemented property.
35+
/// </summary>
36+
AutoImplementedProperty = 6,
3237
}
3338
}

main/OpenCover.Framework/Persistance/BasePersistance.cs

+4
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,10 @@ public virtual void Commit()
9494
RemoveSkippedMethods(SkippedMethod.Attribute);
9595
RemoveEmptyClasses();
9696
break;
97+
case SkippedMethod.AutoImplementedProperty:
98+
RemoveSkippedMethods(SkippedMethod.Attribute);
99+
RemoveEmptyClasses();
100+
break;
97101
}
98102
}
99103
}

main/OpenCover.Framework/Symbols/CecilSymbolManager.cs

+14-12
Original file line numberDiff line numberDiff line change
@@ -176,15 +176,15 @@ private static void GetInstrumentableTypes(IEnumerable<TypeDefinition> typeDefin
176176
}
177177
if (typeDefinition.HasNestedTypes)
178178
GetInstrumentableTypes(typeDefinition.NestedTypes, classes, filter, moduleName);
179-
}
179+
}
180180
}
181181

182182

183183
public Method[] GetMethodsForType(Class type, File[] files)
184184
{
185185
var methods = new List<Method>();
186186
IEnumerable<TypeDefinition> typeDefinitions = SourceAssembly.MainModule.Types;
187-
GetMethodsForType(typeDefinitions, type.FullName, methods, files, _filter);
187+
GetMethodsForType(typeDefinitions, type.FullName, methods, files, _filter, _commandLine);
188188
return methods.ToArray();
189189
}
190190

@@ -201,54 +201,54 @@ private static string GetFirstFile(MethodDefinition definition)
201201
return null;
202202
}
203203

204-
private static void GetMethodsForType(IEnumerable<TypeDefinition> typeDefinitions, string fullName, List<Method> methods, File[] files, IFilter filter)
204+
private static void GetMethodsForType(IEnumerable<TypeDefinition> typeDefinitions, string fullName, List<Method> methods, File[] files, IFilter filter,ICommandLine commandLine)
205205
{
206206
foreach (var typeDefinition in typeDefinitions)
207207
{
208208
if (typeDefinition.FullName == fullName)
209209
{
210-
BuildPropertyMethods(methods, files, filter, typeDefinition);
211-
BuildMethods(methods, files, filter, typeDefinition);
210+
BuildPropertyMethods(methods, files, filter, typeDefinition, commandLine);
211+
BuildMethods(methods, files, filter, typeDefinition, commandLine);
212212
}
213213
if (typeDefinition.HasNestedTypes)
214-
GetMethodsForType(typeDefinition.NestedTypes, fullName, methods, files, filter);
214+
GetMethodsForType(typeDefinition.NestedTypes, fullName, methods, files, filter, commandLine);
215215
}
216216
}
217217

218-
private static void BuildMethods(ICollection<Method> methods, File[] files, IFilter filter, TypeDefinition typeDefinition)
218+
private static void BuildMethods(ICollection<Method> methods, File[] files, IFilter filter, TypeDefinition typeDefinition, ICommandLine commandLine)
219219
{
220220
foreach (var methodDefinition in typeDefinition.Methods)
221221
{
222222
if (methodDefinition.IsAbstract) continue;
223223
if (methodDefinition.IsGetter) continue;
224224
if (methodDefinition.IsSetter) continue;
225225

226-
var method = BuildMethod(files, filter, methodDefinition, false);
226+
var method = BuildMethod(files, filter, methodDefinition, false, commandLine);
227227
methods.Add(method);
228228
}
229229
}
230230

231-
private static void BuildPropertyMethods(ICollection<Method> methods, File[] files, IFilter filter, TypeDefinition typeDefinition)
231+
private static void BuildPropertyMethods(ICollection<Method> methods, File[] files, IFilter filter, TypeDefinition typeDefinition, ICommandLine commandLine)
232232
{
233233
foreach (var propertyDefinition in typeDefinition.Properties)
234234
{
235235
var skipped = filter.ExcludeByAttribute(propertyDefinition);
236236

237237
if (propertyDefinition.GetMethod != null && !propertyDefinition.GetMethod.IsAbstract)
238238
{
239-
var method = BuildMethod(files, filter, propertyDefinition.GetMethod, skipped);
239+
var method = BuildMethod(files, filter, propertyDefinition.GetMethod, skipped, commandLine);
240240
methods.Add(method);
241241
}
242242

243243
if (propertyDefinition.SetMethod != null && !propertyDefinition.SetMethod.IsAbstract)
244244
{
245-
var method = BuildMethod(files, filter, propertyDefinition.SetMethod, skipped);
245+
var method = BuildMethod(files, filter, propertyDefinition.SetMethod, skipped, commandLine);
246246
methods.Add(method);
247247
}
248248
}
249249
}
250250

251-
private static Method BuildMethod(IEnumerable<File> files, IFilter filter, MethodDefinition methodDefinition, bool alreadySkippedDueToAttr)
251+
private static Method BuildMethod(IEnumerable<File> files, IFilter filter, MethodDefinition methodDefinition, bool alreadySkippedDueToAttr, ICommandLine commandLine)
252252
{
253253
var method = new Method();
254254
method.Name = methodDefinition.FullName;
@@ -262,6 +262,8 @@ private static Method BuildMethod(IEnumerable<File> files, IFilter filter, Metho
262262
method.MarkAsSkipped(SkippedMethod.Attribute);
263263
else if (filter.ExcludeByFile(GetFirstFile(methodDefinition)))
264264
method.MarkAsSkipped(SkippedMethod.File);
265+
else if (commandLine.SkipAutoImplementedProperties && filter.IsAutoImplementedProperty(methodDefinition))
266+
method.MarkAsSkipped(SkippedMethod.AutoImplementedProperty);
265267

266268
var definition = methodDefinition;
267269
method.FileRef = files.Where(x => x.FullPath == GetFirstFile(definition))

main/OpenCover.Test/Framework/CommandLineParserTests.cs

+15-3
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public void ParserHasKnownDefaultArguments()
2929
Assert.IsFalse(parser.MergeByHash);
3030
Assert.IsFalse(parser.EnablePerformanceCounters);
3131
Assert.IsFalse(parser.TraceByTest);
32+
Assert.IsFalse(parser.SkipAutoImplementedProperties);
3233

3334
}
3435

@@ -539,7 +540,7 @@ public void ExtractsHideSkipped_ConvertsAll()
539540
parser.ExtractAndValidateArguments();
540541

541542
// assert
542-
Assert.AreEqual(4, parser.HideSkipped.Distinct().Count());
543+
Assert.AreEqual(5, parser.HideSkipped.Distinct().Count());
543544
}
544545

545546
[Test]
@@ -551,7 +552,7 @@ public void ExtractsHideSkipped_Merges_AllFile()
551552
parser.ExtractAndValidateArguments();
552553

553554
// assert
554-
Assert.AreEqual(4, parser.HideSkipped.Distinct().Count());
555+
Assert.AreEqual(5, parser.HideSkipped.Distinct().Count());
555556
}
556557

557558
[Test]
@@ -575,8 +576,19 @@ public void ExtractsHideSkipped_DefaultsToAll()
575576
parser.ExtractAndValidateArguments();
576577

577578
// assert
578-
Assert.AreEqual(4, parser.HideSkipped.Distinct().Count());
579+
Assert.AreEqual(5, parser.HideSkipped.Distinct().Count());
579580
}
580581

582+
[Test]
583+
public void Extracts_SkipAutoImplementedProperties()
584+
{
585+
// arrange
586+
var parser = new CommandLineParser(new[] { "-skipautoprops", RequiredArgs });
587+
588+
parser.ExtractAndValidateArguments();
589+
590+
// assert
591+
Assert.IsTrue(parser.SkipAutoImplementedProperties);
592+
}
581593
}
582594
}

main/OpenCover.Test/Framework/FilterTests.cs

+29-1
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,35 @@ public void Handles_Issue117()
546546
mockDefinition.SetupGet(x => x.Name).Returns("<>f_ddd");
547547
mockDefinition.SetupGet(x => x.DeclaringType).Returns(new TypeDefinition("","f_ddd", TypeAttributes.Public));
548548

549-
filter.ExcludeByAttribute(mockDefinition.Object);
549+
Assert.DoesNotThrow(() => filter.ExcludeByAttribute(mockDefinition.Object));
550+
}
551+
552+
[Test]
553+
public void CanIdentify_AutoImplementedProperties()
554+
{
555+
// arrange
556+
var sourceAssembly = AssemblyDefinition.ReadAssembly(typeof(Samples.Concrete).Assembly.Location);
557+
var type = sourceAssembly.MainModule.Types.First(x => x.FullName == typeof(Samples.DeclaredMethodClass).FullName);
558+
559+
// act/assert
560+
var filter = new Filter();
561+
var wasTested = false;
562+
foreach (var methodDefinition in type.Methods
563+
.Where(x => x.IsGetter || x.IsSetter).Where(x => x.Name.EndsWith("AutoProperty")))
564+
{
565+
wasTested = true;
566+
Assert.IsTrue(filter.IsAutoImplementedProperty(methodDefinition));
567+
}
568+
Assert.IsTrue(wasTested);
569+
570+
wasTested = false;
571+
foreach (var methodDefinition in type.Methods
572+
.Where(x => x.IsGetter || x.IsSetter).Where(x => x.Name.EndsWith("PropertyWithBackingField")))
573+
{
574+
wasTested = true;
575+
Assert.IsFalse(filter.IsAutoImplementedProperty(methodDefinition));
576+
}
577+
Assert.IsTrue(wasTested);
550578
}
551579
}
552580
}

main/OpenCover.Test/Framework/Symbols/CecilSymbolManagerTests.cs

+27
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,33 @@ public void Can_Exclude_A_Method_By_An_FileFilter()
479479
Assert.True(methods.First(y => y.Name.EndsWith("::Method()")).SkippedDueTo == SkippedMethod.File);
480480
}
481481

482+
[Test]
483+
public void Can_Exclude_AutoImplmentedProperties()
484+
{
485+
// arrange
486+
var filter = new Filter();
487+
_mockFilter
488+
.Setup(x => x.InstrumentClass(It.IsAny<string>(), It.IsAny<string>()))
489+
.Returns(true);
490+
491+
_mockFilter
492+
.Setup(x => x.IsAutoImplementedProperty(It.IsAny<MethodDefinition>()))
493+
.Returns<MethodDefinition>(x => filter.IsAutoImplementedProperty(x));
494+
495+
_mockCommandLine.Setup(x => x.SkipAutoImplementedProperties).Returns(true);
496+
497+
var types = _reader.GetInstrumentableTypes();
498+
var target = types.First(x => x.FullName == typeof(DeclaredMethodClass).FullName);
499+
500+
// act
501+
var methods = _reader.GetMethodsForType(target, new File[0]);
502+
503+
// assert
504+
Assert.True(methods.Any());
505+
Assert.AreEqual(SkippedMethod.AutoImplementedProperty, methods.First(y => y.Name.EndsWith("AutoProperty()")).SkippedDueTo);
506+
Assert.AreEqual((SkippedMethod)0, methods.First(y => y.Name.EndsWith("PropertyWithBackingField()")).SkippedDueTo);
507+
}
508+
482509
[Test]
483510
public void GetTrackedMethods_NoTrackedMethods_When_NoStrategies()
484511
{

main/OpenCover.Test/Samples/Samples.cs

+7
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,17 @@ public bool HasSwitch(int input)
4343

4444
class DeclaredMethodClass
4545
{
46+
private string _propertyWithBackingField;
4647
void Method() {}
4748

4849
string AutoProperty { get; set;}
4950

51+
string PropertyWithBackingField
52+
{
53+
get { return _propertyWithBackingField; }
54+
set { _propertyWithBackingField = value; }
55+
}
56+
5057
void DoThing(Action<object> doThing)
5158
{
5259
doThing(1);

0 commit comments

Comments
 (0)