Skip to content

Commit e552103

Browse files
authored
Remove RoslynServiceExtensions.GetServiceAsync (#77799)
Fixes #73636 Remove the RoslynServiceExtensions.GetServiceAsync and instead encourage use of the standard IAsyncServiceProvider* methods. The VS implementation of these methods has been changed to better understand which interfaces require a main thread switch for the cast, as opposed to the roslyn implementations which blindly did a main thread switch.
1 parent fbce2ba commit e552103

17 files changed

+20
-118
lines changed

eng/config/BannedSymbols.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@ M:Microsoft.CodeAnalysis.Document.GetOptionsAsync(System.Threading.CancellationT
2626
T:Microsoft.CodeAnalysis.Options.DocumentOptionSet; Use AnalyzerConfigOptions instead
2727
M:Microsoft.VisualStudio.Shell.ServiceExtensions.GetService``2(System.IServiceProvider); Use RoslynServiceExtensions instead. This extension internally relies on ThreadHelper, which is incompatible with testing.
2828
M:Microsoft.VisualStudio.Shell.ServiceExtensions.GetService``2(System.IServiceProvider,System.Boolean); Use RoslynServiceExtensions instead. This extension internally relies on ThreadHelper, which is incompatible with testing
29-
M:Microsoft.VisualStudio.Shell.ServiceExtensions.GetServiceAsync``2(Microsoft.VisualStudio.Shell.IAsyncServiceProvider); Use RoslynServiceExtensions instead. This extension internally relies on ThreadHelper, which is incompatible with testing
30-
M:Microsoft.VisualStudio.Shell.ServiceExtensions.GetServiceAsync``2(Microsoft.VisualStudio.Shell.IAsyncServiceProvider,System.Boolean); Use RoslynServiceExtensions instead. This extension internally relies on ThreadHelper, which is incompatible with testing
3129
P:Microsoft.VisualStudio.Shell.ThreadHelper.JoinableTaskFactory; Use IThreadingContext.JoinableTaskFactory instead.
3230
M:Microsoft.CodeAnalysis.Formatting.Formatter.FormatAsync(Microsoft.CodeAnalysis.Document,Microsoft.CodeAnalysis.Options.OptionSet,System.Threading.CancellationToken); Use internal overload instead
3331
M:Microsoft.CodeAnalysis.Formatting.Formatter.FormatAsync(Microsoft.CodeAnalysis.Document,Microsoft.CodeAnalysis.Text.TextSpan,Microsoft.CodeAnalysis.Options.OptionSet,System.Threading.CancellationToken); Use overload with SyntaxFormattingOptions instead

src/EditorFeatures/Core.Wpf/Utilities/RoslynServiceExtensions.cs

Lines changed: 0 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44

55
using System;
66
using System.Diagnostics.CodeAnalysis;
7-
using System.Threading.Tasks;
8-
using Microsoft.VisualStudio.Shell;
97
using Microsoft.VisualStudio.Threading;
108

119
namespace Microsoft.VisualStudio.Shell
@@ -25,12 +23,6 @@ public static TInterface GetServiceOnMainThread<TService, TInterface>(this IServ
2523
return @interface;
2624
}
2725

28-
/// <summary>
29-
/// Returns the specified service type from the service.
30-
/// </summary>
31-
public static TServiceType GetServiceOnMainThread<TServiceType>(this IServiceProvider serviceProvider) where TServiceType : class
32-
=> serviceProvider.GetServiceOnMainThread<TServiceType, TServiceType>();
33-
3426
/// <summary>
3527
/// Gets a service interface from a service provider.
3628
/// </summary>
@@ -99,88 +91,5 @@ public static TInterface GetService<TService, TInterface>(
9991
return @interface;
10092
});
10193
}
102-
103-
/// <summary>
104-
/// Gets a service interface from a service provider asynchronously.
105-
/// </summary>
106-
/// <typeparam name="TService">The service type</typeparam>
107-
/// <typeparam name="TInterface">The interface type</typeparam>
108-
/// <param name="asyncServiceProvider">The async service provider</param>
109-
/// <returns>The requested service interface. Never <see langword="null"/>.</returns>
110-
/// <exception cref="ServiceUnavailableException">
111-
/// Either the service could not be acquired, or the service does not support
112-
/// the requested interface.
113-
/// </exception>
114-
public static Task<TInterface> GetServiceAsync<TService, TInterface>(
115-
this IAsyncServiceProvider asyncServiceProvider,
116-
JoinableTaskFactory joinableTaskFactory)
117-
where TInterface : class
118-
{
119-
return GetServiceAsync<TService, TInterface>(asyncServiceProvider, joinableTaskFactory, throwOnFailure: true)!;
120-
}
121-
122-
/// <summary>
123-
/// Gets a service interface from a service provider asynchronously.
124-
/// </summary>
125-
/// <typeparam name="TService">The service type</typeparam>
126-
/// <typeparam name="TInterface">The interface type</typeparam>
127-
/// <param name="asyncServiceProvider">The async service provider</param>
128-
/// <param name="throwOnFailure">
129-
/// Determines how a failure to get the requested service interface is handled. If <see langword="true"/>, an
130-
/// exception is thrown; if <see langword="false"/>, <see langword="null"/> is returned.
131-
/// </param>
132-
/// <returns>The requested service interface, if it could be obtained; otherwise <see langword="null"/> if
133-
/// <paramref name="throwOnFailure"/> is <see langword="false"/>.</returns>
134-
/// <exception cref="ServiceUnavailableException">
135-
/// Either the service could not be acquired, or the service does not support
136-
/// the requested interface.
137-
/// </exception>
138-
public static async Task<TInterface?> GetServiceAsync<TService, TInterface>(
139-
this IAsyncServiceProvider asyncServiceProvider,
140-
JoinableTaskFactory joinableTaskFactory,
141-
bool throwOnFailure)
142-
where TInterface : class
143-
{
144-
Requires.NotNull(asyncServiceProvider, nameof(asyncServiceProvider));
145-
object? service;
146-
147-
// Prefer IAsyncServiceProvider2 so that any original exceptions can be captured and included as an inner
148-
// exception to the one that we throw.
149-
if (throwOnFailure && asyncServiceProvider is IAsyncServiceProvider2 asyncServiceProvider2)
150-
{
151-
try
152-
{
153-
service = await asyncServiceProvider2.GetServiceAsync(typeof(TService), swallowExceptions: false).ConfigureAwait(true);
154-
}
155-
catch (Exception ex)
156-
{
157-
throw new ServiceUnavailableException(typeof(TService), ex);
158-
}
159-
}
160-
else
161-
{
162-
service = await asyncServiceProvider.GetServiceAsync(typeof(TService)).ConfigureAwait(true);
163-
}
164-
165-
if (service == null)
166-
{
167-
if (throwOnFailure)
168-
throw new ServiceUnavailableException(typeof(TService));
169-
170-
return null;
171-
}
172-
173-
await joinableTaskFactory.SwitchToMainThreadAsync();
174-
175-
if (service is not TInterface @interface)
176-
{
177-
if (throwOnFailure)
178-
throw new ServiceUnavailableException(typeof(TInterface));
179-
180-
return null;
181-
}
182-
183-
return @interface;
184-
}
18594
}
18695
}

src/EditorFeatures/TestUtilities/StubVsServiceExporter`2.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public StubVsServiceExporter(
3434
[Import(typeof(SAsyncServiceProvider))] IAsyncServiceProvider2 asyncServiceProvider,
3535
JoinableTaskContext joinableTaskContext)
3636
{
37-
_serviceGetter = new AsyncLazy<TInterface>(() => asyncServiceProvider.GetServiceAsync<TService, TInterface>(joinableTaskContext.Factory, throwOnFailure: true)!, joinableTaskContext.Factory);
37+
_serviceGetter = new AsyncLazy<TInterface>(() => asyncServiceProvider.GetServiceAsync<TService, TInterface>(throwOnFailure: true, CancellationToken.None)!, joinableTaskContext.Factory);
3838
}
3939

4040
/// <inheritdoc />

src/VisualStudio/Core/Def/ColorSchemes/ColorSchemeApplier.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ public void RegisterInitializationWork(PackageLoadTasks packageInitializationTas
7272

7373
private async Task AfterPackageLoadedBackgroundThreadAsync(PackageLoadTasks afterPackageLoadedTasks, CancellationToken cancellationToken)
7474
{
75-
var settingsManager = await _asyncServiceProvider.GetServiceAsync<SVsSettingsPersistenceManager, ISettingsManager>(_threadingContext.JoinableTaskFactory).ConfigureAwait(false);
75+
var settingsManager = await _asyncServiceProvider.GetServiceAsync<SVsSettingsPersistenceManager, ISettingsManager>(cancellationToken).ConfigureAwait(false);
7676

7777
// We need to update the theme whenever the Editor Color Scheme setting changes.
7878
settingsManager.GetSubset(ColorSchemeOptionsStorage.ColorSchemeSettingKey).SettingChangedAsync += ColorSchemeChangedAsync;

src/VisualStudio/Core/Def/Diagnostics/VisualStudioDiagnosticAnalyzerService.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public async Task InitializeAsync(IAsyncServiceProvider serviceProvider, Cancell
6262
_serviceProvider = (IServiceProvider)serviceProvider;
6363

6464
// Hook up the "Run Code Analysis" menu command for CPS based managed projects.
65-
var menuCommandService = await serviceProvider.GetServiceAsync<IMenuCommandService, IMenuCommandService>(_threadingContext.JoinableTaskFactory, throwOnFailure: false).ConfigureAwait(false);
65+
var menuCommandService = await serviceProvider.GetServiceAsync<IMenuCommandService, IMenuCommandService>(throwOnFailure: false, cancellationToken).ConfigureAwait(false);
6666
if (menuCommandService != null)
6767
{
6868
await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);

src/VisualStudio/Core/Def/ProjectSystem/RuleSets/RuleSetEventHandler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public async Task RegisterAsync(IAsyncServiceProvider serviceProvider, Cancellat
4141
{
4242
if (!_eventsHookedUp)
4343
{
44-
var trackProjectDocuments = await serviceProvider.GetServiceAsync<SVsTrackProjectDocuments, IVsTrackProjectDocuments2>(_threadingContext.JoinableTaskFactory).ConfigureAwait(false);
44+
var trackProjectDocuments = await serviceProvider.GetServiceAsync<SVsTrackProjectDocuments, IVsTrackProjectDocuments2>(cancellationToken).ConfigureAwait(false);
4545
await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
4646

4747
if (!_eventsHookedUp)

src/VisualStudio/Core/Def/ProjectSystem/VisualStudioWorkspaceImpl.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -924,7 +924,7 @@ private bool TryAddEditorConfigToSolutionItems(
924924
return false;
925925

926926
// All checks pass, so let's treat this special.
927-
var dte = _threadingContext.JoinableTaskFactory.Run(() => _asyncServiceProvider.GetServiceAsync<SDTE, EnvDTE.DTE>(_threadingContext.JoinableTaskFactory));
927+
var dte = _threadingContext.JoinableTaskFactory.Run(() => _asyncServiceProvider.GetServiceAsync<SDTE, EnvDTE.DTE>(_threadingContext.DisposalToken));
928928

929929
const string SolutionItemsFolderName = "Solution Items";
930930

src/VisualStudio/Core/Def/RoslynPackage.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,9 +133,9 @@ Task OnAfterPackageLoadedMainThreadAsync(PackageLoadTasks afterPackageLoadedTask
133133
private async Task ProfferServiceBrokerServicesAsync(CancellationToken cancellationToken)
134134
{
135135
// Proffer in-process service broker services
136-
var serviceBrokerContainer = await this.GetServiceAsync<SVsBrokeredServiceContainer, IBrokeredServiceContainer>(throwOnFailure: true, cancellationToken).ConfigureAwait(false);
136+
var serviceBrokerContainer = await this.GetServiceAsync<SVsBrokeredServiceContainer, IBrokeredServiceContainer>(cancellationToken).ConfigureAwait(false);
137137

138-
serviceBrokerContainer!.Proffer(
138+
serviceBrokerContainer.Proffer(
139139
WorkspaceProjectFactoryServiceDescriptor.ServiceDescriptor,
140140
(_, _, _, _) => ValueTaskFactory.FromResult<object?>(new WorkspaceProjectFactoryService(this.ComponentModel.GetService<IWorkspaceProjectContextFactory>())));
141141

@@ -172,7 +172,7 @@ protected override async Task LoadComponentsAsync(CancellationToken cancellation
172172

173173
// we need to load it as early as possible since we can have errors from
174174
// package from each language very early
175-
await this.ComponentModel.GetService<VisualStudioSuppressionFixService>().InitializeAsync(this).ConfigureAwait(false);
175+
await this.ComponentModel.GetService<VisualStudioSuppressionFixService>().InitializeAsync(this, cancellationToken).ConfigureAwait(false);
176176
await this.ComponentModel.GetService<VisualStudioDiagnosticListSuppressionStateService>().InitializeAsync(this, cancellationToken).ConfigureAwait(false);
177177

178178
await this.ComponentModel.GetService<IVisualStudioDiagnosticAnalyzerService>().InitializeAsync(this, cancellationToken).ConfigureAwait(false);

src/VisualStudio/Core/Def/SyncNamespaces/SyncNamespacesCommandHandler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public async Task InitializeAsync(IAsyncServiceProvider serviceProvider, Cancell
5252
_serviceProvider = (IServiceProvider)serviceProvider;
5353

5454
// Hook up the "Remove Unused References" menu command for CPS based managed projects.
55-
var menuCommandService = await serviceProvider.GetServiceAsync<IMenuCommandService, IMenuCommandService>(_threadingContext.JoinableTaskFactory, throwOnFailure: false).ConfigureAwait(false);
55+
var menuCommandService = await serviceProvider.GetServiceAsync<IMenuCommandService, IMenuCommandService>(throwOnFailure: false, cancellationToken).ConfigureAwait(false);
5656
if (menuCommandService != null)
5757
{
5858
await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);

src/VisualStudio/Core/Def/TableDataSource/Suppression/VisualStudioDiagnosticListSuppressionStateService.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@ public VisualStudioDiagnosticListSuppressionStateService(
5858

5959
public async Task InitializeAsync(IAsyncServiceProvider serviceProvider, CancellationToken cancellationToken)
6060
{
61-
_shellService = await serviceProvider.GetServiceAsync<SVsUIShell, IVsUIShell>(_threadingContext.JoinableTaskFactory).ConfigureAwait(false);
62-
var errorList = await serviceProvider.GetServiceAsync<SVsErrorList, IErrorList>(_threadingContext.JoinableTaskFactory, throwOnFailure: false).ConfigureAwait(false);
61+
_shellService = await serviceProvider.GetServiceAsync<SVsUIShell, IVsUIShell>(throwOnFailure: false, cancellationToken).ConfigureAwait(false);
62+
var errorList = await serviceProvider.GetServiceAsync<SVsErrorList, IErrorList>(throwOnFailure: false, cancellationToken).ConfigureAwait(false);
6363
_tableControl = errorList?.TableControl;
6464

6565
await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);

0 commit comments

Comments
 (0)