@@ -17,6 +17,7 @@ public class Coverage
1717 private string _identifier ;
1818 private string [ ] _excludeFilters ;
1919 private string [ ] _includeFilters ;
20+ private string [ ] _includeDirectories ;
2021 private string [ ] _excludedSourceFiles ;
2122 private string _mergeWith ;
2223 private string [ ] _excludeAttributes ;
@@ -27,11 +28,12 @@ public string Identifier
2728 get { return _identifier ; }
2829 }
2930
30- public Coverage ( string module , string [ ] excludeFilters , string [ ] includeFilters , string [ ] excludedSourceFiles , string mergeWith , string [ ] excludeAttributes )
31+ public Coverage ( string module , string [ ] excludeFilters , string [ ] includeFilters , string [ ] includeDirectories , string [ ] excludedSourceFiles , string mergeWith , string [ ] excludeAttributes )
3132 {
3233 _module = module ;
3334 _excludeFilters = excludeFilters ;
3435 _includeFilters = includeFilters ;
36+ _includeDirectories = includeDirectories ?? Array . Empty < string > ( ) ;
3537 _excludedSourceFiles = excludedSourceFiles ;
3638 _mergeWith = mergeWith ;
3739 _excludeAttributes = excludeAttributes ;
@@ -42,23 +44,33 @@ public Coverage(string module, string[] excludeFilters, string[] includeFilters,
4244
4345 public void PrepareModules ( )
4446 {
45- string [ ] modules = InstrumentationHelper . GetCoverableModules ( _module ) ;
47+ string [ ] modules = InstrumentationHelper . GetCoverableModules ( _module , _includeDirectories ) ;
4648 string [ ] excludes = InstrumentationHelper . GetExcludedFiles ( _excludedSourceFiles ) ;
4749 _excludeFilters = _excludeFilters ? . Where ( f => InstrumentationHelper . IsValidFilterExpression ( f ) ) . ToArray ( ) ;
4850 _includeFilters = _includeFilters ? . Where ( f => InstrumentationHelper . IsValidFilterExpression ( f ) ) . ToArray ( ) ;
4951
5052 foreach ( var module in modules )
5153 {
52- if ( InstrumentationHelper . IsModuleExcluded ( module , _excludeFilters )
53- || ! InstrumentationHelper . IsModuleIncluded ( module , _includeFilters ) )
54+ if ( InstrumentationHelper . IsModuleExcluded ( module , _excludeFilters ) ||
55+ ! InstrumentationHelper . IsModuleIncluded ( module , _includeFilters ) )
5456 continue ;
5557
5658 var instrumenter = new Instrumenter ( module , _identifier , _excludeFilters , _includeFilters , excludes , _excludeAttributes ) ;
5759 if ( instrumenter . CanInstrument ( ) )
5860 {
5961 InstrumentationHelper . BackupOriginalModule ( module , _identifier ) ;
60- var result = instrumenter . Instrument ( ) ;
61- _results . Add ( result ) ;
62+
63+ // Guard code path and restore if instrumentation fails.
64+ try
65+ {
66+ var result = instrumenter . Instrument ( ) ;
67+ _results . Add ( result ) ;
68+ }
69+ catch ( Exception )
70+ {
71+ // TODO: With verbose logging we should note that instrumentation failed.
72+ InstrumentationHelper . RestoreOriginalModule ( module , _identifier ) ;
73+ }
6274 }
6375 }
6476 }
@@ -153,6 +165,7 @@ public CoverageResult GetCoverageResult()
153165 }
154166
155167 var coverageResult = new CoverageResult { Identifier = _identifier , Modules = modules } ;
168+
156169 if ( ! string . IsNullOrEmpty ( _mergeWith ) && ! string . IsNullOrWhiteSpace ( _mergeWith ) && File . Exists ( _mergeWith ) )
157170 {
158171 string json = File . ReadAllText ( _mergeWith ) ;
@@ -207,29 +220,29 @@ private void CalculateCoverage()
207220 }
208221 }
209222
210- // for MoveNext() compiler autogenerated method we need to patch false positive (IAsyncStateMachine for instance)
211- // we'll remove all MoveNext() not covered branch
212- foreach ( var document in result . Documents )
213- {
214- List < KeyValuePair < ( int , int ) , Branch > > branchesToRemove = new List < KeyValuePair < ( int , int ) , Branch > > ( ) ;
215- foreach ( var branch in document . Value . Branches )
216- {
217- //if one branch is covered we search the other one only if it's not covered
218- if ( CecilSymbolHelper . IsMoveNext ( branch . Value . Method ) && branch . Value . Hits > 0 )
219- {
220- foreach ( var moveNextBranch in document . Value . Branches )
221- {
222- if ( moveNextBranch . Value . Method == branch . Value . Method && moveNextBranch . Value != branch . Value && moveNextBranch . Value . Hits == 0 )
223- {
224- branchesToRemove . Add ( moveNextBranch ) ;
225- }
226- }
227- }
228- }
229- foreach ( var branchToRemove in branchesToRemove )
230- {
231- document . Value . Branches . Remove ( branchToRemove . Key ) ;
232- }
223+ // for MoveNext() compiler autogenerated method we need to patch false positive (IAsyncStateMachine for instance)
224+ // we'll remove all MoveNext() not covered branch
225+ foreach ( var document in result . Documents )
226+ {
227+ List < KeyValuePair < ( int , int ) , Branch > > branchesToRemove = new List < KeyValuePair < ( int , int ) , Branch > > ( ) ;
228+ foreach ( var branch in document . Value . Branches )
229+ {
230+ //if one branch is covered we search the other one only if it's not covered
231+ if ( CecilSymbolHelper . IsMoveNext ( branch . Value . Method ) && branch . Value . Hits > 0 )
232+ {
233+ foreach ( var moveNextBranch in document . Value . Branches )
234+ {
235+ if ( moveNextBranch . Value . Method == branch . Value . Method && moveNextBranch . Value != branch . Value && moveNextBranch . Value . Hits == 0 )
236+ {
237+ branchesToRemove . Add ( moveNextBranch ) ;
238+ }
239+ }
240+ }
241+ }
242+ foreach ( var branchToRemove in branchesToRemove )
243+ {
244+ document . Value . Branches . Remove ( branchToRemove . Key ) ;
245+ }
233246 }
234247
235248 InstrumentationHelper . DeleteHitsFile ( result . HitsFilePath ) ;
0 commit comments