@@ -8,28 +8,34 @@ namespace Microsoft.VisualStudio.TestPlatform.Utilities
8
8
using System . Collections . ObjectModel ;
9
9
using System . IO ;
10
10
using System . Linq ;
11
+ using System . Reflection ;
11
12
using System . Threading ;
12
13
using System . Threading . Tasks ;
13
14
14
- using Microsoft . VisualStudio . Coverage . CoreLib . Net ;
15
15
using Microsoft . VisualStudio . TestPlatform . ObjectModel ;
16
16
using Microsoft . VisualStudio . TestPlatform . ObjectModel . DataCollection ;
17
17
using Microsoft . VisualStudio . TestPlatform . ObjectModel . Logging ;
18
+ using Microsoft . VisualStudio . TestPlatform . PlatformAbstractions ;
18
19
19
20
public class CodeCoverageDataAttachmentsHandler : IDataCollectorAttachmentProcessor
20
21
{
21
22
private const string CoverageUri = "datacollector://microsoft/CodeCoverage/2.0" ;
22
23
private const string CoverageFileExtension = ".coverage" ;
23
24
private const string CoverageFriendlyName = "Code Coverage" ;
24
25
26
+ private const string CodeCoverageCoreLibNetAssemblyName = "Microsoft.VisualStudio.Coverage.CoreLib.Net" ;
27
+ private const string CoverageFileUtilityTypeName = "CoverageFileUtility" ;
28
+ private const string MergeMethodName = "MergeCoverageFilesAsync" ;
29
+ private const string WriteMethodName = "WriteCoverageFile" ;
30
+
25
31
private static readonly Uri CodeCoverageDataCollectorUri = new Uri ( CoverageUri ) ;
26
32
27
33
public bool SupportsIncrementalProcessing => true ;
28
34
29
35
public IEnumerable < Uri > GetExtensionUris ( )
30
36
{
31
37
yield return CodeCoverageDataCollectorUri ;
32
- }
38
+ }
33
39
34
40
public async Task < ICollection < AttachmentSet > > ProcessAttachmentSetsAsync ( ICollection < AttachmentSet > attachments , IProgress < int > progressReporter , IMessageLogger logger , CancellationToken cancellationToken )
35
41
{
@@ -53,7 +59,7 @@ public async Task<ICollection<AttachmentSet>> ProcessAttachmentSetsAsync(ICollec
53
59
}
54
60
}
55
61
56
- if ( coverageReportFilePaths . Count > 1 )
62
+ if ( coverageReportFilePaths . Count > 1 )
57
63
{
58
64
var mergedCoverageReportFilePath = await this . MergeCodeCoverageFilesAsync ( coverageReportFilePaths , progressReporter , cancellationToken ) . ConfigureAwait ( false ) ;
59
65
if ( ! string . IsNullOrEmpty ( mergedCoverageReportFilePath ) )
@@ -106,15 +112,25 @@ private async Task<string> MergeCodeCoverageFilesAsync(IList<string> files, IPro
106
112
107
113
private async Task < string > MergeCodeCoverageFilesAsync ( IList < string > files , CancellationToken cancellationToken )
108
114
{
109
- var coverageUtility = new CoverageFileUtility ( ) ;
110
-
111
- var coverageData = await coverageUtility . MergeCoverageFilesAsync (
112
- files ,
113
- cancellationToken ) . ConfigureAwait ( false ) ;
114
-
115
- coverageUtility . WriteCoverageFile ( files [ 0 ] , coverageData ) ;
116
-
117
- foreach ( var file in files . Skip ( 1 ) )
115
+ cancellationToken . ThrowIfCancellationRequested ( ) ;
116
+
117
+ var assemblyPath = Path . Combine ( Path . GetDirectoryName ( typeof ( CodeCoverageDataAttachmentsHandler ) . GetTypeInfo ( ) . Assembly . GetAssemblyLocation ( ) ) , CodeCoverageCoreLibNetAssemblyName + ".dll" ) ;
118
+
119
+ // Get assembly, type and methods
120
+ Assembly assembly = new PlatformAssemblyLoadContext ( ) . LoadAssemblyFromPath ( assemblyPath ) ;
121
+ var classType = assembly . GetType ( $ "{ CodeCoverageCoreLibNetAssemblyName } .{ CoverageFileUtilityTypeName } ") ;
122
+ var classInstance = Activator . CreateInstance ( classType ) ;
123
+ var mergeMethodInfo = classType ? . GetMethod ( MergeMethodName , new [ ] { typeof ( IList < string > ) , typeof ( CancellationToken ) } ) ;
124
+ var writeMethodInfo = classType ? . GetMethod ( WriteMethodName ) ;
125
+
126
+ // Invoke methods
127
+ var task = ( Task ) mergeMethodInfo . Invoke ( classInstance , new object [ ] { files , cancellationToken } ) ;
128
+ await task . ConfigureAwait ( false ) ;
129
+ var coverageData = task . GetType ( ) . GetProperty ( "Result" ) . GetValue ( task , null ) ;
130
+ writeMethodInfo . Invoke ( classInstance , new object [ ] { files [ 0 ] , coverageData } ) ;
131
+
132
+ // Delete original files and keep merged file only
133
+ foreach ( var file in files . Skip ( 1 ) )
118
134
{
119
135
try
120
136
{
0 commit comments