File: Semantics\SpeculationAnalyzerTestsBase.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.IO;
using System.Linq;
using System.Text.RegularExpressions;
using Roslyn.Test.Utilities;
using Xunit;
 
namespace Microsoft.CodeAnalysis.Editor.UnitTests.Semantics
{
    public abstract class SpeculationAnalyzerTestsBase : TestBase
    {
        protected const string CompilationName = "SemanticModelTestCompilation";
 
        protected readonly Regex UnderTestRegex = new Regex(@"\[\|(?<content>.*?)\|\]");
 
        protected readonly MetadataReference[] References =
        [
            MscorlibRef,
            SystemRef,
            SystemCoreRef,
            MsvbRef
        ];
 
        protected void Test(string code, string replacementExpression, bool semanticChanges, string expressionToAnalyze = null, bool isBrokenCode = false)
        {
            var initialMatch = UnderTestRegex.Match(code);
            Assert.True(initialMatch.Success);
            var initialExpression = initialMatch.Groups["content"].Value;
 
            var initialTree = Parse(UnderTestRegex.Replace(code, m => m.Groups["content"].Value));
            var initialNode = initialTree.GetRoot().DescendantNodes().First(n => IsExpressionNode(n) && n.ToString() == (expressionToAnalyze ?? initialExpression));
 
            var replacementTree = Parse(UnderTestRegex.Replace(code, replacementExpression));
            var replacementNode = replacementTree.GetRoot().DescendantNodes().First(n => IsExpressionNode(n) && n.ToString() == (expressionToAnalyze ?? replacementExpression));
 
            var initialCompilation = CreateCompilation(initialTree);
            var initialModel = initialCompilation.GetSemanticModel(initialTree);
 
            if (!isBrokenCode)
            {
                CheckCompilation(initialCompilation);
                CheckCompilation(CreateCompilation(replacementTree));
            }
 
            Assert.Equal(semanticChanges, ReplacementChangesSemantics(initialNode, replacementNode, initialModel));
        }
 
        private void CheckCompilation(Compilation compilation)
        {
            using var temporaryStream = new MemoryStream();
            Assert.True(CompilationSucceeded(compilation, temporaryStream));
        }
 
        protected abstract SyntaxTree Parse(string text);
 
        protected abstract bool IsExpressionNode(SyntaxNode node);
 
        protected abstract Compilation CreateCompilation(SyntaxTree tree);
 
        protected abstract bool CompilationSucceeded(Compilation compilation, Stream temporaryStream);
 
        protected abstract bool ReplacementChangesSemantics(SyntaxNode initialNode, SyntaxNode replacementNode, SemanticModel initialModel);
    }
}