Skip to content

Commit 5ec636b

Browse files
Exclude code that follows [DoesNotReturn] from code coverage (#904)
Exclude code that follows [DoesNotReturn] from code coverage
1 parent 6479f62 commit 5ec636b

File tree

18 files changed

+1286
-59
lines changed

18 files changed

+1286
-59
lines changed

Documentation/GlobalTool.md

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,26 +17,27 @@ Arguments:
1717
<ASSEMBLY> Path to the test assembly.
1818

1919
Options:
20-
-h|--help Show help information
21-
-v|--version Show version information
22-
-t|--target Path to the test runner application.
23-
-a|--targetargs Arguments to be passed to the test runner.
24-
-o|--output Output of the generated coverage report
25-
-v|--verbosity Sets the verbosity level of the command. Allowed values are quiet, minimal, normal, detailed.
26-
-f|--format Format of the generated coverage report[multiple value].
27-
--threshold Exits with error if the coverage % is below value.
28-
--threshold-type Coverage type to apply the threshold to[multiple value].
29-
--threshold-stat Coverage statistic used to enforce the threshold value.
30-
--exclude Filter expressions to exclude specific modules and types[multiple value].
31-
--include Filter expressions to include specific modules and types[multiple value].
32-
--include-directory Include directories containing additional assemblies to be instrumented[multiple value].
33-
--exclude-by-file Glob patterns specifying source files to exclude[multiple value].
34-
--exclude-by-attribute Attributes to exclude from code coverage[multiple value].
35-
--include-test-assembly Specifies whether to report code coverage of the test assembly.
36-
--single-hit Specifies whether to limit code coverage hit reporting to a single hit for each location.
37-
--merge-with Path to existing coverage result to merge.
38-
--use-source-link Specifies whether to use SourceLink URIs in place of file system paths.
39-
--skipautoprops Neither track nor record auto-implemented properties.
20+
-h|--help Show help information
21+
-v|--version Show version information
22+
-t|--target Path to the test runner application.
23+
-a|--targetargs Arguments to be passed to the test runner.
24+
-o|--output Output of the generated coverage report
25+
-v|--verbosity Sets the verbosity level of the command. Allowed values are quiet, minimal, normal, detailed.
26+
-f|--format Format of the generated coverage report[multiple value].
27+
--threshold Exits with error if the coverage % is below value.
28+
--threshold-type Coverage type to apply the threshold to[multiple value].
29+
--threshold-stat Coverage statistic used to enforce the threshold value.
30+
--exclude Filter expressions to exclude specific modules and types[multiple value].
31+
--include Filter expressions to include specific modules and types[multiple value].
32+
--include-directory Include directories containing additional assemblies to be instrumented[multiple value].
33+
--exclude-by-file Glob patterns specifying source files to exclude[multiple value].
34+
--exclude-by-attribute Attributes to exclude from code coverage[multiple value].
35+
--include-test-assembly Specifies whether to report code coverage of the test assembly.
36+
--single-hit Specifies whether to limit code coverage hit reporting to a single hit for each location.
37+
--merge-with Path to existing coverage result to merge.
38+
--use-source-link Specifies whether to use SourceLink URIs in place of file system paths.
39+
--skipautoprops Neither track nor record auto-implemented properties.
40+
--does-not-return-attribute Attributes that mark methods that do not return[multiple value].
4041
```
4142
4243
NB. For a [multiple value] options you have to specify values multiple times i.e.

Documentation/MSBuildIntegration.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,13 @@ You can also include coverage of the test assembly itself by setting `/p:Include
162162
Neither track nor record auto-implemented properties.
163163
Syntax: `/p:SkipAutoProps=true`
164164

165+
### Methods that do not return
166+
167+
Methods that do not return can be marked with attributes to cause statements after them to be excluded from coverage. `DoesNotReturnAttribute` is included by default.
168+
169+
Attributes can be specified with the following syntax.
170+
Syntax: `/p:DoesNotReturnAttribute="DoesNotReturnAttribute,OtherAttribute"`
171+
165172
### Note for Powershell / VSTS users
166173
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 ```,```.
167174

Documentation/VSTestIntegration.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ These are a list of options that are supported by coverlet. These can be specifi
8080
|UseSourceLink | Specifies whether to use SourceLink URIs in place of file system paths. |
8181
|IncludeTestAssembly | Include coverage of the test assembly. |
8282
|SkipAutoProps | Neither track nor record auto-implemented properties. |
83+
|DoesNotReturnAttribute | Methods marked with these attributes are known not to return, statements following them will be excluded from coverage |
8384

8485
How to specify these options via runsettings?
8586
```

src/coverlet.collector/DataCollection/CoverageWrapper.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ public Coverage CreateCoverage(CoverletSettings settings, ILogger coverletLogger
2828
SingleHit = settings.SingleHit,
2929
MergeWith = settings.MergeWith,
3030
UseSourceLink = settings.UseSourceLink,
31-
SkipAutoProps = settings.SkipAutoProps
31+
SkipAutoProps = settings.SkipAutoProps,
32+
DoesNotReturnAttributes = settings.DoesNotReturnAttributes
3233
};
3334

3435
return new Coverage(

src/coverlet.collector/DataCollection/CoverletSettings.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@ internal class CoverletSettings
6868
/// </summary>
6969
public bool SkipAutoProps { get; set; }
7070

71+
/// <summary>
72+
/// Attributes that mark methods that never return.
73+
/// </summary>
74+
public string[] DoesNotReturnAttributes { get; set; }
75+
7176
public override string ToString()
7277
{
7378
var builder = new StringBuilder();
@@ -83,6 +88,7 @@ public override string ToString()
8388
builder.AppendFormat("SingleHit: '{0}'", SingleHit);
8489
builder.AppendFormat("IncludeTestAssembly: '{0}'", IncludeTestAssembly);
8590
builder.AppendFormat("SkipAutoProps: '{0}'", SkipAutoProps);
91+
builder.AppendFormat("DoesNotReturnAttributes: '{0}'", string.Join(",", DoesNotReturnAttributes ?? Enumerable.Empty<string>()));
8692

8793
return builder.ToString();
8894
}

src/coverlet.collector/DataCollection/CoverletSettingsParser.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ public CoverletSettings Parse(XmlElement configurationElement, IEnumerable<strin
4343
coverletSettings.SingleHit = ParseSingleHit(configurationElement);
4444
coverletSettings.IncludeTestAssembly = ParseIncludeTestAssembly(configurationElement);
4545
coverletSettings.SkipAutoProps = ParseSkipAutoProps(configurationElement);
46+
coverletSettings.DoesNotReturnAttributes = ParseDoesNotReturnAttributes(configurationElement);
4647
}
4748

4849
coverletSettings.ReportFormats = ParseReportFormats(configurationElement);
@@ -218,6 +219,17 @@ private bool ParseSkipAutoProps(XmlElement configurationElement)
218219
return skipAutoProps;
219220
}
220221

222+
/// <summary>
223+
/// Parse attributes that mark methods that do not return.
224+
/// </summary>
225+
/// <param name="configurationElement">Configuration element</param>
226+
/// <returns>DoesNotReturn attributes</returns>
227+
private string[] ParseDoesNotReturnAttributes(XmlElement configurationElement)
228+
{
229+
XmlElement doesNotReturnAttributesElement = configurationElement[CoverletConstants.DoesNotReturnAttributesElementName];
230+
return this.SplitElement(doesNotReturnAttributesElement);
231+
}
232+
221233
/// <summary>
222234
/// Splits a comma separated elements into an array
223235
/// </summary>

src/coverlet.collector/Utilities/CoverletConstants.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,6 @@ internal static class CoverletConstants
2121
public const string DefaultExcludeFilter = "[coverlet.*]*";
2222
public const string InProcDataCollectorName = "CoverletInProcDataCollector";
2323
public const string SkipAutoProps = "SkipAutoProps";
24+
public const string DoesNotReturnAttributesElementName = "DoesNotReturnAttribute";
2425
}
2526
}

src/coverlet.console/Program.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ static int Main(string[] args)
6363
CommandOption skipAutoProp = app.Option("--skipautoprops", "Neither track nor record auto-implemented properties.", CommandOptionType.NoValue);
6464
CommandOption mergeWith = app.Option("--merge-with", "Path to existing coverage result to merge.", CommandOptionType.SingleValue);
6565
CommandOption useSourceLink = app.Option("--use-source-link", "Specifies whether to use SourceLink URIs in place of file system paths.", CommandOptionType.NoValue);
66+
CommandOption doesNotReturnAttributes = app.Option("--does-not-return-attribute", "Attributes that mark methods that do not return.", CommandOptionType.MultipleValue);
6667

6768
app.OnExecute(() =>
6869
{
@@ -89,7 +90,8 @@ static int Main(string[] args)
8990
SingleHit = singleHit.HasValue(),
9091
MergeWith = mergeWith.Value(),
9192
UseSourceLink = useSourceLink.HasValue(),
92-
SkipAutoProps = skipAutoProp.HasValue()
93+
SkipAutoProps = skipAutoProp.HasValue(),
94+
DoesNotReturnAttributes = doesNotReturnAttributes.Values.ToArray()
9395
};
9496

9597
Coverage coverage = new Coverage(module.Value,
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
using System;
2+
3+
namespace Coverlet.Core.Attributes
4+
{
5+
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class)]
6+
internal class DoesNotReturnAttribute : Attribute { }
7+
}

src/coverlet.core/Coverage.cs

Lines changed: 4 additions & 0 deletions
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 string[] DoesNotReturnAttributes { get; set; }
2627
public bool SkipAutoProps { get; set; }
2728
}
2829

@@ -39,6 +40,7 @@ internal class Coverage
3940
private bool _singleHit;
4041
private string _mergeWith;
4142
private bool _useSourceLink;
43+
private string[] _doesNotReturnAttributes;
4244
private bool _skipAutoProps;
4345
private ILogger _logger;
4446
private IInstrumentationHelper _instrumentationHelper;
@@ -70,6 +72,7 @@ public Coverage(string module,
7072
_singleHit = parameters.SingleHit;
7173
_mergeWith = parameters.MergeWith;
7274
_useSourceLink = parameters.UseSourceLink;
75+
_doesNotReturnAttributes = parameters.DoesNotReturnAttributes;
7376
_logger = logger;
7477
_instrumentationHelper = instrumentationHelper;
7578
_fileSystem = fileSystem;
@@ -124,6 +127,7 @@ public CoveragePrepareResult PrepareModules()
124127
_includeFilters,
125128
_excludedSourceFiles,
126129
_excludeAttributes,
130+
_doesNotReturnAttributes,
127131
_singleHit,
128132
_skipAutoProps,
129133
_logger,

0 commit comments

Comments
 (0)