/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Workspaces/Remote/ServiceHub/Services/BrokeredServiceBase.cs
219 строк
9 KB
Cyrus Najmabadi
Remove unnnecessary null suppressions in Roslyn.sln
17 окт 2025, 22:55
17 окт 2025, 22:55
ec722c4
Код
Авторство
О чём код?
// 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. using System; using System.ComponentModel; using System.Diagnostics; using System.Runtime; using System.Runtime.InteropServices; using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.ErrorReporting; using Microsoft.CodeAnalysis.Host; using Microsoft.ServiceHub.Framework; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.Remote; /// <summary> /// Base type for Roslyn brokered services hosted in ServiceHub. /// </summary> internal abstract partial class BrokeredServiceBase : IDisposable { protected readonly TraceSource TraceLogger; protected RemoteWorkspaceManager WorkspaceManager => TestData?.WorkspaceManager ?? RemoteWorkspaceManager.Default; protected readonly SolutionAssetSource SolutionAssetSource; protected readonly ServiceBrokerClient ServiceBrokerClient; // test data are only available when running tests: internal readonly RemoteHostTestData? TestData; static BrokeredServiceBase() { if (GCSettings.IsServerGC) { // Server GC runs processor-affinitized threads with high priority. To avoid interfering with other // applications while still allowing efficient out-of-process execution, slightly reduce the process // priority when using server GC. Process.GetCurrentProcess().TrySetPriorityClass(ProcessPriorityClass.BelowNormal); } // Make encodings that is by default present in desktop framework but not in corefx available to runtime. Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); #if DEBUG // Make sure debug assertions in ServiceHub result in exceptions instead of the assertion UI Trace.Listeners.Clear(); Trace.Listeners.Add(new ThrowingTraceListener()); #endif SetNativeDllSearchDirectories(); } protected BrokeredServiceBase(in ServiceConstructionArguments arguments) { var traceSource = (TraceSource?)arguments.ServiceProvider.GetService(typeof(TraceSource)); Contract.ThrowIfNull(traceSource); TraceLogger = traceSource; TestData = (RemoteHostTestData?)arguments.ServiceProvider.GetService(typeof(RemoteHostTestData)); #pragma warning disable VSTHRD012 // Provide JoinableTaskFactory where allowed ServiceBrokerClient = new ServiceBrokerClient(arguments.ServiceBroker); #pragma warning restore SolutionAssetSource = new SolutionAssetSource(ServiceBrokerClient); } public virtual void Dispose() => ServiceBrokerClient.Dispose(); public RemoteWorkspace GetWorkspace() => WorkspaceManager.GetWorkspace(); public SolutionServices GetWorkspaceServices() => GetWorkspace().Services.SolutionServices; public static TService GetRequiredService<TService>() => RemoteExportProviderBuilder.ExportProvider.GetExportedValue<TService>(); protected void Log(TraceEventType errorType, string message) => TraceLogger.TraceEvent(errorType, 0, $"{GetType()}: {message}"); protected async ValueTask<T> RunWithSolutionAsync<T>( Checksum solutionChecksum, Func<Solution, ValueTask<T>> implementation, CancellationToken cancellationToken) { var workspace = GetWorkspace(); var assetProvider = workspace.CreateAssetProvider(solutionChecksum, WorkspaceManager.SolutionAssetCache, SolutionAssetSource); var (_, result) = await workspace.RunWithSolutionAsync( assetProvider, solutionChecksum, implementation, cancellationToken).ConfigureAwait(false); return result; } protected static ValueTask<T> RunServiceAsync<T>(Func<CancellationToken, ValueTask<T>> implementation, CancellationToken cancellationToken) { return RunServiceImplAsync(implementation, cancellationToken); } protected ValueTask<T> RunServiceAsync<T>( Checksum solutionChecksum, Func<Solution, ValueTask<T>> implementation, CancellationToken cancellationToken) { return RunServiceAsync( c => RunWithSolutionAsync(solutionChecksum, implementation, c), cancellationToken); } internal static async ValueTask<T> RunServiceImplAsync<T>(Func<CancellationToken, ValueTask<T>> implementation, CancellationToken cancellationToken) { try { return await implementation(cancellationToken).ConfigureAwait(false); } catch (Exception ex) when (FatalError.ReportAndPropagateUnlessCanceled(ex, cancellationToken)) { throw ExceptionUtilities.Unreachable(); } } protected static ValueTask RunServiceAsync(Func<CancellationToken, ValueTask> implementation, CancellationToken cancellationToken) { return RunServiceImplAsync(implementation, cancellationToken); } protected ValueTask RunServiceAsync( Checksum solutionChecksum, Func<Solution, ValueTask> implementation, CancellationToken cancellationToken) { return RunServiceAsync( async c => { await RunWithSolutionAsync( solutionChecksum, async s => { await implementation(s).ConfigureAwait(false); // bridge this void 'implementation' callback to the non-void type the underlying api needs. return false; }, c).ConfigureAwait(false); }, cancellationToken); } protected ValueTask RunServiceAsync( Checksum solutionChecksum1, Checksum solutionChecksum2, Func<Solution, Solution, ValueTask> implementation, CancellationToken cancellationToken) { return RunServiceAsync( solutionChecksum1, s1 => RunServiceAsync( solutionChecksum2, s2 => implementation(s1, s2), cancellationToken), cancellationToken); } internal static async ValueTask RunServiceImplAsync(Func<CancellationToken, ValueTask> implementation, CancellationToken cancellationToken) { try { await implementation(cancellationToken).ConfigureAwait(false); } catch (Exception ex) when (FatalError.ReportAndPropagateUnlessCanceled(ex, cancellationToken)) { throw ExceptionUtilities.Unreachable(); } } /// <summary> /// Use for on-demand retrieval of language-specific options from the client. /// /// If the service doesn't know up-front for which languages it will need to retrieve specific options, /// its ICallback interface should implement <see cref="IRemoteOptionsCallback{TOptions}"/> and use this /// method to create the options provider to be passed to the feature implementation. /// </summary> protected static OptionsProvider<TOptions> GetClientOptionsProvider<TOptions, TCallback>(RemoteCallback<TCallback> callback, RemoteServiceCallbackId callbackId) where TCallback : class, IRemoteOptionsCallback<TOptions> => new ClientOptionsProvider<TOptions, TCallback>(callback, callbackId); private static void SetNativeDllSearchDirectories() { if (PlatformInformation.IsWindows) { // Set LoadLibrary search directory to %VSINSTALLDIR%\Common7\IDE so that the compiler // can P/Invoke to Microsoft.DiaSymReader.Native when emitting Windows PDBs. // // The AppDomain base directory is specified in VisualStudio\Setup\codeAnalysisService.servicehub.service.json // to be the directory where devenv.exe is -- which is exactly the directory we need to add to the search paths: // // "appBasePath": "%VSAPPIDDIR%" // var loadDir = AppDomain.CurrentDomain.BaseDirectory; try { [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] static extern IntPtr AddDllDirectory(string directory); if (AddDllDirectory(loadDir) == IntPtr.Zero) { throw new Win32Exception(); } } catch (EntryPointNotFoundException) { // AddDllDirectory API might not be available on Windows 7. Environment.SetEnvironmentVariable("MICROSOFT_DIASYMREADER_NATIVE_ALT_LOAD_PATH", loadDir); } } } }