// 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 = "Generated Code"; } else { sourceFileContent = ReadFileContentsSafely(_fileProvider, sourceFilePath); } var compilationFailure = new RoslynCompilationFailure(group) { CompiledContent = compilationContent, SourceFileContent = sourceFileContent, SourceFilePath = sourceFilePath }; failures.Add(compilationFailure); } return(CompilationResult.Failed(failures)); }
/// <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)); } } }