File: DiagnosticProject.cs
Web Access
Project: src\src\Analyzers\Microsoft.AspNetCore.Analyzer.Testing\src\Microsoft.AspNetCore.Analyzer.Testing.csproj (Microsoft.AspNetCore.Analyzer.Testing)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Text;
using Microsoft.Extensions.DependencyModel;
using Microsoft.Extensions.DependencyModel.Resolution;
 
namespace Microsoft.AspNetCore.Analyzer.Testing;
 
public class DiagnosticProject
{
    /// <summary>
    /// File name prefix used to generate Documents instances from source.
    /// </summary>
    public static string DefaultFilePathPrefix = "Test";
 
    /// <summary>
    /// Project name.
    /// </summary>
    public static string TestProjectName = "TestProject";
 
    private static readonly ICompilationAssemblyResolver _assemblyResolver = new AppBaseCompilationAssemblyResolver();
    private static readonly Dictionary<Assembly, Solution> _solutionCache = new Dictionary<Assembly, Solution>();
 
    public static Project Create(Assembly testAssembly, string[] sources, Func<Workspace> workspaceFactory = null, Type analyzerReference = null)
    {
        Solution solution;
        lock (_solutionCache)
        {
            if (!_solutionCache.TryGetValue(testAssembly, out solution))
            {
                workspaceFactory ??= CreateWorkspace;
 
                var projectId = ProjectId.CreateNewId(debugName: TestProjectName);
                solution = workspaceFactory()
                    .CurrentSolution
                    .AddProject(projectId, TestProjectName, TestProjectName, LanguageNames.CSharp);
 
                foreach (var defaultCompileLibrary in DependencyContext.Load(testAssembly).CompileLibraries)
                {
                    foreach (var resolveReferencePath in defaultCompileLibrary.ResolveReferencePaths(_assemblyResolver))
                    {
                        solution = solution.AddMetadataReference(projectId, MetadataReference.CreateFromFile(resolveReferencePath));
                    }
                }
 
                if (analyzerReference != null)
                {
                    solution = solution.AddAnalyzerReference(
                        projectId,
                        new AnalyzerFileReference(analyzerReference.Assembly.Location, AssemblyLoader.Instance));
                }
 
                _solutionCache.Add(testAssembly, solution);
            }
        }
 
        var testProject = solution.ProjectIds.Single();
        var fileNamePrefix = DefaultFilePathPrefix;
 
        for (var i = 0; i < sources.Length; i++)
        {
            var newFileName = fileNamePrefix;
            if (sources.Length > 1)
            {
                newFileName += i;
            }
            newFileName += ".cs";
 
            var documentId = DocumentId.CreateNewId(testProject, debugName: newFileName);
            solution = solution.AddDocument(documentId, newFileName, SourceText.From(sources[i]));
        }
 
        return solution.GetProject(testProject);
    }
 
    private static Workspace CreateWorkspace()
    {
        return new AdhocWorkspace();
    }
 
    internal sealed class AssemblyLoader : IAnalyzerAssemblyLoader
    {
        public static AssemblyLoader Instance = new AssemblyLoader();
 
        public void AddDependencyLocation(string fullPath)
        {
        }
 
        public Assembly LoadFromPath(string fullPath)
        {
            return Assembly.LoadFrom(fullPath);
        }
    }
}