File: TypeInferrer\TypeInferrerTestBase.cs
Web Access
Project: src\src\EditorFeatures\TestUtilities\Microsoft.CodeAnalysis.EditorFeatures.Test.Utilities.csproj (Microsoft.CodeAnalysis.EditorFeatures.Test.Utilities)
// 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.
 
#nullable disable
 
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.LanguageService;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Test.Utilities;
using Roslyn.Utilities;
 
namespace Microsoft.CodeAnalysis.Editor.UnitTests.TypeInferrer;
 
[UseExportProvider]
public abstract class TypeInferrerTestBase<TWorkspaceFixture> : TestBase
    where TWorkspaceFixture : TestWorkspaceFixture, new()
{
    private readonly TestFixtureHelper<TWorkspaceFixture> _fixtureHelper = new();
 
    private protected ReferenceCountedDisposable<TWorkspaceFixture> GetOrCreateWorkspaceFixture()
        => _fixtureHelper.GetOrCreateFixture();
 
    private static async Task<bool> CanUseSpeculativeSemanticModelAsync(Document document, int position)
    {
        var service = document.GetLanguageService<ISyntaxFactsService>();
        var node = (await document.GetSyntaxRootAsync()).FindToken(position).Parent;
 
        return !service.GetMemberBodySpanForSpeculativeBinding(node).IsEmpty;
    }
 
    /// <summary>
    /// Specifies which overload of the <see cref="ITypeInferenceService"/> will be tested.
    /// </summary>
    public enum TestMode
    {
        /// <summary>
        /// Specifies the test is going to call into <see cref="ITypeInferenceService.InferTypes(SemanticModel, SyntaxNode, string, System.Threading.CancellationToken)"/>.
        /// </summary>
        Node,
 
        /// <summary>
        /// Specifies the test is going to call into <see cref="ITypeInferenceService.InferTypes(SemanticModel, int, string, System.Threading.CancellationToken)"/>.
        /// </summary>
        Position
    }
 
    protected async Task TestAsync(string text, string expectedType, TestMode mode,
        SourceCodeKind sourceCodeKind = SourceCodeKind.Regular)
    {
        using var workspaceFixture = GetOrCreateWorkspaceFixture();
 
        MarkupTestFile.GetSpan(text.NormalizeLineEndings(), out text, out var textSpan);
 
        var document = workspaceFixture.Target.UpdateDocument(text, sourceCodeKind);
        await TestWorkerAsync(document, textSpan, expectedType, mode);
 
        if (await CanUseSpeculativeSemanticModelAsync(document, textSpan.Start))
        {
            var document2 = workspaceFixture.Target.UpdateDocument(text, sourceCodeKind, cleanBeforeUpdate: false);
            await TestWorkerAsync(document2, textSpan, expectedType, mode);
        }
    }
 
    protected abstract Task TestWorkerAsync(Document document, TextSpan textSpan, string expectedType, TestMode mode);
}