66
77namespace FineCodeCoverage . Engine . OpenCover
88{
9- internal static class OpenCoverExeEscaper
9+ internal static class CommandLineArguments
1010 {
1111 public static string EscapeArgument ( string value )
1212 {
1313 return $@ """{ value } """;
1414 }
1515
16- public static string EscapeQuoteTargetArgsArgument (string arg)
16+ public static string EscapeQuotes (string arg)
1717 {
1818 return $@"\""{arg}\""" ;
1919 }
2020 }
2121 [ Export ( typeof ( IOpenCoverExeArgumentsProvider ) ) ]
2222 internal class OpenCoverExeArgumentsProvider : IOpenCoverExeArgumentsProvider
2323 {
24+ private enum Delimiter { Semicolon , Space }
2425 private void AddFilter ( ICoverageProject project , List < string > opencoverSettings )
2526 {
26- var filters = new List < string > ( ) ;
27- var defaultFilter = "+[*]*" ;
28-
29- foreach ( var value in ( project . Settings . Include ?? new string [ 0 ] ) . Where ( x => ! string . IsNullOrWhiteSpace ( x ) ) )
30- {
31- filters . Add ( $@ "+{ value . Replace ( "\" " , "\\ \" " ) . Trim ( ' ' , '\' ' ) } ") ;
32- }
33-
34- foreach ( var includedReferencedProject in project . IncludedReferencedProjects )
27+ var includeFilters = GetExcludesOrIncludes( project . Settings . Include , project . IncludedReferencedProjects , true ) ;
28+ var excludeFilters = GetExcludesOrIncludes ( project . Settings . Exclude , project . ExcludedReferencedProjects , false ) ;
29+ AddIncludeAllIfExcludingWithoutIncludes ( ) ;
30+ var filters = includeFilters . Concat ( excludeFilters ) . ToList ( ) ;
31+ SafeAddToSettingsDelimitedIfAny ( opencoverSettings , "filter ", filters , Delimiter . Space ) ;
32+
33+ void AddIncludeAllIfExcludingWithoutIncludes ( )
3534 {
36- filters . Add ( $@ "+[{ includedReferencedProject } ]*") ;
35+ if ( excludeFilters . Any ( ) && ! includeFilters . Any ( ) )
36+ {
37+ includeFilters . Add ( "+ [ * ] * ") ;
38+ }
3739 }
3840
39- if ( ! filters . Any ( ) )
41+ List < string > GetExcludesOrIncludes ( string [ ] excludesOrIncludes , List < string > referencedExcludesOrIncludes , bool isInclude )
4042 {
41- filters . Add ( defaultFilter ) ;
42- }
43+ var excludeOrIncludeFilters = new List < string > ( ) ;
44+ var prefix = IncludeSymbol ( isInclude ) ;
45+ excludesOrIncludes = SanitizeExcludesOrIncludes ( excludesOrIncludes ) . ToArray ( ) ;
46+
47+ foreach ( var value in excludesOrIncludes )
48+ {
49+ excludeOrIncludeFilters . Add ( $@"{prefix}{value}" ) ;
50+ }
4351
44- foreach ( var value in ( project . Settings . Exclude ?? new string [ 0 ] ) . Where ( x => ! string . IsNullOrWhiteSpace ( x ) ) )
45- {
46- filters . Add ( $@ "-{ value . Replace ( "\" " , "\\ \" " ) . Trim ( ' ' , '\' ' ) } ") ;
52+ foreach ( var includedReferencedProject in referencedExcludesOrIncludes )
53+ {
54+ excludeOrIncludeFilters . Add ( IncludeOrExclude ( isInclude , includedReferencedProject ) ) ;
55+ }
56+ return excludeOrIncludeFilters . Distinct ( ) . ToList( ) ;
4757 }
4858
49- foreach ( var referencedProjectExcludedFromCodeCoverage in project . ExcludedReferencedProjects )
59+ string IncludeOrExclude ( bool include , string moduleFilter , string classFilter = "*" )
5060 {
51- filters . Add ( $@ "-[{ referencedProjectExcludedFromCodeCoverage } ]*") ;
61+ var filter = IncludeSymbol ( include ) ;
62+ return $"{filter}[{moduleFilter}]{classFilter}" ;
5263 }
5364
54- if ( filters . Any ( x => ! x . Equals ( defaultFilter ) ) )
55- {
56- opencoverSettings . Add ( $@ " ""-filter:{ string . Join ( " " , filters . Distinct ( ) ) } "" ") ;
57- }
58-
65+ string IncludeSymbol( bool include ) => include ? "+" : "-" ;
5966 }
6067
61- private IEnumerable< string > GetExcludes ( string [ ] excludes )
68+ private IEnumerable< string > SanitizeExcludesOrIncludes ( string [ ] excludesOrIncludes )
6269 {
63- return ( excludes ?? new string [ 0 ] )
70+ return ( excludesOrIncludes ?? new string [ 0 ] )
6471 . Where ( x => x != null )
6572 . Select ( x => x . Trim ( ' ' , '\' ' , '\" ' ) )
6673 . Where ( x => ! string . IsNullOrWhiteSpace ( x ) ) ;
6774 }
6875
69- private void SafeAddToSettingsSemiColonDelimitedIfAny ( List < string > opencoverSettings , string settingName , IEnumerable < string > settings )
76+ private void SafeAddToSettingsDelimitedIfAny (
77+ List < string > opencoverSettings ,
78+ string settingName ,
79+ IEnumerable < string > settings ,
80+ Delimiter delimiter = Delimiter . Semicolon
81+ )
7082 {
7183 if ( settings . Any ( ) )
7284 {
73- opencoverSettings . Add ( $@ """-{ settingName } :{ string . Join ( ";" , settings ) } """);
85+ var delimit = delimiter == Delimiter. Semicolon ? ";" : " " ;
86+ opencoverSettings . Add ( $@ """-{ settingName } :{ string . Join ( delimit , settings ) } """);
7487 }
7588 }
7689
7790 private void AddExcludeByFile(ICoverageProject project, List<string> opencoverSettings)
7891 {
79- var excludes = GetExcludes ( project . Settings . ExcludeByFile ) . ToList ( ) ;
80- SafeAddToSettingsSemiColonDelimitedIfAny ( opencoverSettings , "excludebyfile" , excludes) ;
92+ var excludes = SanitizeExcludesOrIncludes ( project . Settings . ExcludeByFile ) . ToList ( ) ;
93+ SafeAddToSettingsDelimitedIfAny ( opencoverSettings , "excludebyfile" , excludes) ;
8194 }
8295
8396 private void AddExcludeByAttribute ( ICoverageProject project , List < string > opencoverSettings )
@@ -89,14 +102,14 @@ private void AddExcludeByAttribute(ICoverageProject project, List<string> openco
89102 "ExcludeFromCodeCoverage"
90103 } ;
91104
92- var excludes = GetExcludes ( project . Settings . ExcludeByAttribute )
105+ var excludes = SanitizeExcludesOrIncludes ( project . Settings . ExcludeByAttribute )
93106 . Concat ( excludeFromCodeCoverageAttributes )
94107 . SelectMany ( exclude => new [ ] { exclude , GetAlternateName ( exclude ) } )
95108 . OrderBy ( exclude => exclude )
96109 . Select ( WildCardIfShortName ) ;
97110
98111
99- SafeAddToSettingsSemiColonDelimitedIfAny ( opencoverSettings , "excludebyattribute" , excludes ) ;
112+ SafeAddToSettingsDelimitedIfAny ( opencoverSettings , "excludebyattribute" , excludes ) ;
100113
101114 string WildCardIfShortName ( string exclude )
102115 {
@@ -125,18 +138,18 @@ string GetAlternateName(string exclude)
125138
126139 private string GetTargetArgs( ICoverageProject project )
127140 {
128- var runSettings = ! string. IsNullOrWhiteSpace ( project . RunSettingsFile ) ? $@ " /Settings:{ OpenCoverExeEscaper . EscapeQuoteTargetArgsArgument ( project . RunSettingsFile ) } " : default ;
129- return $@"""-targetargs:{OpenCoverExeEscaper.EscapeQuoteTargetArgsArgument (project.TestDllFile)}{runSettings}""" ;
141+ var runSettings = ! string. IsNullOrWhiteSpace ( project . RunSettingsFile ) ? $@ " /Settings:{ CommandLineArguments . EscapeQuotes ( project . RunSettingsFile ) } " : default ;
142+ return $@"""-targetargs:{CommandLineArguments.EscapeQuotes (project.TestDllFile)}{runSettings}""" ;
130143 }
131144
132145 public List< string > Provide ( ICoverageProject project , string msTestPlatformExePath )
133146 {
134147 var opencoverSettings = new List < string > ( ) ;
135148
136- opencoverSettings . Add ( OpenCoverExeEscaper . EscapeArgument ( $ "-target:{ msTestPlatformExePath } ") ) ;
149+ opencoverSettings . Add ( CommandLineArguments . EscapeArgument ( $ "-target:{ msTestPlatformExePath } ") ) ;
137150 opencoverSettings . Add ( GetTargetArgs ( project ) ) ;
138151
139- opencoverSettings . Add ( OpenCoverExeEscaper . EscapeArgument ( $ "-output:{ project . CoverageOutputFile } ") ) ;
152+ opencoverSettings . Add ( CommandLineArguments . EscapeArgument ( $ "-output:{ project . CoverageOutputFile } ") ) ;
140153
141154 AddFilter ( project , opencoverSettings ) ;
142155 AddExcludeByFile ( project , opencoverSettings ) ;
0 commit comments