Skip to content

Commit

Permalink
Brokered services (#47216)
Browse files Browse the repository at this point in the history
* Brokered service

* TodoCommentService ISB

* Generate PkgDef entries

* Generate VSIX manifest assets

* Brokered services

* Error reporting

* BrokeredServiceConnection

* Enable cancellation on disconnection

* Error handling

* Remove usage of WellKnownServiceHubService for brokered services

* Semantic classification services

* Fix streaming service calls

* Propagate cancellation token to all services

* Misc

* Fixes

* Feedback

* Comments

* Dispose feedback

* RPC fixes

* Rename brokered services

* Prefix services with Microsoft.VisualStudio

* Fix

* Fix cancelation of OOP analyzer requests
  • Loading branch information
tmat committed Sep 11, 2020
1 parent 6bc9aab commit e53ffb7
Show file tree
Hide file tree
Showing 75 changed files with 1,613 additions and 403 deletions.
11 changes: 5 additions & 6 deletions eng/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,8 @@
<MicrosoftNetSdkVersion>2.0.0-alpha-20170405-2</MicrosoftNetSdkVersion>
<MicrosoftNuGetBuildTasksVersion>0.1.0</MicrosoftNuGetBuildTasksVersion>
<MicrosoftPortableTargetsVersion>0.1.2-dev</MicrosoftPortableTargetsVersion>
<MicrosoftServiceHubClientVersion>2.4.227</MicrosoftServiceHubClientVersion>
<MicrosoftServiceHubFrameworkVersion>2.4.227</MicrosoftServiceHubFrameworkVersion>
<MicrosoftServiceHubClientVersion>2.7.69-alpha</MicrosoftServiceHubClientVersion>
<MicrosoftServiceHubFrameworkVersion>2.7.69-alpha</MicrosoftServiceHubFrameworkVersion>
<MicrosoftVisualBasicVersion>10.1.0</MicrosoftVisualBasicVersion>
<MicrosoftVisualStudioCallHierarchyPackageDefinitionsVersion>15.8.27812-alpha</MicrosoftVisualStudioCallHierarchyPackageDefinitionsVersion>
<MicrosoftVisualStudioCodeAnalysisSdkUIVersion>15.8.27812-alpha</MicrosoftVisualStudioCodeAnalysisSdkUIVersion>
Expand Down Expand Up @@ -141,7 +141,7 @@
<MicrosoftVisualStudioProgressionInterfacesVersion>15.8.27812-alpha</MicrosoftVisualStudioProgressionInterfacesVersion>
<MicrosoftVisualStudioProjectSystemVersion>16.2.133-pre</MicrosoftVisualStudioProjectSystemVersion>
<MicrosoftVisualStudioProjectSystemManagedVersion>2.3.6152103</MicrosoftVisualStudioProjectSystemManagedVersion>
<MicrosoftVisualStudioRemoteControlVersion>16.3.4</MicrosoftVisualStudioRemoteControlVersion>
<MicrosoftVisualStudioRemoteControlVersion>16.3.23</MicrosoftVisualStudioRemoteControlVersion>
<MicrosoftVisualStudioSDKAnalyzersVersion>16.3.14</MicrosoftVisualStudioSDKAnalyzersVersion>
<MicrosoftVisualStudioSetupConfigurationInteropVersion>1.16.30</MicrosoftVisualStudioSetupConfigurationInteropVersion>
<MicrosoftVisualStudioShell150Version>16.6.29925.50-pre</MicrosoftVisualStudioShell150Version>
Expand All @@ -156,7 +156,7 @@
<MicrosoftVisualStudioShellInterop157DesignTimeVersion>15.7.1</MicrosoftVisualStudioShellInterop157DesignTimeVersion>
<MicrosoftVisualStudioShellInterop80Version>8.0.50728</MicrosoftVisualStudioShellInterop80Version>
<MicrosoftVisualStudioShellInterop90Version>9.0.30730</MicrosoftVisualStudioShellInterop90Version>
<MicrosoftVisualStudioTelemetryVersion>16.3.36</MicrosoftVisualStudioTelemetryVersion>
<MicrosoftVisualStudioTelemetryVersion>16.3.58</MicrosoftVisualStudioTelemetryVersion>
<MicrosoftVisualStudioTemplateWizardInterfaceVersion>8.0.0.0-alpha</MicrosoftVisualStudioTemplateWizardInterfaceVersion>
<MicrosoftVisualStudioTextDataVersion>$(VisualStudioEditorPackagesVersion)</MicrosoftVisualStudioTextDataVersion>
<MicrosoftVisualStudioTextInternalVersion>$(VisualStudioEditorPackagesVersion)</MicrosoftVisualStudioTextInternalVersion>
Expand All @@ -180,7 +180,6 @@
<MDbgVersion>0.1.0</MDbgVersion>
<MonoOptionsVersion>4.4.0</MonoOptionsVersion>
<MoqVersion>4.10.1</MoqVersion>
<NerdbankFullDuplexStreamVersion>1.1.12</NerdbankFullDuplexStreamVersion>
<NuGetPackagingVersion>4.9.2</NuGetPackagingVersion>
<NuGetVisualStudioVersion>4.0.0-rc-2048</NuGetVisualStudioVersion>
<NuGetSolutionRestoreManagerInteropVersion>4.8.0</NuGetSolutionRestoreManagerInteropVersion>
Expand Down Expand Up @@ -242,7 +241,7 @@
create a test insertion in Visual Studio to validate.
-->
<NewtonsoftJsonVersion>12.0.2</NewtonsoftJsonVersion>
<StreamJsonRpcVersion>2.4.34</StreamJsonRpcVersion>
<StreamJsonRpcVersion>2.6.21-alpha</StreamJsonRpcVersion>
<SystemCollectionsImmutableVersion>5.0.0-preview.8.20407.11</SystemCollectionsImmutableVersion>
<SystemReflectionMetadataVersion>5.0.0-preview.8.20407.11</SystemReflectionMetadataVersion>
<MicrosoftBclAsyncInterfacesVersion>1.1.1</MicrosoftBclAsyncInterfacesVersion>
Expand Down
39 changes: 34 additions & 5 deletions eng/targets/GeneratePkgDef.targets
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,16 @@
- Name
- DisplayName (resource id)
- ProductDetauls (resource id)
3) PkgDefBrokeredService
Emits $RootKey$\BrokeredServices entry.
Entries with ProfferingPackageId correspond to Microsoft.VisualStudio.Shell.ServiceBroker.ProvideBrokeredServiceAttribute.
Metadata:
- ItemSpec: service name
- ProfferingPackageId (guid, optional): GUID of the proffering package or empty for ServiceHub services
3) PkgDefBindingRedirect
4) PkgDefBindingRedirect
Emits $RootKey$\RuntimeConfiguration\dependentAssembly\bindingRedirection entry.
Project may specify <PkgDefEntry>BindingRedirect</PkgDefEntry> on any item that contributes to ReferencePath item group.
Expand All @@ -39,7 +47,7 @@
- ItemSpec: full path to the binary if FusionName is not specified, otherwise it may be just a file name
- FusionName: optional assembly name (read from the binary if not specified)
4) PkgDefCodeBase
5) PkgDefCodeBase
Emits $RootKey$\RuntimeConfiguration\dependentAssembly\codeBase entry.
Project may specify <PkgDefEntry>CodeBase</PkgDefEntry> on any item that contributes to ReferencePath item group.
Expand All @@ -49,7 +57,7 @@
- ItemSpec: full path to the binary
- FusionName: optional assembly name (read from the binary if not specified)
5) PkgDefFileContent
6) PkgDefFileContent
Merges the content of the file whose path is specified in the identity of the item to the generated pkgdef file.
The path may be relative to the project being built.
Expand All @@ -64,7 +72,7 @@

<UsingTask TaskName="Microsoft.DotNet.Build.Tasks.VisualStudio.GetPkgDefAssemblyDependencyGuid" AssemblyFile="$(ArcadeVisualStudioBuildTasksAssembly)" />
<UsingTask TaskName="Microsoft.DotNet.Arcade.Sdk.GetAssemblyFullName" AssemblyFile="$(ArcadeSdkBuildTasksAssembly)" />

<Target Name="_SetGeneratePkgDefInputsOutputs">
<PropertyGroup>
<!-- The path must match the value that VSSDK uses. -->
Expand Down Expand Up @@ -129,7 +137,7 @@
-->
<Target Name="GeneratePkgDef"
DependsOnTargets="$(GeneratePkgDefDependsOn);_SetGeneratePkgDefInputsOutputs"
Inputs="$(MSBuildAllProjects)"
Inputs="$(MSBuildAllProjects);@(PkgDefFileContent)"
Outputs="$(_GeneratePkgDefOutputFile)">
<ItemGroup>
<_AssemblyDependencyEntry Include="@(PkgDefBindingRedirect)" Kind="BindingRedirect" />
Expand Down Expand Up @@ -195,6 +203,27 @@
"ProductDetails"="%(PkgDefInstalledProduct.ProductDetails)"
"UseInterface"=dword:00000000
"UseVSProductID"=dword:00000000
]]>
</RawValue>
</_PkgDefEntry>

<_PkgDefEntry Include="@(PkgDefBrokeredService)" Condition="'%(PkgDefBrokeredService.ProfferingPackageId)' == ''">
<!-- 11AD60FC-6D87-4674-8F88-9ABE79176CBE is id of the HubClient package which proffers ServiceHub services -->
<RawValue>
<![CDATA[[$RootKey$\BrokeredServices\%(PkgDefBrokeredService.Identity)]
@="11AD60FC-6D87-4674-8F88-9ABE79176CBE"
"IsServiceHub"=dword:00000001
"ServiceLocation"="$PackageFolder$"
"audience"=dword:00000003
]]>
</RawValue>
</_PkgDefEntry>

<_PkgDefEntry Include="@(PkgDefBrokeredService)" Condition="'%(PkgDefBrokeredService.ProfferingPackageId)' != ''">
<RawValue>
<![CDATA[[$RootKey$\BrokeredServices\%(PkgDefBrokeredService.Identity)]
@="%(PkgDefBrokeredService.ProfferingPackageId)"
"audience"=dword:00000003
]]>
</RawValue>
</_PkgDefEntry>
Expand Down
30 changes: 10 additions & 20 deletions eng/targets/GenerateServiceHubConfigurationFiles.targets
Original file line number Diff line number Diff line change
@@ -1,19 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. See the LICENSE file in the project root for more information. -->
<Project>
<!--
The inclusion of this file will cause *.servicehub.service.json files to be created. and these json files contain configuration for the servicehub on how it
should configure our services in servicehub process
-->
<ItemGroup>
<ServiceHubService Include="roslynCodeAnalysis" ClassName="Microsoft.CodeAnalysis.Remote.CodeAnalysisService" />
<ServiceHubService Include="roslynRemoteHost" ClassName="Microsoft.CodeAnalysis.Remote.RemoteHostService" />
<ServiceHubService Include="roslynRemoteDesignerAttributeService" ClassName="Microsoft.CodeAnalysis.Remote.RemoteDesignerAttributeService" />
<ServiceHubService Include="roslynRemoteProjectTelemetryService" ClassName="Microsoft.CodeAnalysis.Remote.RemoteProjectTelemetryService" />
<ServiceHubService Include="roslynRemoteSymbolSearchUpdateEngine" ClassName="Microsoft.CodeAnalysis.Remote.RemoteSymbolSearchUpdateEngine" />
<ServiceHubService Include="roslynRemoteTodoCommentsService" ClassName="Microsoft.CodeAnalysis.Remote.RemoteTodoCommentsService" />
<ServiceHubService Include="roslynLanguageServer" ClassName="Microsoft.CodeAnalysis.Remote.LanguageServer" />
</ItemGroup>
<PropertyGroup>
<RoslynPackageGuid>6cf2e545-6109-4730-8883-cf43d7aec3e1</RoslynPackageGuid>
</PropertyGroup>

<PropertyGroup>
<GetVsixSourceItemsDependsOn>$(GetVsixSourceItemsDependsOn);GenerateServiceHubConfigurationFiles</GetVsixSourceItemsDependsOn>
Expand All @@ -24,7 +14,7 @@
<_ServicesWithBitness Include="@(ServiceHubService)" FileSuffix="" HostSuffix=".x86" HostIdSuffix="32" />
<_ServicesWithBitness Include="@(ServiceHubService)" FileSuffix="64" HostSuffix="" HostIdSuffix="" />

<_JsonFile Include="$(IntermediateOutputPath)%(_ServicesWithBitness.FileName)%(_ServicesWithBitness.FileSuffix).servicehub.service.json">
<ServiceHubServiceJsonFile Include="$(IntermediateOutputPath)%(_ServicesWithBitness.Identity)%(_ServicesWithBitness.FileSuffix).servicehub.service.json">
<Content>
<![CDATA[{
"host": "desktopClr%(_ServicesWithBitness.HostSuffix)",
Expand All @@ -40,21 +30,21 @@
}
]]>
</Content>
</_JsonFile>
</ServiceHubServiceJsonFile>
</ItemGroup>
</Target>

<Target Name="GenerateServiceHubConfigurationFiles"
DependsOnTargets="CalculateServiceHubConfigurationFiles"
BeforeTargets="CreateVsixContainer"
Inputs="$(MSBuildProjectFullPath)"
Outputs="@(_JsonFile)">
Inputs="$(MSBuildAllProjects)"
Outputs="@(ServiceHubServiceJsonFile)">

<WriteLinesToFile File="%(_JsonFile.Identity)" Lines="%(_JsonFile.Content)" Overwrite="true"/>
<WriteLinesToFile File="%(ServiceHubServiceJsonFile.Identity)" Lines="%(ServiceHubServiceJsonFile.Content)" Overwrite="true"/>

<ItemGroup>
<FileWrites Include="@(_JsonFile->'%(Identity)')"/>
<VSIXSourceItem Include="@(_JsonFile->'%(Identity)')" />
<FileWrites Include="@(ServiceHubServiceJsonFile->'%(Identity)')"/>
<VSIXSourceItem Include="@(ServiceHubServiceJsonFile->'%(Identity)')" />
</ItemGroup>
</Target>
</Project>
32 changes: 32 additions & 0 deletions eng/targets/Services.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. See the LICENSE file in the project root for more information. -->
<Project>
<!--
Roslyn ServiceHub services.
Used to generate
1) {service-name}.servicehub.service.json files included in Roslyn setup VSIX and in ServiceHub install directory.
2) ServiceHub brokered service registrations in pkgdef file.
Note that brokered services must be defined in Microsoft.VisualStudio service namespace in order to be considered first party.
-->
<ItemGroup>
<ServiceHubService Include="roslynCodeAnalysis" ClassName="Microsoft.CodeAnalysis.Remote.CodeAnalysisService" />
<ServiceHubService Include="roslynRemoteHost" ClassName="Microsoft.CodeAnalysis.Remote.RemoteHostService" />
<ServiceHubService Include="Microsoft.VisualStudio.LanguageServices.DiagnosticAnalyzer" ClassName="Microsoft.CodeAnalysis.Remote.RemoteDiagnosticAnalyzerService+Factory" IsBrokered="true" />
<ServiceHubService Include="Microsoft.VisualStudio.LanguageServices.SemanticClassification" ClassName="Microsoft.CodeAnalysis.Remote.RemoteSemanticClassificationService+Factory" IsBrokered="true" />
<ServiceHubService Include="Microsoft.VisualStudio.LanguageServices.SemanticClassificationCache" ClassName="Microsoft.CodeAnalysis.Remote.RemoteSemanticClassificationCacheService+Factory" IsBrokered="true" />
<ServiceHubService Include="Microsoft.VisualStudio.LanguageServices.DesignerAttribute" ClassName="Microsoft.CodeAnalysis.Remote.RemoteDesignerAttributeService+Factory" IsBrokered="true" />
<ServiceHubService Include="Microsoft.VisualStudio.LanguageServices.ProjectTelemetry" ClassName="Microsoft.CodeAnalysis.Remote.RemoteProjectTelemetryService+Factory" IsBrokered="true" />
<ServiceHubService Include="roslynRemoteSymbolSearchUpdateEngine" ClassName="Microsoft.CodeAnalysis.Remote.RemoteSymbolSearchUpdateEngine" />
<ServiceHubService Include="Microsoft.VisualStudio.LanguageServices.TodoComments" ClassName="Microsoft.CodeAnalysis.Remote.RemoteTodoCommentsService+Factory" IsBrokered="true" />
<ServiceHubService Include="roslynLanguageServer" ClassName="Microsoft.CodeAnalysis.Remote.LanguageServer" />
</ItemGroup>

<!--
Roslyn in-proc brokered services.
-->
<ItemGroup>
<InProcService Include="Microsoft.VisualStudio.LanguageServices.SolutionAssetProvider" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
<ItemGroup>
<PackageReference Include="Moq" Version="$(MoqVersion)" />
<PackageReference Include="Newtonsoft.Json" Version="$(NewtonsoftJsonVersion)" />
<PackageReference Include="Nerdbank.FullDuplexStream" Version="$(NerdbankFullDuplexStreamVersion)" />
<PackageReference Include="BasicUndo" Version="$(BasicUndoVersion)" />
<PackageReference Include="SQLitePCLRaw.bundle_green" Version="$(SQLitePCLRawbundle_greenVersion)" />
<PackageReference Include="StreamJsonRpc" Version="$(StreamJsonRpcVersion)" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ protected AbstractDesignerAttributeIncrementalAnalyzer(Workspace workspace)
_storageService = workspace.Services.GetRequiredService<IPersistentStorageService>();
}

protected abstract Task ReportProjectRemovedAsync(ProjectId projectId, CancellationToken cancellationToken);
protected abstract ValueTask ReportProjectRemovedAsync(ProjectId projectId, CancellationToken cancellationToken);

protected abstract Task ReportDesignerAttributeDataAsync(List<DesignerAttributeData> data, CancellationToken cancellationToken);
protected abstract ValueTask ReportDesignerAttributeDataAsync(List<DesignerAttributeData> data, CancellationToken cancellationToken);

public override Task RemoveProjectAsync(ProjectId projectId, CancellationToken cancellationToken)
=> ReportProjectRemovedAsync(projectId, cancellationToken);
=> ReportProjectRemovedAsync(projectId, cancellationToken).AsTask();

public override Task AnalyzeProjectAsync(Project project, bool semanticsChanged, InvocationReasons reasons, CancellationToken cancellationToken)
=> AnalyzeProjectAsync(project, specificDocument: null, cancellationToken);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,11 +140,10 @@ private async Task FireAndForgetReportAnalyzerPerformanceAsync(
// +1 for project itself
var count = documentAnalysisScope != null ? 1 : project.DocumentIds.Count + 1;

await client.RunRemoteAsync(
WellKnownServiceHubService.CodeAnalysis,
nameof(IRemoteDiagnosticAnalyzerService.ReportAnalyzerPerformance),
solution: null,
new object[] { analysisResult.AnalyzerTelemetryInfo.ToAnalyzerPerformanceInfo(AnalyzerInfoCache), count },
var performanceInfo = analysisResult.AnalyzerTelemetryInfo.ToAnalyzerPerformanceInfo(AnalyzerInfoCache).ToImmutableArray();

_ = await client.TryInvokeAsync<IRemoteDiagnosticAnalyzerService>(
(service, cancellationToken) => service.ReportAnalyzerPerformanceAsync(performanceInfo, count, cancellationToken),
callbackTarget: null,
cancellationToken).ConfigureAwait(false);
}
Expand Down Expand Up @@ -193,17 +192,17 @@ private async Task<DiagnosticAnalysisResultMap<DiagnosticAnalyzer, DiagnosticAna
project.Id,
analyzerMap.Keys.ToArray());

return await client.RunRemoteAsync(
WellKnownServiceHubService.CodeAnalysis,
nameof(IRemoteDiagnosticAnalyzerService.CalculateDiagnosticsAsync),
var result = await client.TryInvokeAsync<IRemoteDiagnosticAnalyzerService, DiagnosticAnalysisResultMap<DiagnosticAnalyzer, DiagnosticAnalysisResult>>(
solution,
new object[] { argument },
invocation: (service, solutionInfo, stream, cancellationToken) => service.CalculateDiagnosticsAsync(solutionInfo, argument, stream, cancellationToken),
reader: (stream, cancellationToken) => ReadCompilerAnalysisResultAsync(stream, analyzerMap, documentAnalysisScope, project, cancellationToken),
callbackTarget: null,
(s, c) => ReadCompilerAnalysisResultAsync(s, analyzerMap, documentAnalysisScope, project, c),
cancellationToken).ConfigureAwait(false);

return result.HasValue ? result.Value : DiagnosticAnalysisResultMap<DiagnosticAnalyzer, DiagnosticAnalysisResult>.Empty;
}

private static async Task<DiagnosticAnalysisResultMap<DiagnosticAnalyzer, DiagnosticAnalysisResult>> ReadCompilerAnalysisResultAsync(
private static async ValueTask<DiagnosticAnalysisResultMap<DiagnosticAnalyzer, DiagnosticAnalysisResult>> ReadCompilerAnalysisResultAsync(
Stream stream,
Dictionary<string, DiagnosticAnalyzer> analyzerMap,
DocumentAnalysisScope? documentAnalysisScope,
Expand All @@ -213,7 +212,7 @@ private static async Task<DiagnosticAnalysisResultMap<DiagnosticAnalyzer, Diagno
// handling of cancellation and exception
var version = await DiagnosticIncrementalAnalyzer.GetDiagnosticVersionAsync(project, cancellationToken).ConfigureAwait(false);

using var reader = ObjectReader.TryGetReader(stream, leaveOpen: true, cancellationToken);
using var reader = ObjectReader.TryGetReader(stream, leaveOpen: false, cancellationToken);

// We only get a reader for data transmitted between live processes.
// This data should always be correct as we're never persisting the data between sessions.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Remote;
Expand All @@ -12,8 +14,8 @@ namespace Microsoft.CodeAnalysis.Diagnostics
{
internal interface IRemoteDiagnosticAnalyzerService
{
Task CalculateDiagnosticsAsync(PinnedSolutionInfo solutionInfo, DiagnosticArguments arguments, string streamName, CancellationToken cancellationToken);
void ReportAnalyzerPerformance(List<AnalyzerPerformanceInfo> snapshot, int unitCount, CancellationToken cancellationToken);
ValueTask CalculateDiagnosticsAsync(PinnedSolutionInfo solutionInfo, DiagnosticArguments arguments, Stream outputStream, CancellationToken cancellationToken);
ValueTask ReportAnalyzerPerformanceAsync(ImmutableArray<AnalyzerPerformanceInfo> snapshot, int unitCount, CancellationToken cancellationToken);
}

internal readonly struct AnalyzerPerformanceInfo
Expand Down
Loading

0 comments on commit e53ffb7

Please sign in to comment.