File: DiagnosticAnalyzer\DefaultAnalyzerAssemblyLoader.cs
Web Access
Project: src\src\Compilers\Core\Portable\Microsoft.CodeAnalysis.csproj (Microsoft.CodeAnalysis)
// 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.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using Roslyn.Utilities;
 
namespace Microsoft.CodeAnalysis
{
    internal sealed class DefaultAnalyzerAssemblyLoader : AnalyzerAssemblyLoader
    {
        internal DefaultAnalyzerAssemblyLoader()
            : base([])
        {
        }
 
        internal DefaultAnalyzerAssemblyLoader(ImmutableArray<IAnalyzerAssemblyResolver> externalResolvers)
            : base(externalResolvers)
        {
        }
 
#if NET
 
        internal DefaultAnalyzerAssemblyLoader(System.Runtime.Loader.AssemblyLoadContext? compilerLoadContext = null, AnalyzerLoadOption loadOption = AnalyzerLoadOption.LoadFromDisk, ImmutableArray<IAnalyzerAssemblyResolver>? externalResolvers = null)
            : base(compilerLoadContext, loadOption, externalResolvers ?? [])
        {
        }
 
#endif
 
        /// <summary>
        /// The default implementation is to simply load in place.
        /// </summary>
        protected override string PreparePathToLoad(string fullPath) => fullPath;
 
        /// <summary>
        /// The default implementation is to simply load in place.
        /// </summary>
        protected override string PrepareSatelliteAssemblyToLoad(string assemblyFilePath, string cultureName)
        {
            var directory = Path.GetDirectoryName(assemblyFilePath)!;
            var fileName = GetSatelliteFileName(Path.GetFileName(assemblyFilePath));
 
            return Path.Combine(directory, cultureName, fileName);
        }
 
        /// <summary>
        /// Return an <see cref="IAnalyzerAssemblyLoader"/> which does not lock assemblies on disk that is
        /// most appropriate for the current platform.
        /// </summary>
        /// <param name="windowsShadowPath">A shadow copy path will be created on Windows and this value 
        /// will be the base directory where shadow copy assemblies are stored. </param>
        internal static IAnalyzerAssemblyLoaderInternal CreateNonLockingLoader(string windowsShadowPath, ImmutableArray<IAnalyzerAssemblyResolver>? externalResolvers = null)
        {
#if NET
            if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                return new DefaultAnalyzerAssemblyLoader(loadOption: AnalyzerLoadOption.LoadFromStream, externalResolvers: externalResolvers);
            }
#endif
 
            // The shadow copy analyzer should only be created on Windows. To create on Linux we cannot use 
            // GetTempPath as it's not per-user. Generally there is no need as LoadFromStream achieves the same
            // effect
            if (!Path.IsPathRooted(windowsShadowPath))
            {
                throw new ArgumentException("Must be a full path.", nameof(windowsShadowPath));
            }
 
            return new ShadowCopyAnalyzerAssemblyLoader(windowsShadowPath, externalResolvers);
        }
    }
}