提交 e01120a5 编写于 作者: K Kevin Halverson 提交者: GitHub

Merge pull request #13299 from KevinH-MS/oop

Add support for TestImpact out-of-proc emit...
......@@ -25,26 +25,26 @@ protected RemoteHostClient(Workspace workspace)
public event EventHandler<bool> ConnectionChanged;
public Task<Session> CreateCodeAnalysisServiceSessionAsync(Solution solution, CancellationToken cancellationToken)
public Task<Session> CreateServiceSessionAsync(string serviceName, Solution solution, CancellationToken cancellationToken)
{
return CreateCodeAnalysisServiceSessionAsync(solution, callbackTarget: null, cancellationToken: cancellationToken);
return CreateServiceSessionAsync(serviceName, solution, callbackTarget: null, cancellationToken: cancellationToken);
}
public async Task<Session> CreateCodeAnalysisServiceSessionAsync(Solution solution, object callbackTarget, CancellationToken cancellationToken)
public async Task<Session> CreateServiceSessionAsync(string serviceName, Solution solution, object callbackTarget, CancellationToken cancellationToken)
{
Contract.ThrowIfFalse(solution.Workspace == _workspace);
var service = _workspace.Services.GetService<ISolutionChecksumService>();
var snapshot = await service.CreateChecksumAsync(solution, cancellationToken).ConfigureAwait(false);
return await CreateCodeAnalysisServiceSessionAsync(snapshot, callbackTarget, cancellationToken).ConfigureAwait(false);
return await CreateServiceSessionAsync(serviceName, snapshot, callbackTarget, cancellationToken).ConfigureAwait(false);
}
protected abstract void OnConnected();
protected abstract void OnDisconnected();
protected abstract Task<Session> CreateCodeAnalysisServiceSessionAsync(ChecksumScope snapshot, object callbackTarget, CancellationToken cancellationToken);
protected abstract Task<Session> CreateServiceSessionAsync(string serviceName, ChecksumScope snapshot, object callbackTarget, CancellationToken cancellationToken);
internal void Shutdown()
{
......
......@@ -262,6 +262,7 @@
<Reference Include="System.ComponentModel.Composition" />
</ItemGroup>
<ItemGroup>
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.TestImpact.BuildManager" />
<InternalsVisibleTo Include="Microsoft.VisualStudio.LanguageServices.Next" />
<InternalsVisibleTo Include="Microsoft.VisualStudio.LanguageServices.CSharp" />
<InternalsVisibleTo Include="Microsoft.VisualStudio.LanguageServices.Implementation" />
......
......@@ -17,6 +17,7 @@
using Microsoft.CodeAnalysis.Remote;
using Microsoft.CodeAnalysis.Remote.Diagnostics;
using Microsoft.CodeAnalysis.Workspaces.Diagnostics;
using Microsoft.VisualStudio.LanguageServices.Implementation.Extensions;
using Microsoft.VisualStudio.LanguageServices.Remote;
using Roslyn.Utilities;
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Remote;
using Microsoft.VisualStudio.LanguageServices.Remote;
using static Microsoft.VisualStudio.LanguageServices.Remote.RemoteHostClient;
namespace Microsoft.VisualStudio.LanguageServices.Implementation.Extensions
{
internal static class RemoteHostClientExtensions
{
public static Task<Session> CreateCodeAnalysisServiceSessionAsync(this RemoteHostClient client, Solution solution, CancellationToken cancellationToken)
{
return CreateCodeAnalysisServiceSessionAsync(client, solution, callbackTarget: null, cancellationToken: cancellationToken);
}
public static Task<Session> CreateCodeAnalysisServiceSessionAsync(this RemoteHostClient client, Solution solution, object callbackTarget, CancellationToken cancellationToken)
{
return client.CreateServiceSessionAsync(WellKnownServiceHubServices.CodeAnalysisService, solution, callbackTarget, cancellationToken);
}
}
}
......@@ -55,7 +55,7 @@ public static async Task<RemoteHostClient> CreateAsync(Workspace workspace, Canc
_rpc.Disconnected += OnRpcDisconnected;
}
protected override async Task<Session> CreateCodeAnalysisServiceSessionAsync(ChecksumScope snapshot, object callbackTarget, CancellationToken cancellationToken)
protected override async Task<Session> CreateServiceSessionAsync(string serviceName, ChecksumScope snapshot, object callbackTarget, CancellationToken cancellationToken)
{
// get stream from service hub to communicate snapshot/asset related information
// this is the back channel the system uses to move data between VS and remote host
......@@ -63,7 +63,7 @@ protected override async Task<Session> CreateCodeAnalysisServiceSessionAsync(Che
// get stream from service hub to communicate service specific information
// this is what consumer actually use to communicate information
var serviceStream = await _hubClient.RequestServiceAsync(WellKnownServiceHubServices.CodeAnalysisService, cancellationToken).ConfigureAwait(false);
var serviceStream = await _hubClient.RequestServiceAsync(serviceName, cancellationToken).ConfigureAwait(false);
return new JsonRpcSession(snapshot, snapshotStream, callbackTarget, serviceStream, cancellationToken);
}
......
......@@ -93,6 +93,7 @@
<Link>Shared\WellKnownServiceHubServices.cs</Link>
</Compile>
<Compile Include="Diagnostics\OutOfProcDiagnosticAnalyzerExecutor.cs" />
<Compile Include="Extensions\RemoteHostClientExtensions.cs" />
<Compile Include="FindReferences\FindReferencesTableControlEventProcessorProvider.cs" />
<Compile Include="FindReferences\ISupportsNavigation.cs" />
<Compile Include="FindReferences\StreamingFindReferencesPresenter.cs" />
......@@ -121,5 +122,8 @@
<LastGenOutput>ServicesVisualStudioNextResources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.TestImpact.BuildManager" />
</ItemGroup>
<Import Project="..\..\..\build\Targets\VSL.Imports.targets" />
</Project>
</Project>
\ No newline at end of file
......@@ -131,6 +131,10 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="emitService.servicehub.service.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<None Include="project.json" />
<Content Include="codeAnalysisService.servicehub.service.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
......@@ -151,4 +155,4 @@
<Compile Include="AssemblyRedirects.cs" />
</ItemGroup>
<Import Project="..\..\..\build\Targets\VSL.Imports.targets" />
</Project>
</Project>
\ No newline at end of file
{
"$schema": "../../../schemas/servicehub.service.schema.json",
"host": "desktopClr.x86",
"hostId": "RoslynCodeAnalysisService32",
"entryPoint": {
......
{
"host": "desktopClr.x86",
"hostId": "RoslynCodeAnalysisService32",
"entryPoint": {
"assemblyPath": "Microsoft.CodeAnalysis.Remote.ServiceHub.dll",
"fullClassName": "Microsoft.CodeAnalysis.TestImpact.BuildManagement.EmitService"
}
}
\ No newline at end of file
{
"$schema": "../../../schemas/servicehub.service.schema.json",
"host": "desktopClr.x86",
"hostId": "RoslynCodeAnalysisService32",
"entryPoint": {
......
{
"$schema": "../../../schemas/servicehub.service.schema.json",
"host": "desktopClr.x86",
"hostId": "RoslynCodeAnalysisService32",
"entryPoint": {
......
......@@ -23,5 +23,6 @@
<Asset Type="Microsoft.ServiceHub.Service" d:Source="File" Path="remoteHostService.servicehub.service.json" />
<Asset Type="Microsoft.ServiceHub.Service" d:Source="File" Path="snapshotService.servicehub.service.json" />
<Asset Type="Microsoft.ServiceHub.Service" d:Source="File" Path="codeAnalysisService.servicehub.service.json" />
<Asset Type="Microsoft.ServiceHub.Service" d:Source="File" Path="emitService.servicehub.service.json" />
</Assets>
</PackageManifest>
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.CodeAnalysis.TestImpact.BuildManagement
{
internal struct Diagnostic
{
public DiagnosticSeverity Severity;
public string Message;
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.CodeAnalysis.TestImpact.BuildManagement
{
internal struct EmitOptions
{
public int FileAlignment;
public ulong BaseAddress;
public bool HighEntropyVirtualAddressSpace;
public string SubsystemVersion;
public string Instrument;
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Immutable;
namespace Microsoft.CodeAnalysis.TestImpact.BuildManagement
{
internal struct EmitResult
{
public bool Success;
public ImmutableArray<Diagnostic> Diagnostics;
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.CodeAnalysis.TestImpact.BuildManagement
{
internal struct ResourceDescription
{
public string Name;
public string File;
public bool IsPublic;
public bool IsLinkResource;
}
}
......@@ -248,6 +248,7 @@
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.Features" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.InteractiveEditorFeatures" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.InteractiveFeatures" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.TestImpact.BuildManager" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.TestImpact.Orchestrator" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.TestImpact.Orchestrator.UnitTests" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.TestImpact.Test.Utilities" />
......@@ -494,6 +495,10 @@
<Compile Include="Shared\Utilities\IProgressTracker.cs" />
<Compile Include="SolutionCrawler\NullSolutionCrawlerRegisterationService.cs" />
<Compile Include="SolutionCrawler\WellKnownSolutionCrawlerAnalyzers.cs" />
<Compile Include="TestImpact\Diagnostic.cs" />
<Compile Include="TestImpact\EmitOptions.cs" />
<Compile Include="TestImpact\EmitResult.cs" />
<Compile Include="TestImpact\ResourceDescription.cs" />
<Compile Include="Utilities\ArraySlice.cs" />
<Compile Include="Utilities\BKTree.cs" />
<Compile Include="FindSymbols\SyntaxTree\AbstractSyntaxTreeInfo.cs" />
......
......@@ -47,6 +47,7 @@
<ItemGroup />
<ItemGroup>
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.Remote.ServiceHub" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.TestImpact.BuildManager" />
</ItemGroup>
<ItemGroup>
<Compile Include="Diagnostics\DiagnosticComputer.cs" />
......@@ -55,6 +56,7 @@
<Compile Include="Services\CompilationService.cs" />
<Compile Include="Services\RoslynServices.cs" />
<Compile Include="Services\SolutionService.cs" />
<Compile Include="TestImpact\EmitHelper.cs" />
</ItemGroup>
<Import Project="..\..\..\..\build\Targets\VSL.Imports.targets" />
</Project>
</Project>
\ No newline at end of file
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Emit;
namespace Microsoft.CodeAnalysis.TestImpact.BuildManagement
{
internal static class EmitHelper
{
private static readonly Dictionary<string, MetadataReference> _runtimeReferenceCache = new Dictionary<string, MetadataReference>(capacity: 2);
public static async Task<EmitResult> EmitAsync(
this Project project,
string outputFilePath,
string win32ResourcePath,
ImmutableArray<ResourceDescription> manifestResources,
EmitOptions options,
string runtimeReferencePath,
CancellationToken cancellationToken)
{
if (File.Exists(outputFilePath))
{
File.Delete(outputFilePath);
}
var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);
if (runtimeReferencePath != null)
{
MetadataReference runtimeReference;
if (!_runtimeReferenceCache.TryGetValue(runtimeReferencePath, out runtimeReference))
{
runtimeReference = MetadataReference.CreateFromFile(runtimeReferencePath);
_runtimeReferenceCache[runtimeReferencePath] = runtimeReference;
}
compilation = compilation.AddReferences(runtimeReference);
}
Stream peStream = null, pdbStream = null, win32Resources = null;
try
{
peStream = new FileStream(outputFilePath, FileMode.Create, FileAccess.Write);
pdbStream = new FileStream(Path.ChangeExtension(outputFilePath, ".pdb"), FileMode.Create, FileAccess.Write);
win32Resources = !string.IsNullOrWhiteSpace(win32ResourcePath) ? new FileStream(win32ResourcePath, FileMode.Open, FileAccess.Read) : null;
var result = compilation.Emit(
peStream,
pdbStream,
xmlDocumentationStream: null, // Do not generate XML documentation.
win32Resources: win32Resources,
manifestResources: GetResourceDescriptions(manifestResources),
options: GetEmitOptions(options),
cancellationToken: cancellationToken);
ArrayBuilder<Diagnostic> builder = null;
foreach (var diagnostic in result.Diagnostics)
{
if (diagnostic.Severity != DiagnosticSeverity.Hidden)
{
if (builder == null)
{
builder = ArrayBuilder<Diagnostic>.GetInstance();
}
builder.Add(new Diagnostic() { Severity = diagnostic.Severity, Message = diagnostic.ToString() });
}
}
return new EmitResult() { Success = result.Success, Diagnostics = builder != null ? builder.ToImmutableAndFree() : ImmutableArray<Diagnostic>.Empty };
}
finally
{
peStream?.Dispose();
pdbStream?.Dispose();
win32Resources?.Dispose();
}
}
private static Microsoft.CodeAnalysis.Emit.EmitOptions GetEmitOptions(EmitOptions options)
{
SubsystemVersion subsystemVersion;
SubsystemVersion.TryParse(options.SubsystemVersion, out subsystemVersion);
return new Microsoft.CodeAnalysis.Emit.EmitOptions(
metadataOnly: false,
debugInformationFormat: DebugInformationFormat.Pdb,
pdbFilePath: null,
outputNameOverride: null,
fileAlignment: options.FileAlignment,
baseAddress: options.BaseAddress,
highEntropyVirtualAddressSpace: options.HighEntropyVirtualAddressSpace,
subsystemVersion: subsystemVersion,
runtimeMetadataVersion: null,
tolerateErrors: false,
includePrivateMembers: true,
instrument: options.Instrument);
}
private static IEnumerable<Microsoft.CodeAnalysis.ResourceDescription> GetResourceDescriptions(ImmutableArray<ResourceDescription> resources)
{
if (resources.IsDefaultOrEmpty)
{
return null;
}
var builder = ArrayBuilder<Microsoft.CodeAnalysis.ResourceDescription>.GetInstance();
foreach (var item in resources)
{
Func<Stream> dataProvider = () => File.Open(item.File, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
builder.Add(item.IsLinkResource ?
new Microsoft.CodeAnalysis.ResourceDescription(item.Name, item.File, dataProvider, item.IsPublic) :
new Microsoft.CodeAnalysis.ResourceDescription(item.Name, dataProvider, item.IsPublic));
}
return builder?.ToImmutableAndFree();
}
}
}
\ No newline at end of file
......@@ -45,6 +45,7 @@
</ItemGroup>
<ItemGroup>
<None Include="project.json" />
<Compile Include="Services\EmitService.cs" />
<Compile Include="Services\SnapshotService.JsonRpcAssetSource.cs" />
<PublicAPI Include="PublicAPI.Shipped.txt" />
<PublicAPI Include="PublicAPI.Unshipped.txt" />
......@@ -62,5 +63,8 @@
<Compile Include="Shared\ClientDirectStream.cs" />
<Compile Include="Shared\WellKnownServiceHubServices.cs" />
</ItemGroup>
<ItemGroup>
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.TestImpact.BuildManager" />
</ItemGroup>
<Import Project="..\..\..\..\build\Targets\VSL.Imports.targets" />
</Project>
</Project>
\ No newline at end of file
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Emit;
using Microsoft.CodeAnalysis.Execution;
using Microsoft.CodeAnalysis.Remote;
namespace Microsoft.CodeAnalysis.TestImpact.BuildManagement
{
internal partial class EmitService : ServiceHubServiceBase
{
public EmitService(Stream stream, IServiceProvider serviceProvider) :
base(stream, serviceProvider)
{
}
public async Task<EmitResult> EmitAsync(
Guid guid,
string debugName,
string outputFilePath,
string win32ResourcesPath,
ImmutableArray<ResourceDescription> manifestResources,
EmitOptions options,
string runtimeReferencePath,
byte[] solutionChecksum)
{
var projectId = ProjectId.CreateFromSerialized(guid, debugName);
var solution = await RoslynServices.SolutionService.GetSolutionAsync(new Checksum(solutionChecksum), CancellationToken).ConfigureAwait(false);
var project = solution.GetProject(projectId);
return await project.EmitAsync(
outputFilePath,
win32ResourcesPath,
manifestResources,
options,
runtimeReferencePath,
CancellationToken).ConfigureAwait(false);
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册