2020using Microsoft . CodeAnalysis . Host . Mef ;
2121using Microsoft . CodeAnalysis . Options ;
2222using Microsoft . CodeAnalysis . Progress ;
23- using Microsoft . CodeAnalysis . Shared . Extensions ;
2423using Microsoft . CodeAnalysis . Shared . TestHooks ;
2524using Microsoft . VisualStudio . LanguageServices . Implementation . ProjectSystem ;
2625using Microsoft . VisualStudio . LanguageServices . Implementation . TableDataSource ;
@@ -40,54 +39,33 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation.Suppression;
4039/// </summary>
4140[ Export ( typeof ( IVisualStudioSuppressionFixService ) ) ]
4241[ Export ( typeof ( VisualStudioSuppressionFixService ) ) ]
43- internal sealed class VisualStudioSuppressionFixService : IVisualStudioSuppressionFixService
42+ [ method: ImportingConstructor ]
43+ [ method: Obsolete ( MefConstruction . ImportingConstructorMessage , error : true ) ]
44+ internal sealed class VisualStudioSuppressionFixService (
45+ IThreadingContext threadingContext ,
46+ VisualStudioWorkspaceImpl workspace ,
47+ IDiagnosticAnalyzerService diagnosticService ,
48+ ICodeFixService codeFixService ,
49+ ICodeActionEditHandlerService editHandlerService ,
50+ VisualStudioDiagnosticListSuppressionStateService suppressionStateService ,
51+ IUIThreadOperationExecutor uiThreadOperationExecutor ,
52+ IVsHierarchyItemManager vsHierarchyItemManager ,
53+ IAsynchronousOperationListenerProvider listenerProvider ) : IVisualStudioSuppressionFixService
4454{
45- private readonly IThreadingContext _threadingContext ;
46- private readonly VisualStudioWorkspaceImpl _workspace ;
47- private readonly IAsynchronousOperationListener _listener ;
48- private readonly IDiagnosticAnalyzerService _diagnosticService ;
49- private readonly ExternalErrorDiagnosticUpdateSource _buildErrorDiagnosticService ;
50- private readonly ICodeFixService _codeFixService ;
51- private readonly IFixMultipleOccurrencesService _fixMultipleOccurencesService ;
52- private readonly ICodeActionEditHandlerService _editHandlerService ;
53- private readonly VisualStudioDiagnosticListSuppressionStateService _suppressionStateService ;
54- private readonly IUIThreadOperationExecutor _uiThreadOperationExecutor ;
55- private readonly IVsHierarchyItemManager _vsHierarchyItemManager ;
56- private readonly IHierarchyItemToProjectIdMap _projectMap ;
57- private readonly IGlobalOptionService _globalOptions ;
55+ private readonly IThreadingContext _threadingContext = threadingContext ;
56+ private readonly VisualStudioWorkspaceImpl _workspace = workspace ;
57+ private readonly IAsynchronousOperationListener _listener = listenerProvider . GetListener ( FeatureAttribute . ErrorList ) ;
58+ private readonly IDiagnosticAnalyzerService _diagnosticService = diagnosticService ;
59+ private readonly ICodeFixService _codeFixService = codeFixService ;
60+ private readonly IFixMultipleOccurrencesService _fixMultipleOccurencesService = workspace . Services . GetRequiredService < IFixMultipleOccurrencesService > ( ) ;
61+ private readonly ICodeActionEditHandlerService _editHandlerService = editHandlerService ;
62+ private readonly VisualStudioDiagnosticListSuppressionStateService _suppressionStateService = suppressionStateService ;
63+ private readonly IUIThreadOperationExecutor _uiThreadOperationExecutor = uiThreadOperationExecutor ;
64+ private readonly IVsHierarchyItemManager _vsHierarchyItemManager = vsHierarchyItemManager ;
65+ private readonly IHierarchyItemToProjectIdMap _projectMap = workspace . Services . GetRequiredService < IHierarchyItemToProjectIdMap > ( ) ;
5866
5967 private IWpfTableControl ? _tableControl ;
6068
61- [ ImportingConstructor ]
62- [ Obsolete ( MefConstruction . ImportingConstructorMessage , error : true ) ]
63- public VisualStudioSuppressionFixService (
64- IThreadingContext threadingContext ,
65- SVsServiceProvider serviceProvider ,
66- VisualStudioWorkspaceImpl workspace ,
67- IDiagnosticAnalyzerService diagnosticService ,
68- ICodeFixService codeFixService ,
69- ICodeActionEditHandlerService editHandlerService ,
70- VisualStudioDiagnosticListSuppressionStateService suppressionStateService ,
71- IUIThreadOperationExecutor uiThreadOperationExecutor ,
72- IVsHierarchyItemManager vsHierarchyItemManager ,
73- IAsynchronousOperationListenerProvider listenerProvider ,
74- IGlobalOptionService globalOptions )
75- {
76- _threadingContext = threadingContext ;
77- _workspace = workspace ;
78- _diagnosticService = diagnosticService ;
79- _buildErrorDiagnosticService = workspace . ExternalErrorDiagnosticUpdateSource ;
80- _codeFixService = codeFixService ;
81- _suppressionStateService = suppressionStateService ;
82- _editHandlerService = editHandlerService ;
83- _uiThreadOperationExecutor = uiThreadOperationExecutor ;
84- _vsHierarchyItemManager = vsHierarchyItemManager ;
85- _fixMultipleOccurencesService = workspace . Services . GetRequiredService < IFixMultipleOccurrencesService > ( ) ;
86- _projectMap = workspace . Services . GetRequiredService < IHierarchyItemToProjectIdMap > ( ) ;
87- _listener = listenerProvider . GetListener ( FeatureAttribute . ErrorList ) ;
88- _globalOptions = globalOptions ;
89- }
90-
9169 public async Task InitializeAsync ( IAsyncServiceProvider serviceProvider )
9270 {
9371 var errorList = await serviceProvider . GetServiceAsync < SVsErrorList , IErrorList > ( _threadingContext . JoinableTaskFactory , throwOnFailure : false ) . ConfigureAwait ( false ) ;
@@ -96,44 +74,57 @@ public async Task InitializeAsync(IAsyncServiceProvider serviceProvider)
9674
9775 public bool AddSuppressions ( IVsHierarchy ? projectHierarchy )
9876 {
99- if ( _tableControl == null )
77+ return _threadingContext . JoinableTaskFactory . Run ( async ( ) =>
10078 {
101- return false ;
102- }
79+ if ( _tableControl == null )
80+ return false ;
10381
104- var shouldFixInProject = GetShouldFixInProjectDelegate ( _vsHierarchyItemManager , _projectMap , projectHierarchy ) ;
82+ var shouldFixInProject = GetShouldFixInProjectDelegate ( _vsHierarchyItemManager , _projectMap , projectHierarchy ) ;
10583
106- // Apply suppressions fix in global suppressions file for non-compiler diagnostics and
107- // in source only for compiler diagnostics.
108- var diagnosticsToFix = GetDiagnosticsToFix ( selectedEntriesOnly : false , isAddSuppression : true ) ;
109- if ( ! ApplySuppressionFix ( diagnosticsToFix , shouldFixInProject , filterStaleDiagnostics : false , isAddSuppression : true , isSuppressionInSource : false , onlyCompilerDiagnostics : false , showPreviewChangesDialog : false ) )
110- {
111- return false ;
112- }
84+ // Apply suppressions fix in global suppressions file for non-compiler diagnostics and
85+ // in source only for compiler diagnostics.
86+ var diagnosticsToFix = await GetDiagnosticsToFixAsync ( selectedEntriesOnly : false , isAddSuppression : true ) . ConfigureAwait ( true ) ;
87+ if ( ! ApplySuppressionFix ( diagnosticsToFix , shouldFixInProject , filterStaleDiagnostics : false , isAddSuppression : true , isSuppressionInSource : false , onlyCompilerDiagnostics : false , showPreviewChangesDialog : false ) )
88+ return false ;
11389
114- return ApplySuppressionFix ( diagnosticsToFix , shouldFixInProject , filterStaleDiagnostics : false , isAddSuppression : true , isSuppressionInSource : true , onlyCompilerDiagnostics : true , showPreviewChangesDialog : false ) ;
90+ return ApplySuppressionFix ( diagnosticsToFix , shouldFixInProject , filterStaleDiagnostics : false , isAddSuppression : true , isSuppressionInSource : true , onlyCompilerDiagnostics : true , showPreviewChangesDialog : false ) ;
91+ } ) ;
11592 }
11693
11794 public bool AddSuppressions ( bool selectedErrorListEntriesOnly , bool suppressInSource , IVsHierarchy ? projectHierarchy )
11895 {
119- if ( _tableControl == null )
96+ return _threadingContext . JoinableTaskFactory . Run ( async ( ) =>
12097 {
121- return false ;
122- }
123-
124- var shouldFixInProject = GetShouldFixInProjectDelegate ( _vsHierarchyItemManager , _projectMap , projectHierarchy ) ;
125- return ApplySuppressionFix ( shouldFixInProject , selectedErrorListEntriesOnly , isAddSuppression : true , isSuppressionInSource : suppressInSource , onlyCompilerDiagnostics : false , showPreviewChangesDialog : true ) ;
98+ if ( _tableControl == null )
99+ return false ;
100+
101+ var shouldFixInProject = GetShouldFixInProjectDelegate ( _vsHierarchyItemManager , _projectMap , projectHierarchy ) ;
102+ return await ApplySuppressionFixAsync (
103+ shouldFixInProject ,
104+ selectedErrorListEntriesOnly ,
105+ isAddSuppression : true ,
106+ isSuppressionInSource : suppressInSource ,
107+ onlyCompilerDiagnostics : false ,
108+ showPreviewChangesDialog : true ) . ConfigureAwait ( true ) ;
109+ } ) ;
126110 }
127111
128112 public bool RemoveSuppressions ( bool selectedErrorListEntriesOnly , IVsHierarchy ? projectHierarchy )
129113 {
130- if ( _tableControl == null )
114+ return _threadingContext . JoinableTaskFactory . Run ( async ( ) =>
131115 {
132- return false ;
133- }
134-
135- var shouldFixInProject = GetShouldFixInProjectDelegate ( _vsHierarchyItemManager , _projectMap , projectHierarchy ) ;
136- return ApplySuppressionFix ( shouldFixInProject , selectedErrorListEntriesOnly , isAddSuppression : false , isSuppressionInSource : false , onlyCompilerDiagnostics : false , showPreviewChangesDialog : true ) ;
116+ if ( _tableControl == null )
117+ return false ;
118+
119+ var shouldFixInProject = GetShouldFixInProjectDelegate ( _vsHierarchyItemManager , _projectMap , projectHierarchy ) ;
120+ return await ApplySuppressionFixAsync (
121+ shouldFixInProject ,
122+ selectedErrorListEntriesOnly ,
123+ isAddSuppression : false ,
124+ isSuppressionInSource : false ,
125+ onlyCompilerDiagnostics : false ,
126+ showPreviewChangesDialog : true ) . ConfigureAwait ( true ) ;
127+ } ) ;
137128 }
138129
139130 private static Func < Project , bool > GetShouldFixInProjectDelegate ( IVsHierarchyItemManager vsHierarchyItemManager , IHierarchyItemToProjectIdMap projectMap , IVsHierarchy ? projectHierarchy )
@@ -157,38 +148,38 @@ private static string GetFixTitle(bool isAddSuppression)
157148 private static string GetWaitDialogMessage ( bool isAddSuppression )
158149 => isAddSuppression ? ServicesVSResources . Computing_suppressions_fix : ServicesVSResources . Computing_remove_suppressions_fix ;
159150
160- private IEnumerable < DiagnosticData > ? GetDiagnosticsToFix ( bool selectedEntriesOnly , bool isAddSuppression )
151+ private async Task < ImmutableHashSet < DiagnosticData > ? > GetDiagnosticsToFixAsync (
152+ bool selectedEntriesOnly ,
153+ bool isAddSuppression )
161154 {
162155 var diagnosticsToFix = ImmutableHashSet < DiagnosticData > . Empty ;
163- void computeDiagnosticsToFix ( IUIThreadOperationContext context )
164- {
165- var cancellationToken = context . UserCancellationToken ;
166156
167- // If we are fixing selected diagnostics in error list, then get the diagnostics from error list entry
157+ var result = await InvokeWithWaitDialogAsync ( async cancellationToken =>
158+ { // If we are fixing selected diagnostics in error list, then get the diagnostics from error list entry
168159 // snapshots. Otherwise, get all diagnostics from the diagnostic service.
169- var diagnosticsToFixTask = selectedEntriesOnly
170- ? _suppressionStateService . GetSelectedItemsAsync ( isAddSuppression , cancellationToken )
171- : Task . FromResult < ImmutableArray < DiagnosticData > > ( [ ] ) ;
160+ var diagnosticsToFixArray = selectedEntriesOnly
161+ ? await _suppressionStateService . GetSelectedItemsAsync ( isAddSuppression , cancellationToken ) . ConfigureAwait ( true )
162+ : [ ] ;
172163
173- diagnosticsToFix = diagnosticsToFixTask . WaitAndGetResult ( cancellationToken ) . ToImmutableHashSet ( ) ;
174- }
164+ diagnosticsToFix = diagnosticsToFixArray . ToImmutableHashSet ( ) ;
175165
176- var title = GetFixTitle ( isAddSuppression ) ;
177- var waitDialogMessage = GetWaitDialogMessage ( isAddSuppression ) ;
178- var result = InvokeWithWaitDialog ( computeDiagnosticsToFix , title , waitDialogMessage ) ;
166+ } , GetFixTitle ( isAddSuppression ) , GetWaitDialogMessage ( isAddSuppression ) ) . ConfigureAwait ( true ) ;
179167
180- // Bail out if the user cancelled.
181168 if ( result == UIThreadOperationStatus . Canceled )
182- {
183169 return null ;
184- }
185170
186171 return diagnosticsToFix ;
187172 }
188173
189- private bool ApplySuppressionFix ( Func < Project , bool > shouldFixInProject , bool selectedEntriesOnly , bool isAddSuppression , bool isSuppressionInSource , bool onlyCompilerDiagnostics , bool showPreviewChangesDialog )
174+ private async Task < bool > ApplySuppressionFixAsync (
175+ Func < Project , bool > shouldFixInProject ,
176+ bool selectedEntriesOnly ,
177+ bool isAddSuppression ,
178+ bool isSuppressionInSource ,
179+ bool onlyCompilerDiagnostics ,
180+ bool showPreviewChangesDialog )
190181 {
191- var diagnosticsToFix = GetDiagnosticsToFix ( selectedEntriesOnly , isAddSuppression ) ;
182+ var diagnosticsToFix = await GetDiagnosticsToFixAsync ( selectedEntriesOnly , isAddSuppression ) . ConfigureAwait ( true ) ;
192183 return ApplySuppressionFix ( diagnosticsToFix , shouldFixInProject , selectedEntriesOnly , isAddSuppression , isSuppressionInSource , onlyCompilerDiagnostics , showPreviewChangesDialog ) ;
193184 }
194185
@@ -395,28 +386,22 @@ private static IEnumerable<DiagnosticData> FilterDiagnostics(IEnumerable<Diagnos
395386 }
396387 }
397388
398- private UIThreadOperationStatus InvokeWithWaitDialog (
399- Action < IUIThreadOperationContext > action , string waitDialogTitle , string waitDialogMessage )
389+ private async Task < UIThreadOperationStatus > InvokeWithWaitDialogAsync (
390+ Func < CancellationToken , Task > action , string waitDialogTitle , string waitDialogMessage )
400391 {
392+ using var waitContext = _uiThreadOperationExecutor . BeginExecute ( waitDialogTitle , waitDialogMessage , allowCancellation : true , showProgress : true ) ;
393+
401394 var cancelled = false ;
402- var result = _uiThreadOperationExecutor . Execute (
403- waitDialogTitle ,
404- waitDialogMessage ,
405- allowCancellation : true ,
406- showProgress : true ,
407- action : waitContext =>
408- {
409- try
410- {
411- action ( waitContext ) ;
412- }
413- catch ( OperationCanceledException )
414- {
415- cancelled = true ;
416- }
417- } ) ;
395+ try
396+ {
397+ await action ( waitContext . UserCancellationToken ) . ConfigureAwait ( true ) ;
398+ }
399+ catch ( OperationCanceledException )
400+ {
401+ cancelled = true ;
402+ }
418403
419- return cancelled ? UIThreadOperationStatus . Canceled : result ;
404+ return cancelled ? UIThreadOperationStatus . Canceled : UIThreadOperationStatus . Completed ;
420405 }
421406
422407 private static ImmutableDictionary < Document , ImmutableArray < Diagnostic > > GetDocumentDiagnosticsMappedToNewSolution ( ImmutableDictionary < Document , ImmutableArray < Diagnostic > > documentDiagnosticsToFixMap , Solution newSolution , string language )
0 commit comments