Skip to content

Commit fdd2930

Browse files
Add skipautoprops feature (#912)
Add skipautoprops feature
1 parent 778b697 commit fdd2930

20 files changed

+217
-168
lines changed

Documentation/GlobalTool.md

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ Options:
3636
--single-hit Specifies whether to limit code coverage hit reporting to a single hit for each location.
3737
--merge-with Path to existing coverage result to merge.
3838
--use-source-link Specifies whether to use SourceLink URIs in place of file system paths.
39+
--skipautoprops Neither track nor record auto-implemented properties.
3940
```
4041
4142
NB. For a [multiple value] options you have to specify values multiple times i.e.

Documentation/MSBuildIntegration.md

+5
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,11 @@ Both `Exclude` and `Include` properties can be used together but `Exclude` takes
157157

158158
You can also include coverage of the test assembly itself by setting `/p:IncludeTestAssembly` to `true`.
159159

160+
### Skip auto-implemented properties
161+
162+
Neither track nor record auto-implemented properties.
163+
Syntax: `/p:SkipAutoProps=true`
164+
160165
### Note for Powershell / VSTS users
161166
To exclude or include multiple assemblies when using Powershell scripts or creating a .yaml file for a VSTS build ```%2c``` should be used as a separator. Msbuild will translate this symbol to ```,```.
162167

Documentation/VSTestIntegration.md

+2
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ These are a list of options that are supported by coverlet. These can be specifi
7979
|SingleHit | Specifies whether to limit code coverage hit reporting to a single hit for each location.|
8080
|UseSourceLink | Specifies whether to use SourceLink URIs in place of file system paths. |
8181
|IncludeTestAssembly | Include coverage of the test assembly. |
82+
|SkipAutoProps | Neither track nor record auto-implemented properties. |
8283

8384
How to specify these options via runsettings?
8485
```
@@ -97,6 +98,7 @@ How to specify these options via runsettings?
9798
<SingleHit>false</SingleHit>
9899
<UseSourceLink>true</UseSourceLink>
99100
<IncludeTestAssembly>true</IncludeTestAssembly>
101+
<SkipAutoProps>true</SkipAutoProps>
100102
</Configuration>
101103
</DataCollector>
102104
</DataCollectors>

README.md

+4
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,10 @@ to clarify expected behavior in our community.
167167

168168
For more information, see the [.NET Foundation Code of Conduct](https://dotnetfoundation.org/code-of-conduct).
169169

170+
## Credits
171+
172+
Part of the code is based on work done by OpenCover team https://github.com/OpenCover
173+
170174
## License
171175

172176
This project is licensed under the MIT license. See the [LICENSE](LICENSE) file for more info.

src/coverlet.collector/DataCollection/CoverageWrapper.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ public Coverage CreateCoverage(CoverletSettings settings, ILogger coverletLogger
2727
IncludeTestAssembly = settings.IncludeTestAssembly,
2828
SingleHit = settings.SingleHit,
2929
MergeWith = settings.MergeWith,
30-
UseSourceLink = settings.UseSourceLink
30+
UseSourceLink = settings.UseSourceLink,
31+
SkipAutoProps = settings.SkipAutoProps
3132
};
3233

3334
return new Coverage(

src/coverlet.collector/DataCollection/CoverletSettings.cs

+16-10
Original file line numberDiff line numberDiff line change
@@ -63,20 +63,26 @@ internal class CoverletSettings
6363
/// </summary>
6464
public bool IncludeTestAssembly { get; set; }
6565

66+
/// <summary>
67+
/// Neither track nor record auto-implemented properties.
68+
/// </summary>
69+
public bool SkipAutoProps { get; set; }
70+
6671
public override string ToString()
6772
{
6873
var builder = new StringBuilder();
6974

70-
builder.AppendFormat("TestModule: '{0}', ", this.TestModule);
71-
builder.AppendFormat("IncludeFilters: '{0}', ", string.Join(",", this.IncludeFilters ?? Enumerable.Empty<string>()));
72-
builder.AppendFormat("IncludeDirectories: '{0}', ", string.Join(",", this.IncludeDirectories ?? Enumerable.Empty<string>()));
73-
builder.AppendFormat("ExcludeFilters: '{0}', ", string.Join(",", this.ExcludeFilters ?? Enumerable.Empty<string>()));
74-
builder.AppendFormat("ExcludeSourceFiles: '{0}', ", string.Join(",", this.ExcludeSourceFiles ?? Enumerable.Empty<string>()));
75-
builder.AppendFormat("ExcludeAttributes: '{0}', ", string.Join(",", this.ExcludeAttributes ?? Enumerable.Empty<string>()));
76-
builder.AppendFormat("MergeWith: '{0}', ", this.MergeWith);
77-
builder.AppendFormat("UseSourceLink: '{0}'", this.UseSourceLink);
78-
builder.AppendFormat("SingleHit: '{0}'", this.SingleHit);
79-
builder.AppendFormat("IncludeTestAssembly: '{0}'", this.IncludeTestAssembly);
75+
builder.AppendFormat("TestModule: '{0}', ", TestModule);
76+
builder.AppendFormat("IncludeFilters: '{0}', ", string.Join(",", IncludeFilters ?? Enumerable.Empty<string>()));
77+
builder.AppendFormat("IncludeDirectories: '{0}', ", string.Join(",", IncludeDirectories ?? Enumerable.Empty<string>()));
78+
builder.AppendFormat("ExcludeFilters: '{0}', ", string.Join(",", ExcludeFilters ?? Enumerable.Empty<string>()));
79+
builder.AppendFormat("ExcludeSourceFiles: '{0}', ", string.Join(",", ExcludeSourceFiles ?? Enumerable.Empty<string>()));
80+
builder.AppendFormat("ExcludeAttributes: '{0}', ", string.Join(",", ExcludeAttributes ?? Enumerable.Empty<string>()));
81+
builder.AppendFormat("MergeWith: '{0}', ", MergeWith);
82+
builder.AppendFormat("UseSourceLink: '{0}'", UseSourceLink);
83+
builder.AppendFormat("SingleHit: '{0}'", SingleHit);
84+
builder.AppendFormat("IncludeTestAssembly: '{0}'", IncludeTestAssembly);
85+
builder.AppendFormat("SkipAutoProps: '{0}'", SkipAutoProps);
8086

8187
return builder.ToString();
8288
}

src/coverlet.collector/DataCollection/CoverletSettingsParser.cs

+24-11
Original file line numberDiff line numberDiff line change
@@ -29,23 +29,24 @@ public CoverletSettings Parse(XmlElement configurationElement, IEnumerable<strin
2929
{
3030
var coverletSettings = new CoverletSettings
3131
{
32-
TestModule = this.ParseTestModule(testModules)
32+
TestModule = ParseTestModule(testModules)
3333
};
3434

3535
if (configurationElement != null)
3636
{
37-
coverletSettings.IncludeFilters = this.ParseIncludeFilters(configurationElement);
38-
coverletSettings.IncludeDirectories = this.ParseIncludeDirectories(configurationElement);
39-
coverletSettings.ExcludeAttributes = this.ParseExcludeAttributes(configurationElement);
40-
coverletSettings.ExcludeSourceFiles = this.ParseExcludeSourceFiles(configurationElement);
41-
coverletSettings.MergeWith = this.ParseMergeWith(configurationElement);
42-
coverletSettings.UseSourceLink = this.ParseUseSourceLink(configurationElement);
43-
coverletSettings.SingleHit = this.ParseSingleHit(configurationElement);
44-
coverletSettings.IncludeTestAssembly = this.ParseIncludeTestAssembly(configurationElement);
37+
coverletSettings.IncludeFilters = ParseIncludeFilters(configurationElement);
38+
coverletSettings.IncludeDirectories = ParseIncludeDirectories(configurationElement);
39+
coverletSettings.ExcludeAttributes = ParseExcludeAttributes(configurationElement);
40+
coverletSettings.ExcludeSourceFiles = ParseExcludeSourceFiles(configurationElement);
41+
coverletSettings.MergeWith = ParseMergeWith(configurationElement);
42+
coverletSettings.UseSourceLink = ParseUseSourceLink(configurationElement);
43+
coverletSettings.SingleHit = ParseSingleHit(configurationElement);
44+
coverletSettings.IncludeTestAssembly = ParseIncludeTestAssembly(configurationElement);
45+
coverletSettings.SkipAutoProps = ParseSkipAutoProps(configurationElement);
4546
}
4647

47-
coverletSettings.ReportFormats = this.ParseReportFormats(configurationElement);
48-
coverletSettings.ExcludeFilters = this.ParseExcludeFilters(configurationElement);
48+
coverletSettings.ReportFormats = ParseReportFormats(configurationElement);
49+
coverletSettings.ExcludeFilters = ParseExcludeFilters(configurationElement);
4950

5051
if (_eqtTrace.IsVerboseEnabled)
5152
{
@@ -205,6 +206,18 @@ private bool ParseIncludeTestAssembly(XmlElement configurationElement)
205206
return includeTestAssembly;
206207
}
207208

209+
/// <summary>
210+
/// Parse skipautoprops flag
211+
/// </summary>
212+
/// <param name="configurationElement">Configuration element</param>
213+
/// <returns>Include Test Assembly Flag</returns>
214+
private bool ParseSkipAutoProps(XmlElement configurationElement)
215+
{
216+
XmlElement skipAutoPropsElement = configurationElement[CoverletConstants.SkipAutoProps];
217+
bool.TryParse(skipAutoPropsElement?.InnerText, out bool skipAutoProps);
218+
return skipAutoProps;
219+
}
220+
208221
/// <summary>
209222
/// Splits a comma separated elements into an array
210223
/// </summary>

src/coverlet.collector/Utilities/CoverletConstants.cs

+1
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,6 @@ internal static class CoverletConstants
2020
public const string ReportFormatElementName = "Format";
2121
public const string DefaultExcludeFilter = "[coverlet.*]*";
2222
public const string InProcDataCollectorName = "CoverletInProcDataCollector";
23+
public const string SkipAutoProps = "SkipAutoProps";
2324
}
2425
}

src/coverlet.console/Program.cs

+4-2
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ static int Main(string[] args)
6060
CommandOption excludeAttributes = app.Option("--exclude-by-attribute", "Attributes to exclude from code coverage.", CommandOptionType.MultipleValue);
6161
CommandOption includeTestAssembly = app.Option("--include-test-assembly", "Specifies whether to report code coverage of the test assembly.", CommandOptionType.NoValue);
6262
CommandOption singleHit = app.Option("--single-hit", "Specifies whether to limit code coverage hit reporting to a single hit for each location", CommandOptionType.NoValue);
63+
CommandOption skipAutoProp = app.Option("--skipautoprops", "Neither track nor record auto-implemented properties.", CommandOptionType.NoValue);
6364
CommandOption mergeWith = app.Option("--merge-with", "Path to existing coverage result to merge.", CommandOptionType.SingleValue);
6465
CommandOption useSourceLink = app.Option("--use-source-link", "Specifies whether to use SourceLink URIs in place of file system paths.", CommandOptionType.NoValue);
6566

@@ -87,7 +88,8 @@ static int Main(string[] args)
8788
IncludeTestAssembly = includeTestAssembly.HasValue(),
8889
SingleHit = singleHit.HasValue(),
8990
MergeWith = mergeWith.Value(),
90-
UseSourceLink = useSourceLink.HasValue()
91+
UseSourceLink = useSourceLink.HasValue(),
92+
SkipAutoProps = skipAutoProp.HasValue()
9193
};
9294

9395
Coverage coverage = new Coverage(module.Value,
@@ -97,7 +99,7 @@ static int Main(string[] args)
9799
fileSystem,
98100
serviceProvider.GetRequiredService<ISourceRootTranslator>(),
99101
serviceProvider.GetRequiredService<ICecilSymbolHelper>());
100-
coverage.PrepareModules();
102+
coverage.PrepareModules();
101103

102104
Process process = new Process();
103105
process.StartInfo.FileName = target.Value();

src/coverlet.core/Coverage.cs

+16-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ internal class CoverageParameters
2323
public bool SingleHit { get; set; }
2424
public string MergeWith { get; set; }
2525
public bool UseSourceLink { get; set; }
26+
public bool SkipAutoProps { get; set; }
2627
}
2728

2829
internal class Coverage
@@ -38,6 +39,7 @@ internal class Coverage
3839
private bool _singleHit;
3940
private string _mergeWith;
4041
private bool _useSourceLink;
42+
private bool _skipAutoProps;
4143
private ILogger _logger;
4244
private IInstrumentationHelper _instrumentationHelper;
4345
private IFileSystem _fileSystem;
@@ -73,6 +75,7 @@ public Coverage(string module,
7375
_fileSystem = fileSystem;
7476
_sourceRootTranslator = sourceRootTranslator;
7577
_cecilSymbolHelper = cecilSymbolHelper;
78+
_skipAutoProps = parameters.SkipAutoProps;
7679

7780
_identifier = Guid.NewGuid().ToString();
7881
_results = new List<InstrumenterResult>();
@@ -115,7 +118,19 @@ public CoveragePrepareResult PrepareModules()
115118
continue;
116119
}
117120

118-
var instrumenter = new Instrumenter(module, _identifier, _excludeFilters, _includeFilters, _excludedSourceFiles, _excludeAttributes, _singleHit, _logger, _instrumentationHelper, _fileSystem, _sourceRootTranslator, _cecilSymbolHelper);
121+
var instrumenter = new Instrumenter(module,
122+
_identifier,
123+
_excludeFilters,
124+
_includeFilters,
125+
_excludedSourceFiles,
126+
_excludeAttributes,
127+
_singleHit,
128+
_skipAutoProps,
129+
_logger,
130+
_instrumentationHelper,
131+
_fileSystem,
132+
_sourceRootTranslator,
133+
_cecilSymbolHelper);
119134

120135
if (instrumenter.CanInstrument())
121136
{

src/coverlet.core/Instrumentation/Instrumenter.cs

+8
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ internal class Instrumenter
2525
private readonly ExcludedFilesHelper _excludedFilesHelper;
2626
private readonly string[] _excludedAttributes;
2727
private readonly bool _singleHit;
28+
private readonly bool _skipAutoProps;
2829
private readonly bool _isCoreLibrary;
2930
private readonly ILogger _logger;
3031
private readonly IInstrumentationHelper _instrumentationHelper;
@@ -55,6 +56,7 @@ public Instrumenter(
5556
string[] excludedFiles,
5657
string[] excludedAttributes,
5758
bool singleHit,
59+
bool skipAutoProps,
5860
ILogger logger,
5961
IInstrumentationHelper instrumentationHelper,
6062
IFileSystem fileSystem,
@@ -84,6 +86,7 @@ public Instrumenter(
8486
_fileSystem = fileSystem;
8587
_sourceRootTranslator = sourceRootTranslator;
8688
_cecilSymbolHelper = cecilSymbolHelper;
89+
_skipAutoProps = skipAutoProps;
8790
}
8891

8992
public bool CanInstrument()
@@ -432,6 +435,11 @@ private void InstrumentType(TypeDefinition type)
432435

433436
if (actualMethod.IsGetter || actualMethod.IsSetter)
434437
{
438+
if (_skipAutoProps && actualMethod.CustomAttributes.Any(ca => ca.AttributeType.FullName == typeof(CompilerGeneratedAttribute).FullName))
439+
{
440+
continue;
441+
}
442+
435443
PropertyDefinition prop = type.Properties.FirstOrDefault(p => (p.GetMethod ?? p.SetMethod).FullName.Equals(actualMethod.FullName));
436444
if (prop?.HasCustomAttributes == true)
437445
customAttributes = customAttributes.Union(prop.CustomAttributes);

0 commit comments

Comments
 (0)