File: Diagnostics\VisualStudioDiagnosticAnalyzerProvider.WorkspaceEventListener.cs
Web Access
Project: src\src\VisualStudio\Core\Def\Microsoft.VisualStudio.LanguageServices_pxr0p0dn_wpftmp.csproj (Microsoft.VisualStudio.LanguageServices)
// 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.Composition;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.ErrorReporting;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Roslyn.Utilities;
 
namespace Microsoft.VisualStudio.LanguageServices.Implementation.Diagnostics;
 
internal partial class VisualStudioDiagnosticAnalyzerProvider
{
    /// <summary>
    /// Loads VSIX analyzers into workspaces that provide <see cref="ISolutionAnalyzerSetterWorkspaceService"/> when they are loaded.
    /// </summary>
    [Export]
    [ExportEventListener(WellKnownEventListeners.Workspace, WorkspaceKind.Host, WorkspaceKind.Interactive, WorkspaceKind.SemanticSearch), Shared]
    internal sealed class WorkspaceEventListener : IEventListener<object>
    {
        private readonly IAsynchronousOperationListener _listener;
        private readonly IVisualStudioDiagnosticAnalyzerProviderFactory _providerFactory;
 
        [ImportingConstructor]
        [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
        public WorkspaceEventListener(
            IAsynchronousOperationListenerProvider listenerProvider,
            IVisualStudioDiagnosticAnalyzerProviderFactory providerFactory)
        {
            _listener = listenerProvider.GetListener(nameof(Workspace));
            _providerFactory = providerFactory;
        }
 
        public void StartListening(Workspace workspace, object serviceOpt)
        {
            var setter = workspace.Services.GetService<ISolutionAnalyzerSetterWorkspaceService>();
            if (setter != null)
            {
                // fire and forget
                var token = _listener.BeginAsyncOperation(nameof(InitializeWorkspaceAsync));
                _ = Task.Run(() => InitializeWorkspaceAsync(setter)).CompletesAsyncOperation(token);
            }
        }
 
        private async Task InitializeWorkspaceAsync(ISolutionAnalyzerSetterWorkspaceService setter)
        {
            try
            {
                var provider = await _providerFactory.GetOrCreateProviderAsync(CancellationToken.None).ConfigureAwait(false);
 
                var references = provider.GetAnalyzerReferencesInExtensions();
                LogWorkspaceAnalyzerCount(references.Length);
                setter.SetAnalyzerReferences(references.SelectAsArray(referenceAndId => (AnalyzerReference)referenceAndId.reference));
            }
            catch (Exception e) when (FatalError.ReportAndPropagate(e, ErrorSeverity.Diagnostic))
            {
                throw ExceptionUtilities.Unreachable();
            }
        }
 
        private static void LogWorkspaceAnalyzerCount(int analyzerCount)
        {
            Logger.Log(FunctionId.DiagnosticAnalyzerService_Analyzers, KeyValueLogMessage.Create(m => m["AnalyzerCount"] = analyzerCount, LogLevel.Debug));
        }
    }
}