private static IEnumerable <NamedTest> GetSelfVerifyingFacts <TTargetCompiler, TLanguageConversion>(string sourceFileText,
                                                                                                        List <NamedTest> runnableTestsInSource) where TTargetCompiler : ICompiler, new()
        where TLanguageConversion : ILanguageConversion, new()
    {
        // Lazy to avoid confusing test runner on error, but also avoid calculating multiple times
        var conversionResultAsync = new AsyncLazy <ConversionResult>(() => {
            var xUnitReferences = DefaultReferences.With(typeof(FactAttribute).Assembly, typeof(Assert).Assembly);
            return(ProjectConversion.ConvertTextAsync <TLanguageConversion>(sourceFileText, new TextConversionOptions(xUnitReferences)));
        });

        var runnableTestsInTarget = new AsyncLazy <Dictionary <string, NamedTest> >(async() => GetConvertedNamedFacts <TTargetCompiler>(runnableTestsInSource,
                                                                                                                                        await conversionResultAsync.GetValueAsync()));

        return(runnableTestsInSource.Select(sourceFact =>
                                            new NamedTest(sourceFact.Name, async() =>
        {
            try
            {
                await sourceFact.Execute();
            }
            catch (TargetInvocationException ex)
            {
                throw new XunitException(
                    $"Source test failed, ensure the source is correct for \"{sourceFact.Name}\": {(ex.InnerException ?? ex)}");
            }

            try {
                var test = await runnableTestsInTarget.GetValueAsync();
                await test[sourceFact.Name].Execute();
            }
            catch (TargetInvocationException ex) {
                var conversionResult = await conversionResultAsync.GetValueAsync();
                throw new XunitException(
                    $"Converted test failed, the conversion is incorrect for \"{sourceFact.Name}\": {(ex.InnerException ?? ex)}\r\nConverted Code: {conversionResult.ConvertedCode ?? conversionResult.GetExceptionsAsString()}");
            }
        })
                                            ));
    }
    /// <summary>
    /// Compiles the given string of source code into an IL byte array.
    /// </summary>
    /// <remarks>The transitive closure of the references for <paramref name="requiredAssemblies"/> are added.</remarks>
    public static Assembly AssemblyFromCode(this ICompiler compiler, SyntaxTree syntaxTree, params Assembly[] requiredAssemblies)
    {
        var allReferences = DefaultReferences.With(requiredAssemblies);
        var compilation   = compiler.CreateCompilationFromTree(syntaxTree, allReferences);

        using (var dllStream = new MemoryStream())
            using (var pdbStream = new MemoryStream()) {
                var result = compilation.Emit(dllStream, pdbStream);
                if (!result.Success)
                {
                    string codeLines = string.Join("\r\n", Utils.HomogenizeEol(syntaxTree.ToString())
                                                   .Split(new[] { "\r\n" }, StringSplitOptions.None)
                                                   .Select((l, i) => $"{i+1:000}: {l}"));
                    throw new CompilationException(
                              $"{compiler.GetType().Name} error:\r\n{string.Join("\r\n", result.Diagnostics)}\r\n\r\nSource code:\r\n{codeLines}"
                              );
                }

                dllStream.Seek(0, SeekOrigin.Begin);
                pdbStream.Seek(0, SeekOrigin.Begin);
                return(Assembly.Load(dllStream.ToArray(), pdbStream.ToArray()));
            }
    }