File: Compilation\CompilationTestDataExtensions.cs
Web Access
Project: src\src\Compilers\Test\Core\Microsoft.CodeAnalysis.Test.Utilities.csproj (Microsoft.CodeAnalysis.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;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
using System.Runtime.CompilerServices;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeGen;
using Microsoft.CodeAnalysis.Emit;
using Microsoft.CodeAnalysis.Symbols;
using Cci = Microsoft.Cci;
 
namespace Roslyn.Test.Utilities
{
    internal static class CompilationTestDataExtensions
    {
        internal static void VerifyIL(
            this CompilationTestData.MethodData method,
            string expectedIL,
            [CallerLineNumber] int expectedValueSourceLine = 0,
            [CallerFilePath] string expectedValueSourcePath = null)
        {
            const string moduleNamePlaceholder = "{#Module#}";
            string actualIL = GetMethodIL(method);
            if (expectedIL.IndexOf(moduleNamePlaceholder) >= 0)
            {
                var module = method.Method.ContainingModule;
                var moduleName = Path.GetFileNameWithoutExtension(module.Name);
                expectedIL = expectedIL.Replace(moduleNamePlaceholder, moduleName);
            }
 
            AssertEx.AssertEqualToleratingWhitespaceDifferences(expectedIL, actualIL, escapeQuotes: false, expectedValueSourcePath: expectedValueSourcePath, expectedValueSourceLine: expectedValueSourceLine);
        }
 
        internal static ImmutableArray<KeyValuePair<IMethodSymbolInternal, CompilationTestData.MethodData>> GetExplicitlyDeclaredMethods(this CompilationTestData data)
        {
            return data.Methods.Where(m => !m.Key.IsImplicitlyDeclared).ToImmutableArray();
        }
 
        private static bool TryGetMethodData(ImmutableDictionary<string, CompilationTestData.MethodData> map, string qualifiedMethodName, out CompilationTestData.MethodData methodData)
        {
            if (map.TryGetValue(qualifiedMethodName, out methodData))
            {
                return true;
            }
 
            // caller may not have specified parameter list, so try to match parameterless method
            if (map.TryGetValue(qualifiedMethodName + "()", out methodData))
            {
                return true;
            }
 
            // now try to match single method with any parameter list
            var keys = map.Keys.Where(k => k.StartsWith(qualifiedMethodName + "(", StringComparison.Ordinal));
            if (keys.Count() == 1)
            {
                methodData = map[keys.First()];
                return true;
            }
            else if (keys.Count() > 1)
            {
                throw new AmbiguousMatchException(
                    "Could not determine best match for method named: " + qualifiedMethodName + Environment.NewLine +
                    string.Join(Environment.NewLine, keys.Select(s => "    " + s)) + Environment.NewLine);
            }
            else
            {
                return false;
            }
        }
 
        internal static bool TryGetMethodData(this CompilationTestData data, string qualifiedMethodName, out CompilationTestData.MethodData methodData)
        {
            var map = data.GetMethodsByName();
            return TryGetMethodData(map, qualifiedMethodName, out methodData);
        }
 
        internal static CompilationTestData.MethodData GetMethodData(this CompilationTestData data, string qualifiedMethodName)
        {
            var map = data.GetMethodsByName();
            TryGetMethodData(data, qualifiedMethodName, out var methodData);
 
            if (methodData.ILBuilder == null)
            {
                throw new KeyNotFoundException("Could not find ILBuilder matching method '" + qualifiedMethodName + "'. Existing methods:\r\n" + string.Join("\r\n", map.Keys));
            }
 
            return methodData;
        }
 
        internal static string GetMethodIL(this CompilationTestData.MethodData method)
        {
            return ILBuilderVisualizer.ILBuilderToString(method.ILBuilder);
        }
 
        internal static EditAndContinueMethodDebugInformation GetEncDebugInfo(this CompilationTestData.MethodData methodData)
        {
            // TODO:
            return new EditAndContinueMethodDebugInformation(
                0,
                Cci.MetadataWriter.GetLocalSlotDebugInfos(methodData.ILBuilder.LocalSlotManager.LocalsInOrder()),
                closures: ImmutableArray<ClosureDebugInfo>.Empty,
                lambdas: ImmutableArray<LambdaDebugInfo>.Empty,
                stateMachineStates: ImmutableArray<StateMachineStateDebugInfo>.Empty);
        }
 
        internal static Func<MethodDefinitionHandle, EditAndContinueMethodDebugInformation> EncDebugInfoProvider(this CompilationTestData.MethodData methodData)
        {
            return _ => methodData.GetEncDebugInfo();
        }
    }
}