Repository: dotnet/roslyn
File: src/VisualStudio/Core/Def/ProjectSystem/SdkAnalyzerAssemblyRedirector.cs (C#)

Code before:
// ProductVersion: "8.0.8"
// PathSuffix: "analyzers\dotnet"
using AnalyzerInfo = (string FullPath, string ProductVersion, string PathSuffix);

namespace Microsoft.VisualStudio.LanguageServices.ProjectSystem;

/// <summary>
/// See <see href="https://github.com/dotnet/sdk/blob/main/documentation/general/analyzer-redirecting.md"/>.
/// </summary>
[Export(typeof(IAnalyzerAssemblyRedirector))]
[method: ImportingConstructor]
[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
internal sealed class SdkAnalyzerAssemblyRedirector(SVsServiceProvider serviceProvider) : SdkAnalyzerAssemblyRedirectorCore(
    Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"CommonExtensions\Microsoft\DotNet")),
    (IVsActivityLog)serviceProvider.GetService(typeof(SVsActivityLog)));

/// <summary>
/// Core functionality of <see cref="SdkAnalyzerAssemblyRedirector"/> extracted for testing.
/// </summary>
internal class SdkAnalyzerAssemblyRedirectorCore : IAnalyzerAssemblyRedirector
{
    private readonly IVsActivityLog? _log;

    private readonly bool _enabled;

    private readonly string? _insertedAnalyzersDirectory;

    /// <summary>
    /// Map from analyzer assembly name (file name without extension) to a list of matching analyzers.
    /// </summary>
    private readonly ImmutableDictionary<string, List<AnalyzerInfo>> _analyzerMap;

    public SdkAnalyzerAssemblyRedirectorCore(string? insertedAnalyzersDirectory, IVsActivityLog? log = null)
    {
        _log = log;
        var enable = Environment.GetEnvironmentVariable("DOTNET_ANALYZER_REDIRECTING");
        _enabled = !"0".Equals(enable, StringComparison.OrdinalIgnoreCase) && !"false".Equals(enable, StringComparison.OrdinalIgnoreCase);
        _insertedAnalyzersDirectory = insertedAnalyzersDirectory;
        _analyzerMap = CreateAnalyzerMap();
    }

    private ImmutableDictionary<string, List<AnalyzerInfo>> CreateAnalyzerMap()
    {
        if (!_enabled)
        {
            Log("Analyzer redirecting is disabled.");
            return ImmutableDictionary<string, List<AnalyzerInfo>>.Empty;
        }

        var metadataFilePath = Path.Combine(_insertedAnalyzersDirectory, "metadata.json");
        if (!File.Exists(metadataFilePath))

Review comment (suggestion):
Consider just passing these to CreateAnalyzerMap because then you can get rid of them. _enabled isn't really needed either since the map can just be empty and the rest of the code would work fine.

Code after:
// ProductVersion: "8.0.8"
// PathSuffix: "analyzers\dotnet"
using AnalyzerInfo = (string FullPath, string ProductVersion, string PathSuffix);

namespace Microsoft.VisualStudio.LanguageServices.ProjectSystem;

/// <summary>
/// See <see href="https://github.com/dotnet/sdk/blob/main/documentation/general/analyzer-redirecting.md"/>.
/// </summary>
[Export(typeof(IAnalyzerAssemblyRedirector))]
[method: ImportingConstructor]
[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
internal sealed class SdkAnalyzerAssemblyRedirector(SVsServiceProvider serviceProvider) : SdkAnalyzerAssemblyRedirectorCore(
    GetInsertedAnalyzersDirectory(),
    (IVsActivityLog)serviceProvider.GetService(typeof(SVsActivityLog)))
{
    private static string? GetInsertedAnalyzersDirectory()
    {
        var enable = Environment.GetEnvironmentVariable("DOTNET_ANALYZER_REDIRECTING");
        if (!"0".Equals(enable, StringComparison.OrdinalIgnoreCase) && !"false".Equals(enable, StringComparison.OrdinalIgnoreCase))
        {
            return Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"CommonExtensions\Microsoft\DotNet"));
        }

        return null;
    }
}

/// <summary>
/// Core functionality of <see cref="SdkAnalyzerAssemblyRedirector"/> extracted for testing.
/// </summary>
internal class SdkAnalyzerAssemblyRedirectorCore : IAnalyzerAssemblyRedirector
{
    private readonly IVsActivityLog? _log;

    /// <summary>
    /// Map from analyzer assembly name (file name without extension) to a list of matching analyzers.
    /// </summary>
    private readonly Lazy<ImmutableDictionary<string, List<AnalyzerInfo>>> _analyzerMap;

    public SdkAnalyzerAssemblyRedirectorCore(string? insertedAnalyzersDirectory, IVsActivityLog? log = null)
    {
        _log = log;
        _analyzerMap = new(() => CreateAnalyzerMap(insertedAnalyzersDirectory));
    }

    private ImmutableDictionary<string, List<AnalyzerInfo>> CreateAnalyzerMap(string? insertedAnalyzersDirectory)
    {
        if (insertedAnalyzersDirectory == null)
        {
            Log("Analyzer redirecting is disabled.");