/// <inheritdoc />
        public CompilationResult Compile([NotNull] RelativeFileInfo fileInfo, [NotNull] string compilationContent)
        {
            // The path passed to SyntaxTreeGenerator.Generate is used by the compiler to generate symbols (pdb) that
            // map to the source file. If a file does not exist on a physical file system, PhysicalPath will be null.
            // This prevents files that exist in a non-physical file system from being debugged.
            var path = fileInfo.FileInfo.PhysicalPath ?? fileInfo.RelativePath;
            var compilationSettings = _compilerOptionsProvider.GetCompilationSettings(_environment);
            var syntaxTree = SyntaxTreeGenerator.Generate(compilationContent,
                                                          path,
                                                          compilationSettings);
            var references = _applicationReferences.Value;

            var assemblyName = Path.GetRandomFileName();
            var compilationOptions = compilationSettings.CompilationOptions
                                                        .WithOutputKind(OutputKind.DynamicallyLinkedLibrary);

            var compilation = CSharpCompilation.Create(assemblyName,
                        options: compilationOptions,
                        syntaxTrees: new[] { syntaxTree },
                        references: references);

            using (var ms = new MemoryStream())
            {
                using (var pdb = new MemoryStream())
                {
                    EmitResult result;

                    if (_supportsPdbGeneration.Value)
                    {
                        result = compilation.Emit(ms, pdbStream: pdb);
                    }
                    else
                    {
                        result = compilation.Emit(ms);
                    }

                    if (!result.Success)
                    {
                        var failures = result.Diagnostics.Where(IsError);
                        var compilationFailure = new RoslynCompilationFailure(failures)
                        {
                            CompiledContent = compilationContent,
                            SourceFileContent = ReadFileContentsSafely(fileInfo.FileInfo),
                            SourceFilePath = fileInfo.RelativePath
                        };

                        return CompilationResult.Failed(compilationFailure);
                    }

                    Assembly assembly;
                    ms.Seek(0, SeekOrigin.Begin);

                    if (_supportsPdbGeneration.Value)
                    {
                        pdb.Seek(0, SeekOrigin.Begin);
                        assembly = _loader.LoadStream(ms, pdb);
                    }
                    else
                    {
                        assembly = _loader.LoadStream(ms, assemblySymbols: null);
                    }

                    var type = assembly.GetExportedTypes()
                                       .First(t => t.Name.StartsWith(_classPrefix, StringComparison.Ordinal));

                    return UncachedCompilationResult.Successful(type, compilationContent);
                }
            }
        }
        // Internal for unit testing
        internal CompilationResult GetCompilationFailedResult(
            string relativePath,
            string compilationContent,
            string assemblyName,
            IEnumerable<Diagnostic> diagnostics)
        {
            var diagnosticGroups = diagnostics
                .Where(IsError)
                .GroupBy(diagnostic => GetFilePath(relativePath, diagnostic), StringComparer.Ordinal);

            var failures = new List<ICompilationFailure>();
            foreach (var group in diagnosticGroups)
            {
                var sourceFilePath = group.Key;
                string sourceFileContent;
                if (string.Equals(assemblyName, sourceFilePath, StringComparison.Ordinal))
                {
                    // The error is in the generated code and does not have a mapping line pragma
                    sourceFileContent = compilationContent;
                    sourceFilePath = Resources.GeneratedCodeFileName;
                }
                else
                {
                    sourceFileContent = ReadFileContentsSafely(_fileProvider, sourceFilePath);
                }

                var compilationFailure = new RoslynCompilationFailure(group)
                {
                    CompiledContent = compilationContent,
                    SourceFileContent = sourceFileContent,
                    SourceFilePath = sourceFilePath
                };

                failures.Add(compilationFailure);
            }

            return CompilationResult.Failed(failures);
        }