File: Workspaces\WorkspaceTestBase.cs
Web Access
Project: src\src\Razor\src\Razor\test\Microsoft.AspNetCore.Razor.Test.Common.Tooling\Microsoft.AspNetCore.Razor.Test.Common.Tooling.csproj (Microsoft.AspNetCore.Razor.Test.Common.Tooling)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.Razor.Workspaces;
 
using Xunit.Abstractions;
 
namespace Microsoft.AspNetCore.Razor.Test.Common.Workspaces;
 
public abstract class WorkspaceTestBase(ITestOutputHelper testOutput) : ToolingTestBase(testOutput)
{
    private bool _initialized;
    private HostServices? _hostServices;
    private Workspace? _workspace;
    private IWorkspaceProvider? _workspaceProvider;
    private LanguageServerFeatureOptions? _languageServerFeatureOptions;
 
    protected HostServices HostServices
    {
        get
        {
            EnsureInitialized();
            return _hostServices;
        }
    }
 
    protected Workspace Workspace
    {
        get
        {
            EnsureInitialized();
            return _workspace;
        }
    }
 
    private protected IWorkspaceProvider WorkspaceProvider
    {
        get
        {
            EnsureInitialized();
            return _workspaceProvider;
        }
    }
 
    private protected LanguageServerFeatureOptions LanguageServerFeatureOptions
    {
        get
        {
            EnsureInitialized();
            return _languageServerFeatureOptions;
        }
    }
 
    protected virtual void ConfigureWorkspace(AdhocWorkspace workspace)
    {
    }
 
    protected virtual void ConfigureProjectEngine(RazorProjectEngineBuilder builder)
    {
    }
 
    [MemberNotNull(
        nameof(_hostServices),
        nameof(_workspace),
        nameof(_workspaceProvider),
        nameof(_languageServerFeatureOptions))]
    private void EnsureInitialized()
    {
        if (_initialized)
        {
            _hostServices.AssumeNotNull();
            _workspace.AssumeNotNull();
            _workspaceProvider.AssumeNotNull();
            _languageServerFeatureOptions.AssumeNotNull();
            return;
        }
 
        _hostServices = MefHostServices.DefaultHost;
        _workspace = TestWorkspace.Create(_hostServices, ConfigureWorkspace);
        AddDisposable(_workspace);
        _workspaceProvider = new TestWorkspaceProvider(_workspace);
        _languageServerFeatureOptions = TestLanguageServerFeatureOptions.Instance;
        _initialized = true;
    }
 
    /// <summary>
    ///  Calls <see cref="Workspace.TryApplyChanges(Solution)"/> and waits for <see cref="Workspace.WorkspaceChanged"/>
    ///  to stop firing events.
    /// </summary>
    protected Task<bool> UpdateWorkspaceAsync(Solution solution)
    {
        return Task.Run(
            async () =>
            {
                var currentCount = 0;
 
                using var _ = Workspace.RegisterWorkspaceChangedHandler(OnWorkspaceChanged);
 
                if (!Workspace.TryApplyChanges(solution))
                {
                    return false;
                }
 
                int lastCount;
 
                do
                {
                    lastCount = currentCount;
                    await Task.Delay(50);
                }
                while (lastCount != currentCount);
 
                return true;
 
                void OnWorkspaceChanged(WorkspaceChangeEventArgs e)
                {
                    currentCount++;
                }
            },
            DisposalToken);
    }
 
    private sealed class TestWorkspaceProvider(Workspace workspace) : IWorkspaceProvider
    {
        public Workspace GetWorkspace() => workspace;
    }
}