Skip to content

Commit b411efa

Browse files
Make IDiagnosticAnalyzerService into an IWorkspaceService (#78359)
Followup to #78356. Needed so we can access IDiagAnalyzerService in OOP. Currently one cannot as it attempts to access the Workspace of a document passed into it. We block WOrkspace access like for safety/clarity concerns (we don't want a stateless OOP api call to have access to the mutable workspace API). This also cleans up some ugly initialization code IDiagAnalyzerService had.
2 parents 02a8b35 + e70ac77 commit b411efa

File tree

50 files changed

+216
-277
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+216
-277
lines changed

src/EditorFeatures/CSharp/CodeCleanup/CSharpCodeCleanupService.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ namespace Microsoft.CodeAnalysis.CSharp.CodeCleanup;
1616
[ExportLanguageService(typeof(ICodeCleanupService), LanguageNames.CSharp), Shared]
1717
[method: ImportingConstructor]
1818
[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
19-
internal sealed class CSharpCodeCleanupService(ICodeFixService codeFixService, IDiagnosticAnalyzerService diagnosticAnalyzerService) : AbstractCodeCleanupService(codeFixService, diagnosticAnalyzerService)
19+
internal sealed class CSharpCodeCleanupService(ICodeFixService codeFixService)
20+
: AbstractCodeCleanupService(codeFixService)
2021
{
2122
/// <summary>
2223
/// Maps format document code cleanup options to DiagnosticId[]

src/EditorFeatures/Core.Wpf/InlineDiagnostics/AbstractDiagnosticsTaggerProvider.SingleDiagnosticKindPullTaggerProvider.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,12 @@ internal abstract partial class AbstractDiagnosticsTaggerProvider<TTag>
3535
/// </summary>
3636
private sealed class SingleDiagnosticKindPullTaggerProvider(
3737
AbstractDiagnosticsTaggerProvider<TTag> callback,
38-
IDiagnosticAnalyzerService analyzerService,
3938
DiagnosticKind diagnosticKind,
4039
TaggerHost taggerHost,
4140
string featureName)
4241
: AsynchronousTaggerProvider<TTag>(taggerHost, featureName)
4342
{
4443
private readonly DiagnosticKind _diagnosticKind = diagnosticKind;
45-
private readonly IDiagnosticAnalyzerService _analyzerService = analyzerService;
4644

4745
// The following three fields are used to help calculate diagnostic performance for syntax errors upon file open.
4846
// During TagsChanged notification for syntax errors, VSPlatform will check the buffer's property bag for a
@@ -104,7 +102,8 @@ private async Task ProduceTagsAsync(
104102
var snapshot = documentSpanToTag.SnapshotSpan.Snapshot;
105103

106104
var project = document.Project;
107-
var workspace = project.Solution.Workspace;
105+
var solution = project.Solution;
106+
var workspace = solution.Workspace;
108107

109108
// See if we've marked any spans as those we want to suppress diagnostics for.
110109
// This can happen for buffers used in the preview workspace where some feature
@@ -124,7 +123,8 @@ private async Task ProduceTagsAsync(
124123
// NOTE: We pass 'includeSuppressedDiagnostics: true' to ensure that IDE0079 (unnecessary suppressions)
125124
// are flagged and faded in the editor. IDE0079 analyzer requires all source suppressed diagnostics to
126125
// be provided to it to function correctly.
127-
var diagnostics = await _analyzerService.GetDiagnosticsForSpanAsync(
126+
var analyzerService = solution.Services.GetRequiredService<IDiagnosticAnalyzerService>();
127+
var diagnostics = await analyzerService.GetDiagnosticsForSpanAsync(
128128
document,
129129
requestedSpan.Span.ToTextSpan(),
130130
diagnosticKind: _diagnosticKind,

src/EditorFeatures/Core.Wpf/InlineDiagnostics/AbstractDiagnosticsTaggerProvider.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ internal abstract partial class AbstractDiagnosticsTaggerProvider<TTag> : ITagge
3131
private readonly ImmutableArray<SingleDiagnosticKindPullTaggerProvider> _diagnosticsTaggerProviders;
3232

3333
public AbstractDiagnosticsTaggerProvider(
34-
IDiagnosticAnalyzerService analyzerService,
3534
TaggerHost taggerHost,
3635
string featureName)
3736
{
@@ -48,7 +47,7 @@ public AbstractDiagnosticsTaggerProvider(
4847
return;
4948

5049
SingleDiagnosticKindPullTaggerProvider CreateDiagnosticsTaggerProvider(DiagnosticKind diagnosticKind)
51-
=> new(this, analyzerService, diagnosticKind, taggerHost, featureName);
50+
=> new(this, diagnosticKind, taggerHost, featureName);
5251
}
5352

5453
// Functionality for subclasses to control how this diagnostic tagging operates. All the individual

src/EditorFeatures/Core.Wpf/InlineDiagnostics/InlineDiagnosticsTaggerProvider.cs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,12 @@ namespace Microsoft.CodeAnalysis.Editor.InlineDiagnostics;
2525
[method: ImportingConstructor]
2626
[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
2727
internal sealed class InlineDiagnosticsTaggerProvider(
28-
IDiagnosticAnalyzerService analyzerService,
2928
TaggerHost taggerHost,
3029
IEditorFormatMapService editorFormatMapService,
3130
IClassificationFormatMapService classificationFormatMapService,
3231
IClassificationTypeRegistryService classificationTypeRegistryService)
3332
: AbstractDiagnosticsTaggerProvider<InlineDiagnosticsTag>(
34-
analyzerService,
35-
taggerHost,
36-
FeatureAttribute.ErrorSquiggles)
33+
taggerHost, FeatureAttribute.ErrorSquiggles)
3734
{
3835
private readonly IEditorFormatMap _editorFormatMap = editorFormatMapService.GetEditorFormatMap("text");
3936
private readonly IClassificationFormatMapService _classificationFormatMapService = classificationFormatMapService;

src/EditorFeatures/Core/EditorConfigSettings/DataProvider/Analyzer/AnalyzerSettingsProvider.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,10 @@ public AnalyzerSettingsProvider(
2424
string fileName,
2525
AnalyzerSettingsUpdater settingsUpdater,
2626
Workspace workspace,
27-
IDiagnosticAnalyzerService analyzerService,
2827
IGlobalOptionService optionService)
2928
: base(fileName, settingsUpdater, workspace, optionService)
3029
{
31-
_analyzerService = analyzerService;
30+
_analyzerService = workspace.Services.GetRequiredService<IDiagnosticAnalyzerService>();
3231
Update();
3332
}
3433

src/EditorFeatures/Core/EditorConfigSettings/DataProvider/Analyzer/AnalyzerSettingsProviderFactory.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,11 @@ namespace Microsoft.CodeAnalysis.Editor.EditorConfigSettings.DataProvider.Analyz
1111

1212
internal sealed class AnalyzerSettingsProviderFactory(
1313
Workspace workspace,
14-
IDiagnosticAnalyzerService analyzerService,
1514
IGlobalOptionService globalOptionService) : IWorkspaceSettingsProviderFactory<AnalyzerSetting>
1615
{
1716
public ISettingsProvider<AnalyzerSetting> GetForFile(string filePath)
1817
{
1918
var updater = new AnalyzerSettingsUpdater(workspace, filePath);
20-
return new AnalyzerSettingsProvider(filePath, updater, workspace, analyzerService, globalOptionService);
19+
return new AnalyzerSettingsProvider(filePath, updater, workspace, globalOptionService);
2120
}
2221
}

src/EditorFeatures/Core/EditorConfigSettings/DataProvider/Analyzer/AnalyzerSettingsWorkspaceServiceFactory.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,8 @@ namespace Microsoft.CodeAnalysis.Editor.EditorConfigSettings.DataProvider.Analyz
1616
[method: ImportingConstructor]
1717
[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
1818
internal sealed class AnalyzerSettingsWorkspaceServiceFactory(
19-
IDiagnosticAnalyzerService analyzerService,
2019
IGlobalOptionService globalOptionService) : IWorkspaceServiceFactory
2120
{
2221
public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices)
23-
=> new AnalyzerSettingsProviderFactory(workspaceServices.Workspace, analyzerService, globalOptionService);
22+
=> new AnalyzerSettingsProviderFactory(workspaceServices.Workspace, globalOptionService);
2423
}

src/EditorFeatures/Core/RenameTracking/RenameTrackingTaggerProvider.StateMachine.cs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ private sealed class StateMachine
3838

3939
private readonly IInlineRenameService _inlineRenameService;
4040
private readonly IAsynchronousOperationListener _asyncListener;
41-
private readonly IDiagnosticAnalyzerService _diagnosticAnalyzerService;
4241

4342
// Store committed sessions so they can be restored on undo/redo. The undo transactions
4443
// may live beyond the lifetime of the buffer tracked by this StateMachine, so storing
@@ -58,7 +57,6 @@ public StateMachine(
5857
IThreadingContext threadingContext,
5958
ITextBuffer buffer,
6059
IInlineRenameService inlineRenameService,
61-
IDiagnosticAnalyzerService diagnosticAnalyzerService,
6260
IGlobalOptionService globalOptions,
6361
IAsynchronousOperationListener asyncListener)
6462
{
@@ -67,7 +65,6 @@ public StateMachine(
6765
Buffer.Changed += Buffer_Changed;
6866
_inlineRenameService = inlineRenameService;
6967
_asyncListener = asyncListener;
70-
_diagnosticAnalyzerService = diagnosticAnalyzerService;
7168
GlobalOptions = globalOptions;
7269
}
7370

@@ -238,8 +235,8 @@ public bool ClearVisibleTrackingSession()
238235
// provide a diagnostic/codefix, but nothing has changed in the workspace
239236
// to trigger the diagnostic system to reanalyze, so we trigger it
240237
// manually.
241-
242-
_diagnosticAnalyzerService?.RequestDiagnosticRefresh();
238+
var service = document.Project.Solution.Services.GetRequiredService<IDiagnosticAnalyzerService>();
239+
service.RequestDiagnosticRefresh();
243240
}
244241

245242
// Disallow the existing TrackingSession from triggering IdentifierFound.

src/EditorFeatures/Core/RenameTracking/RenameTrackingTaggerProvider.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,19 +40,17 @@ namespace Microsoft.CodeAnalysis.Editor.Implementation.RenameTracking;
4040
internal sealed partial class RenameTrackingTaggerProvider(
4141
IThreadingContext threadingContext,
4242
IInlineRenameService inlineRenameService,
43-
IDiagnosticAnalyzerService diagnosticAnalyzerService,
4443
IGlobalOptionService globalOptions,
4544
IAsynchronousOperationListenerProvider listenerProvider) : ITaggerProvider
4645
{
4746
private readonly IThreadingContext _threadingContext = threadingContext;
4847
private readonly IAsynchronousOperationListener _asyncListener = listenerProvider.GetListener(FeatureAttribute.RenameTracking);
4948
private readonly IInlineRenameService _inlineRenameService = inlineRenameService;
50-
private readonly IDiagnosticAnalyzerService _diagnosticAnalyzerService = diagnosticAnalyzerService;
5149
private readonly IGlobalOptionService _globalOptions = globalOptions;
5250

5351
public ITagger<T> CreateTagger<T>(ITextBuffer buffer) where T : ITag
5452
{
55-
var stateMachine = buffer.Properties.GetOrCreateSingletonProperty(() => new StateMachine(_threadingContext, buffer, _inlineRenameService, _diagnosticAnalyzerService, _globalOptions, _asyncListener));
53+
var stateMachine = buffer.Properties.GetOrCreateSingletonProperty(() => new StateMachine(_threadingContext, buffer, _inlineRenameService, _globalOptions, _asyncListener));
5654
return new Tagger(stateMachine) as ITagger<T>;
5755
}
5856

src/EditorFeatures/Test/CodeFixes/CodeFixServiceTests.cs

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,14 @@ public async Task TestGetFirstDiagnosticWithFixAsync()
4343
";
4444
using var workspace = TestWorkspace.CreateCSharp(code, composition: s_compositionWithMockDiagnosticUpdateSourceRegistrationService, openDocuments: true);
4545

46-
var diagnosticService = workspace.GetService<IDiagnosticAnalyzerService>();
46+
var diagnosticService = workspace.Services.GetRequiredService<IDiagnosticAnalyzerService>();
4747

4848
var analyzerReference = new TestAnalyzerReferenceByLanguage(DiagnosticExtensions.GetCompilerDiagnosticAnalyzersMap());
4949
workspace.TryApplyChanges(workspace.CurrentSolution.WithAnalyzerReferences([analyzerReference]));
5050

5151
var logger = SpecializedCollections.SingletonEnumerable(new Lazy<IErrorLoggerService>(() => workspace.Services.GetRequiredService<IErrorLoggerService>()));
5252
var fixService = new CodeFixService(
53-
diagnosticService, logger, fixers, configurationProviders: []);
53+
logger, fixers, configurationProviders: []);
5454

5555
var reference = new MockAnalyzerReference();
5656
var project = workspace.CurrentSolution.Projects.Single().AddAnalyzerReference(reference);
@@ -323,15 +323,15 @@ private static async Task GetFirstDiagnosticWithFixWithExceptionValidationAsync(
323323
Assert.True(errorReported);
324324
}
325325

326-
private static (EditorTestWorkspace workspace, IDiagnosticAnalyzerService analyzerService, CodeFixService codeFixService, IErrorLoggerService errorLogger) ServiceSetup(
326+
private static (EditorTestWorkspace workspace, CodeFixService codeFixService, IErrorLoggerService errorLogger) ServiceSetup(
327327
CodeFixProvider codefix,
328328
bool includeConfigurationFixProviders = false,
329329
bool throwExceptionInFixerCreation = false,
330330
EditorTestHostDocument? additionalDocument = null,
331331
string code = "class Program { }")
332332
=> ServiceSetup([codefix], includeConfigurationFixProviders, throwExceptionInFixerCreation, additionalDocument, code);
333333

334-
private static (EditorTestWorkspace workspace, IDiagnosticAnalyzerService analyzerService, CodeFixService codeFixService, IErrorLoggerService errorLogger) ServiceSetup(
334+
private static (EditorTestWorkspace workspace, CodeFixService codeFixService, IErrorLoggerService errorLogger) ServiceSetup(
335335
ImmutableArray<CodeFixProvider> codefixers,
336336
bool includeConfigurationFixProviders = false,
337337
bool throwExceptionInFixerCreation = false,
@@ -355,21 +355,16 @@ private static (EditorTestWorkspace workspace, IDiagnosticAnalyzerService analyz
355355
var analyzerReference = new TestAnalyzerReferenceByLanguage(DiagnosticExtensions.GetCompilerDiagnosticAnalyzersMap());
356356
workspace.TryApplyChanges(workspace.CurrentSolution.WithAnalyzerReferences([analyzerReference]));
357357

358-
var diagnosticService = workspace.GetService<IDiagnosticAnalyzerService>();
358+
var diagnosticService = workspace.Services.GetRequiredService<IDiagnosticAnalyzerService>();
359359
var logger = SpecializedCollections.SingletonEnumerable(new Lazy<IErrorLoggerService>(() => new TestErrorLogger()));
360360
var errorLogger = logger.First().Value;
361361

362362
var configurationFixProviders = includeConfigurationFixProviders
363363
? workspace.ExportProvider.GetExports<IConfigurationFixProvider, CodeChangeProviderMetadata>()
364364
: [];
365365

366-
var fixService = new CodeFixService(
367-
diagnosticService,
368-
logger,
369-
fixers,
370-
configurationFixProviders);
371-
372-
return (workspace, diagnosticService, fixService, errorLogger);
366+
var fixService = new CodeFixService(logger, fixers, configurationFixProviders);
367+
return (workspace, fixService, errorLogger);
373368
}
374369

375370
private static void GetDocumentAndExtensionManager(
@@ -757,11 +752,10 @@ private static async Task<ImmutableArray<CodeFixCollection>> GetNuGetAndVsixCode
757752

758753
using var workspace = TestWorkspace.CreateCSharp(code, composition: s_compositionWithMockDiagnosticUpdateSourceRegistrationService, openDocuments: true);
759754

760-
var diagnosticService = workspace.GetService<IDiagnosticAnalyzerService>();
755+
var diagnosticService = workspace.Services.GetRequiredService<IDiagnosticAnalyzerService>();
761756

762757
var logger = SpecializedCollections.SingletonEnumerable(new Lazy<IErrorLoggerService>(() => workspace.Services.GetRequiredService<IErrorLoggerService>()));
763-
var fixService = new CodeFixService(
764-
diagnosticService, logger, vsixFixers, configurationProviders: []);
758+
var fixService = new CodeFixService(logger, vsixFixers, configurationProviders: []);
765759

766760
diagnosticAnalyzer ??= new MockAnalyzerReference.MockDiagnosticAnalyzer();
767761
var analyzers = ImmutableArray.Create<DiagnosticAnalyzer>(diagnosticAnalyzer);
@@ -1033,7 +1027,6 @@ void M()
10331027

10341028
var tuple = ServiceSetup(codeFix, code: code);
10351029
using var workspace = tuple.workspace;
1036-
var analyzerService = tuple.analyzerService;
10371030
GetDocumentAndExtensionManager(workspace, out var document,
10381031
out var extensionManager, analyzerReference);
10391032

@@ -1047,6 +1040,7 @@ void M()
10471040
// We enable full solution analysis so the 'AnalyzeDocumentAsync' doesn't skip analysis based on whether the document is active/open.
10481041
workspace.GlobalOptions.SetGlobalOption(SolutionCrawlerOptionsStorage.BackgroundAnalysisScopeOption, LanguageNames.CSharp, BackgroundAnalysisScope.FullSolution);
10491042

1043+
var analyzerService = workspace.Services.GetRequiredService<IDiagnosticAnalyzerService>();
10501044
var diagnostics = await analyzerService.ForceAnalyzeProjectAsync(sourceDocument.Project, CancellationToken.None);
10511045
await VerifyCachedDiagnosticsAsync(
10521046
sourceDocument, expectedCachedDiagnostic: diagnosticOnFixLineInPriorSnapshot, testSpan, diagnostics);

0 commit comments

Comments
 (0)