public void FromSource_ArgumentErrors() { Assert.Throws <ArgumentNullException>("filePath", () => EmbeddedText.FromSource(null, null)); Assert.Throws <ArgumentException>("filePath", () => EmbeddedText.FromSource("", null)); Assert.Throws <ArgumentNullException>("text", () => EmbeddedText.FromSource("path", null)); // no encoding Assert.Throws <ArgumentException>("text", () => EmbeddedText.FromSource("path", SourceText.From("source"))); // embedding not allowed Assert.Throws <ArgumentException>("text", () => EmbeddedText.FromSource("path", SourceText.From(new byte[0], 0, Encoding.UTF8, canBeEmbedded: false))); Assert.Throws <ArgumentException>("text", () => EmbeddedText.FromSource("path", SourceText.From(new MemoryStream(new byte[0]), Encoding.UTF8, canBeEmbedded: false))); }
public void FromTextReader_Large() { var expected = SourceText.From(LargeSource, Encoding.UTF8, SourceHashAlgorithm.Sha1); var expectedEmbedded = EmbeddedText.FromSource("pathToSmall", expected); var actual = SourceText.From(new StringReader(LargeSource), LargeSource.Length, Encoding.UTF8, SourceHashAlgorithm.Sha1); var actualEmbedded = EmbeddedText.FromSource(expectedEmbedded.FilePath, actual); Assert.Equal(expectedEmbedded.FilePath, actualEmbedded.FilePath); Assert.Equal(expectedEmbedded.ChecksumAlgorithm, actualEmbedded.ChecksumAlgorithm); AssertEx.Equal(expectedEmbedded.Checksum, actualEmbedded.Checksum); AssertEx.Equal(expectedEmbedded.Blob, actualEmbedded.Blob); }
public void FromSource_Small() { var source = SourceText.From(SmallSource, Encoding.UTF8, SourceHashAlgorithm.Sha1); var text = EmbeddedText.FromSource("pathToSmall", source); Assert.Equal("pathToSmall", text.FilePath); Assert.Equal(SourceHashAlgorithm.Sha1, text.ChecksumAlgorithm); AssertEx.Equal(source.GetChecksum(), text.Checksum); AssertEx.Equal(new byte[] { 0, 0, 0, 0 }, text.Blob.Take(4)); AssertEx.Equal( Encoding.UTF8.GetPreamble().Concat(Encoding.UTF8.GetBytes(SmallSource)), text.Blob.Skip(4) ); }
public Source(Stream s, string name, bool includeText) { Name = name; SourceText source = SourceText.From(s, canBeEmbedded: includeText); if (includeText) { Text = EmbeddedText.FromSource(name, source); Tree = CSharpSyntaxTree.ParseText(source, new CSharpParseOptions(LanguageVersion.Latest), name); } else { Tree = CSharpSyntaxTree.ParseText(source, new CSharpParseOptions(LanguageVersion.Latest)); } }
public async Task <bool> BuildAsync(string code, OptimizationLevel?optimizationLevel, string codePath, CancellationToken cancellationToken = default) { await new NoContextYieldAwaitable(); _logger.LogInformation($"{Name}: Start to build..."); var sw = Stopwatch.StartNew(); try { _assemblyPath = Path.Combine(BuildPath, $"{Name}.dll"); _depsFile = Path.ChangeExtension(_assemblyPath, ".deps.json"); var encoding = Encoding.UTF8; var buffer = encoding.GetBytes(code); var sourceText = SourceText.From(buffer, buffer.Length, encoding, canBeEmbedded: true); var scriptRunner = CreateScriptRunner(sourceText, codePath, optimizationLevel); CopyDependencies(); var embeddedTexts = new List <EmbeddedText>() { EmbeddedText.FromSource(codePath, sourceText), }; var diagnostics = await scriptRunner.SaveAssembly(_assemblyPath, embeddedTexts, cancellationToken) .ConfigureAwait(false); SendDiagnostics(diagnostics); var error = diagnostics.Any(d => d.Severity == DiagnosticSeverity.Error); _logger.LogInformation($"{Name}: Build {(error ? "error": "successfully")} , time: {sw.ElapsedMilliseconds}ms"); if (error) { return(false); } CreateRuntimeConfig(); } catch (Exception e) { _logger?.LogError(e.Message + e.StackTrace); return(false); } return(true); }
public EmitResult Emit( Stream rebuildPeStream, Compilation rebuildCompilation, CancellationToken cancellationToken) { var embeddedTexts = rebuildCompilation.SyntaxTrees .Select(st => (path: st.FilePath, text: st.GetText())) .Where(pair => pair.text.CanBeEmbedded) .Select(pair => EmbeddedText.FromSource(pair.path, pair.text)) .ToImmutableArray(); return(Emit( rebuildPeStream, rebuildCompilation, embeddedTexts, cancellationToken)); }
public void EmbeddedPdb() { string source = @" using System; class C { public static void Main() { Console.WriteLine(); } } "; var tree = Parse(source, "f:/build/goo.cs"); var c = CreateCompilation(tree, options: TestOptions.DebugDll); var pdbStream = new MemoryStream(); var peBlob = c.EmitToArray( EmitOptions.Default.WithDebugInformationFormat(DebugInformationFormat.Embedded), embeddedTexts: new[] { EmbeddedText.FromSource(tree.FilePath, tree.GetText()) }); pdbStream.Position = 0; using (var peReader = new PEReader(peBlob)) { var embeddedEntry = peReader.ReadDebugDirectory().Single(e => e.Type == DebugDirectoryEntryType.EmbeddedPortablePdb); using (var embeddedMetadataProvider = peReader.ReadEmbeddedPortablePdbDebugDirectoryData(embeddedEntry)) { var pdbReader = embeddedMetadataProvider.GetMetadataReader(); var embeddedSource = (from documentHandle in pdbReader.Documents let document = pdbReader.GetDocument(documentHandle) select new { FilePath = pdbReader.GetString(document.Name), Text = pdbReader.GetEmbeddedSource(documentHandle) }).Single(); Assert.Equal(embeddedSource.FilePath, "f:/build/goo.cs"); Assert.Equal(source, embeddedSource.Text.ToString()); } } }
public void FromSource_Large() { var source = SourceText.From(LargeSource, Encoding.Unicode, SourceHashAlgorithm.Sha256); var text = EmbeddedText.FromSource("pathToLarge", source); Assert.Equal("pathToLarge", text.FilePath); Assert.Equal(SourceHashAlgorithm.Sha256, text.ChecksumAlgorithm); AssertEx.Equal(source.GetChecksum(), text.Checksum); AssertEx.Equal( BitConverter.GetBytes( Encoding.Unicode.GetPreamble().Length + LargeSource.Length * sizeof(char) ), text.Blob.Take(4) ); AssertEx.Equal( Encoding.Unicode.GetPreamble().Concat(Encoding.Unicode.GetBytes(LargeSource)), Decompress(text.Blob.Skip(4)) ); }
private void AddCode(string desiredPath, MemberDeclarationSyntax member) { var compilationUnit = SyntaxFactory.CompilationUnit().AddMembers(member); var sourceText = compilationUnit.ToString(); var sourceBytes = Encoding.UTF8.GetBytes(sourceText); var embeddableText = SourceText.From(sourceBytes, sourceBytes.Length, Encoding.UTF8, canBeEmbedded: true); embeddedSource.Add(EmbeddedText.FromSource(desiredPath, embeddableText)); var tree = CSharpSyntaxTree.Create(compilationUnit, null, desiredPath, Encoding.UTF8); this.compilation = this.compilation.AddSyntaxTrees(tree); if (string.IsNullOrWhiteSpace(this.generatedScriptOutput) == false) { File.WriteAllText(Path.Combine(this.generatedScriptOutput, desiredPath), sourceText); } }
public void FromSource_Empty() { var source = SourceText.From( "", new UTF8Encoding(encoderShouldEmitUTF8Identifier: false), SourceHashAlgorithm.Sha1 ); var text = EmbeddedText.FromSource("pathToEmpty", source); var checksum = SourceText.CalculateChecksum( new byte[0], 0, 0, SourceHashAlgorithm.Sha1 ); Assert.Equal("pathToEmpty", text.FilePath); Assert.Equal(SourceHashAlgorithm.Sha1, text.ChecksumAlgorithm); AssertEx.Equal(checksum, text.Checksum); AssertEx.Equal(new byte[] { 0, 0, 0, 0 }, text.Blob); }
public void FromSource_Precomputed() { byte[] bytes = Encoding.ASCII.GetBytes(LargeSource); bytes[0] = 0xFF; // invalid ASCII, should be reflected in checksum, blob. foreach (bool useStream in new[] { true, false }) { var source = useStream ? SourceText.From(new MemoryStream(bytes), Encoding.ASCII, SourceHashAlgorithm.Sha1, canBeEmbedded: true) : SourceText.From(bytes, bytes.Length, Encoding.ASCII, SourceHashAlgorithm.Sha1, canBeEmbedded: true); var text = EmbeddedText.FromSource("pathToPrecomputed", source); Assert.Equal("pathToPrecomputed", text.FilePath); Assert.Equal(SourceHashAlgorithm.Sha1, text.ChecksumAlgorithm); AssertEx.Equal(SourceText.CalculateChecksum(bytes, 0, bytes.Length, SourceHashAlgorithm.Sha1), source.GetChecksum()); AssertEx.Equal(source.GetChecksum(), text.Checksum); AssertEx.Equal(BitConverter.GetBytes(bytes.Length), text.Blob.Take(4)); AssertEx.Equal(bytes, Decompress(text.Blob.Skip(4))); } }
public void EmbeddedSource() { string source = @" using System; class C { public static void Main() { Console.WriteLine(); } } "; var tree = Parse(source, "f:/build/foo.cs"); var c = CreateCompilationWithMscorlib(tree, options: TestOptions.DebugDll); var pdbStream = new MemoryStream(); c.EmitToArray( EmitOptions.Default.WithDebugInformationFormat(DebugInformationFormat.PortablePdb), pdbStream: pdbStream, embeddedTexts: new[] { EmbeddedText.FromSource(tree.FilePath, tree.GetText()) }); pdbStream.Position = 0; using (var provider = MetadataReaderProvider.FromPortablePdbStream(pdbStream)) { var pdbReader = provider.GetMetadataReader(); var embeddedSource = (from documentHandle in pdbReader.Documents let document = pdbReader.GetDocument(documentHandle) select new { FilePath = pdbReader.GetString(document.Name), Text = pdbReader.GetEmbeddedSource(documentHandle) }).Single(); Assert.Equal(embeddedSource.FilePath, "f:/build/foo.cs"); Assert.Equal(source, embeddedSource.Text.ToString()); } }
public static void CompileCSharpWithPdb(string assemblyName, Dictionary <string, string> sourceFiles) { var parseOptions = new CSharpParseOptions(languageVersion: Microsoft.CodeAnalysis.CSharp.LanguageVersion.Latest); List <EmbeddedText> embeddedTexts = new List <EmbeddedText>(); List <SyntaxTree> syntaxTrees = new List <SyntaxTree>(); foreach (KeyValuePair <string, string> file in sourceFiles) { var sourceText = SourceText.From(file.Value, new UTF8Encoding(false), SourceHashAlgorithm.Sha256); syntaxTrees.Add(SyntaxFactory.ParseSyntaxTree(sourceText, parseOptions, file.Key)); embeddedTexts.Add(EmbeddedText.FromSource(file.Key, sourceText)); } var compilation = CSharpCompilation.Create(Path.GetFileNameWithoutExtension(assemblyName), syntaxTrees, roslynDefaultReferences.Value.Select(r => MetadataReference.CreateFromFile(r)), new CSharpCompilationOptions( OutputKind.DynamicallyLinkedLibrary, platform: Platform.AnyCpu, optimizationLevel: OptimizationLevel.Release, allowUnsafe: true, deterministic: true )); using (FileStream peStream = File.Open(assemblyName + ".dll", FileMode.OpenOrCreate, FileAccess.ReadWrite)) using (FileStream pdbStream = File.Open(assemblyName + ".pdb", FileMode.OpenOrCreate, FileAccess.ReadWrite)) { var emitResult = compilation.Emit(peStream, pdbStream, options: new EmitOptions(debugInformationFormat: DebugInformationFormat.PortablePdb, pdbFilePath: assemblyName + ".pdb"), embeddedTexts: embeddedTexts); if (!emitResult.Success) { StringBuilder b = new StringBuilder("Compiler error:"); foreach (var diag in emitResult.Diagnostics) { b.AppendLine(diag.ToString()); } throw new Exception(b.ToString()); } } }
/// <inheritdoc /> public Assembly Compile(string sourceTextHash, CSharpCompilation compilation, Action <EmitResult> check) { this._logger.LogInformation("Compiling source to an in-memory DLL with embedded source"); using var assemblyStream = new MemoryStream(); using var symbolsStream = new MemoryStream(); var emitOptions = new EmitOptions(debugInformationFormat: DebugInformationFormat.PortablePdb); var embeddedTexts = compilation.SyntaxTrees.Select(s => EmbeddedText.FromSource(s.FilePath, s.GetText())); var result = compilation.Emit( peStream: assemblyStream, pdbStream: symbolsStream, embeddedTexts: embeddedTexts, options: emitOptions); check(result); assemblyStream.Seek(0, SeekOrigin.Begin); symbolsStream.Seek(0, SeekOrigin.Begin); return(AssemblyLoadContext.Default.LoadFromStream(assemblyStream, symbolsStream)); }
public void StandalonePdb() { string source1 = @" using System; class C { public static void Main() { Console.WriteLine(); } } "; string source2 = @" // no code "; var tree1 = Parse(source1, "f:/build/goo.cs"); var tree2 = Parse(source2, "f:/build/nocode.cs"); var c = CreateCompilation(new[] { tree1, tree2 }, options: TestOptions.DebugDll); var embeddedTexts = new[] { EmbeddedText.FromSource(tree1.FilePath, tree1.GetText()), EmbeddedText.FromSource(tree2.FilePath, tree2.GetText()) }; c.VerifyPdb(@" <symbols> <files> <file id=""1"" name=""f:/build/goo.cs"" language=""C#"" checksumAlgorithm=""SHA1"" checksum=""5D-7D-CF-1B-79-12-0E-0A-80-13-E0-98-7E-5C-AA-3B-63-D8-7E-4F"" embeddedSourceLength=""98""><![CDATA[ using System; class C { public static void Main() { Console.WriteLine(); } } ]]></file> <file id=""2"" name=""f:/build/nocode.cs"" language=""C#"" checksumAlgorithm=""SHA1"" checksum=""8B-1D-3F-75-E0-A8-8F-90-B2-D3-52-CF-71-9B-17-29-3C-70-7A-42"" embeddedSourceLength=""21""><![CDATA[ // no code ]]></file> </files> <methods> <method containingType=""C"" name=""Main""> <customDebugInfo> <using> <namespace usingCount=""1"" /> </using> </customDebugInfo> <sequencePoints> <entry offset=""0x0"" startLine=""7"" startColumn=""5"" endLine=""7"" endColumn=""6"" document=""1"" /> <entry offset=""0x1"" startLine=""8"" startColumn=""9"" endLine=""8"" endColumn=""29"" document=""1"" /> <entry offset=""0x7"" startLine=""9"" startColumn=""5"" endLine=""9"" endColumn=""6"" document=""1"" /> </sequencePoints> <scope startOffset=""0x0"" endOffset=""0x8""> <namespace name=""System"" /> </scope> </method> </methods> </symbols> ", embeddedTexts); }
public Assembly CreateAssembly(string filePath) { string code = File.ReadAllText(filePath); var encoding = Encoding.UTF8; var assemblyName = Path.GetRandomFileName(); var symbolsName = Path.ChangeExtension(assemblyName, "pdb"); var buffer = encoding.GetBytes(code); var sourceText = SourceText.From(buffer, buffer.Length, encoding, canBeEmbedded: true); var syntaxTree = CSharpSyntaxTree.ParseText( sourceText, new CSharpParseOptions(), path: filePath); var syntaxRootNode = syntaxTree.GetRoot() as CSharpSyntaxNode; var encoded = CSharpSyntaxTree.Create(syntaxRootNode, null, filePath, encoding); var optimizationLevel = OptimizationLevel.Debug; var references = new MetadataReference[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location), MetadataReference.CreateFromFile(typeof(Console).Assembly.Location), MetadataReference.CreateFromFile(typeof(System.Runtime.AssemblyTargetedPatchBandAttribute).Assembly.Location), MetadataReference.CreateFromFile(typeof(Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo).Assembly.Location), }; CSharpCompilation compilation = CSharpCompilation.Create( assemblyName, syntaxTrees: new[] { encoded }, references: references, options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary) .WithOptimizationLevel(optimizationLevel) .WithPlatform(Platform.AnyCpu) ); using var assemblyStream = new MemoryStream(); using var symbolsStream = new MemoryStream(); var emitOptions = new EmitOptions(debugInformationFormat: DebugInformationFormat.PortablePdb, pdbFilePath: symbolsName); var embeddedTexts = new List <EmbeddedText>() { EmbeddedText.FromSource(filePath, sourceText) }; EmitResult result = compilation.Emit( peStream: assemblyStream, pdbStream: symbolsStream, embeddedTexts: embeddedTexts, options: emitOptions); if (!result.Success) { var errors = new List <string>(); IEnumerable <Diagnostic> failures = result.Diagnostics.Where(diagnostic => diagnostic.IsWarningAsError || diagnostic.Severity == DiagnosticSeverity.Error); foreach (Diagnostic diagnostic in failures) { errors.Add($"{diagnostic.Id}: {diagnostic.GetMessage()}"); } throw new Exception(String.Join("\n", errors)); } // Console.WriteLine(code); assemblyStream.Seek(0, SeekOrigin.Begin); symbolsStream?.Seek(0, SeekOrigin.Begin); var assembly = Assembly.Load(assemblyStream.ToArray(), symbolsStream.ToArray()); return(assembly); }
public static Assembly Compile(string[] references, string name, params string[] codes) { string systemAsm = typeof(object).GetTypeInfo().Assembly.Location; string attributeAsm = typeof(System.Runtime.AssemblyTargetedPatchBandAttribute).GetTypeInfo().Assembly.Location; string vectorAsm = typeof(Vector3).GetTypeInfo().Assembly.Location; string consoleAsm = typeof(Console).GetTypeInfo().Assembly.Location; Encoding encoding = Encoding.UTF8; string assemblyName = Path.GetRandomFileName(); string symbolsName = Path.ChangeExtension(assemblyName, "pdb"); List <EmbeddedText> embeddedTexts = new List <EmbeddedText>(); List <SyntaxTree> encoded = new List <SyntaxTree>(); foreach (string code in codes) { string sourceCodePath = code.GetHashCode() + ".cs"; byte[] buffer = encoding.GetBytes(code); SourceText sourceText = SourceText.From(buffer, buffer.Length, encoding, canBeEmbedded: true); SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText( sourceText, new CSharpParseOptions(), path: sourceCodePath); encoded.Add(CSharpSyntaxTree.Create(syntaxTree.GetRoot() as CSharpSyntaxNode, null, sourceCodePath, encoding)); embeddedTexts.Add(EmbeddedText.FromSource(sourceCodePath, sourceText)); } OptimizationLevel optimizationLevel = OptimizationLevel.Debug; #if !DEBUG optimizationLevel = OptimizationLevel.Release; #endif CSharpCompilation compilation = CSharpCompilation.Create( assemblyName, syntaxTrees: encoded, references: new List <MetadataReference> { MetadataReference.CreateFromFile("ShaderLib.dll"), MetadataReference.CreateFromFile(systemAsm), MetadataReference.CreateFromFile(attributeAsm), MetadataReference.CreateFromFile(vectorAsm), MetadataReference.CreateFromFile(consoleAsm) }, options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary) .WithOptimizationLevel(optimizationLevel) .WithPlatform(Platform.AnyCpu) ); foreach (string item in references) { compilation = compilation.AddReferences(MetadataReference.CreateFromFile(item)); } using (MemoryStream assemblyStream = new MemoryStream()) using (MemoryStream symbolsStream = new MemoryStream()) { EmitOptions emitOptions = new EmitOptions( debugInformationFormat: DebugInformationFormat.PortablePdb, pdbFilePath: symbolsName); EmitResult result = compilation.Emit( peStream: assemblyStream, pdbStream: symbolsStream, embeddedTexts: embeddedTexts, options: emitOptions); if (!result.Success) { foreach (Diagnostic item in result.Diagnostics) { if (item.Severity == DiagnosticSeverity.Error) { Console.WriteLine(item); } } return(null); } assemblyStream.Seek(0, SeekOrigin.Begin); symbolsStream?.Seek(0, SeekOrigin.Begin); Assembly assembly = AssemblyLoadContext.Default.LoadFromStream(assemblyStream, symbolsStream); return(assembly); } }
internal static EmitOutput?EmitCompilationCore( Compilation compilation, IEnumerable <ResourceDescription> manifestResources, DiagnosticBag diagnostics, CompilationTestData testData, EmitOptions emitOptions ) { if (emitOptions is null) { emitOptions = EmitOptions.Default.WithDebugInformationFormat(DebugInformationFormat.Embedded); } using (var executableStream = new MemoryStream()) { var pdb = default(ImmutableArray <byte>); var assembly = default(ImmutableArray <byte>); var pdbStream = (emitOptions.DebugInformationFormat != DebugInformationFormat.Embedded) ? new MemoryStream() : null; var embeddedTexts = compilation.SyntaxTrees .Select(t => (filePath: t.FilePath, text: t.GetText())) .Where(t => t.text.CanBeEmbedded && !string.IsNullOrEmpty(t.filePath)) .Select(t => EmbeddedText.FromSource(t.filePath, t.text)) .ToImmutableArray(); EmitResult result; try { result = compilation.Emit( executableStream, metadataPEStream: null, pdbStream: pdbStream, xmlDocumentationStream: null, win32Resources: null, manifestResources: manifestResources, options: emitOptions, debugEntryPoint: null, sourceLinkStream: null, embeddedTexts, testData: testData, cancellationToken: default); } finally { if (pdbStream != null) { pdb = pdbStream.ToImmutable(); pdbStream.Dispose(); } } diagnostics.AddRange(result.Diagnostics); assembly = executableStream.ToImmutable(); if (result.Success) { return(new EmitOutput(assembly, pdb)); } return(null); } }
public static unsafe CompilationDiff Create( FileInfo originalBinaryPath, CompilationOptionsReader optionsReader, Compilation producedCompilation, IMethodSymbol?debugEntryPoint, ILogger logger, Options options) { using var rebuildPeStream = new MemoryStream(); // By default the Roslyn command line adds a resource that we need to replicate here. using var win32ResourceStream = producedCompilation.CreateDefaultWin32Resources( versionResource: true, noManifest: producedCompilation.Options.OutputKind == OutputKind.DynamicallyLinkedLibrary, manifestContents: null, iconInIcoFormat: null); var sourceLink = optionsReader.GetSourceLinkUTF8(); var emitResult = producedCompilation.Emit( peStream: rebuildPeStream, pdbStream: null, xmlDocumentationStream: null, win32Resources: win32ResourceStream, manifestResources: optionsReader.GetManifestResources(), options: new EmitOptions( debugInformationFormat: DebugInformationFormat.Embedded, highEntropyVirtualAddressSpace: true), debugEntryPoint: debugEntryPoint, metadataPEStream: null, pdbOptionsBlobReader: optionsReader.GetMetadataCompilationOptionsBlobReader(), sourceLinkStream: sourceLink != null ? new MemoryStream(sourceLink) : null, embeddedTexts: producedCompilation.SyntaxTrees .Select(st => (path: st.FilePath, text: st.GetText())) .Where(pair => pair.text.CanBeEmbedded) .Select(pair => EmbeddedText.FromSource(pair.path, pair.text)), cancellationToken: CancellationToken.None); if (!emitResult.Success) { using var diagsScope = logger.BeginScope($"Diagnostics"); foreach (var diag in emitResult.Diagnostics) { logger.LogError(diag.ToString()); } return(new CompilationDiff(emitResult.Diagnostics, originalBinaryPath.FullName)); } else { var originalBytes = File.ReadAllBytes(originalBinaryPath.FullName); var rebuildBytes = rebuildPeStream.ToArray(); var bytesEqual = originalBytes.SequenceEqual(rebuildBytes); if (!bytesEqual) { logger.LogError($"Rebuild of {originalBinaryPath.Name} was not equivalent to the original."); if (!options.Debug) { logger.LogInformation("Pass the --debug argument and re-run to write the visualization of the original and rebuild to disk."); } else { logger.LogInformation("Creating a diff..."); var debugPath = options.DebugPath; logger.LogInformation($@"Writing diffs to ""{Path.GetFullPath(debugPath)}"""); var assemblyName = Path.GetFileNameWithoutExtension(originalBinaryPath.Name); var assemblyDebugPath = Path.Combine(debugPath, assemblyName); var originalPath = Path.Combine(assemblyDebugPath, "original"); var rebuildPath = Path.Combine(assemblyDebugPath, "rebuild"); var sourcesPath = Path.Combine(assemblyDebugPath, "sources"); Directory.CreateDirectory(originalPath); Directory.CreateDirectory(rebuildPath); Directory.CreateDirectory(sourcesPath); // TODO: output source files should include the entire relative path instead of just the file name. foreach (var tree in producedCompilation.SyntaxTrees) { var sourceFilePath = Path.Combine(sourcesPath, Path.GetFileName(tree.FilePath)); using var file = File.OpenWrite(sourceFilePath); var writer = new StreamWriter(file); tree.GetText().Write(writer); writer.Flush(); } var originalAssemblyPath = Path.Combine(originalPath, originalBinaryPath.Name); File.WriteAllBytes(originalAssemblyPath, originalBytes); var rebuildAssemblyPath = Path.Combine(rebuildPath, originalBinaryPath.Name); File.WriteAllBytes(rebuildAssemblyPath, rebuildBytes); var originalPeMdvPath = Path.Combine(originalPath, assemblyName + ".pe.mdv"); var originalPdbMdvPath = Path.Combine(originalPath, assemblyName + ".pdb.mdv"); writeVisualization(originalPeMdvPath, optionsReader.PeReader.GetMetadataReader()); writeVisualization(originalPdbMdvPath, optionsReader.PdbReader); var rebuildPeMdvPath = Path.Combine(rebuildPath, assemblyName + ".pe.mdv"); var rebuildPdbMdvPath = Path.Combine(rebuildPath, assemblyName + ".pdb.mdv"); fixed(byte *ptr = rebuildBytes) { using var rebuildPeReader = new PEReader(ptr, rebuildBytes.Length); writeVisualization(rebuildPeMdvPath, rebuildPeReader.GetMetadataReader()); if (rebuildPeReader.TryOpenAssociatedPortablePdb( rebuildAssemblyPath, path => File.Exists(path) ? File.OpenRead(path) : null, out var provider, out _) && provider is { })
/// <summary>Compile a c# script.</summary> /// <param name="code">The c# code to compile.</param> /// <param name="model">The model owning the script.</param> /// <param name="referencedAssemblies">Optional referenced assemblies.</param> /// <returns>Compile errors or null if no errors.</returns> public Results Compile(string code, IModel model, IEnumerable <MetadataReference> referencedAssemblies = null) { string errors = null; if (code != null) { // See if we have compiled the code already. If so then no need to compile again. PreviousCompilation compilation = previousCompilations.Find(c => c.Code == code); bool newlyCompiled; if (compilation == null || compilation.Code != code) { newlyCompiled = true; bool withDebug = System.Diagnostics.Debugger.IsAttached; IEnumerable <MetadataReference> assemblies = GetReferenceAssemblies(referencedAssemblies, model.Name); // We haven't compiled the code so do it now. string sourceName; Compilation compiled = CompileTextToAssembly(code, assemblies, out sourceName); List <EmbeddedText> embeddedTexts = null; if (withDebug) { System.Text.Encoding encoding = System.Text.Encoding.UTF8; byte[] buffer = encoding.GetBytes(code); SourceText sourceText = SourceText.From(buffer, buffer.Length, encoding, canBeEmbedded: true); embeddedTexts = new List <EmbeddedText> { EmbeddedText.FromSource(sourceName, sourceText), }; } MemoryStream ms = new MemoryStream(); MemoryStream pdbStream = new MemoryStream(); { EmitResult emitResult = compiled.Emit( peStream: ms, pdbStream: withDebug ? pdbStream : null, embeddedTexts: embeddedTexts ); if (!emitResult.Success) { // Errors were found. Add then to the return error string. errors = null; foreach (Diagnostic diag in emitResult.Diagnostics) { if (diag.Severity == DiagnosticSeverity.Error) { errors += $"{diag.ToString()}{Environment.NewLine}"; } } // Because we have errors, remove the previous compilation if there is one. if (compilation != null) { previousCompilations.Remove(compilation); } compilation = null; } else { // No errors. // If we don't have a previous compilation, create one. if (compilation == null) { compilation = new PreviousCompilation() { ModelFullPath = model.FullPath }; previousCompilations.Add(compilation); } // Write the assembly to disk ms.Seek(0, SeekOrigin.Begin); string fileName = Path.Combine(Path.GetTempPath(), compiled.AssemblyName + ".dll"); using (FileStream file = new FileStream(fileName, FileMode.Create, FileAccess.Write)) ms.WriteTo(file); // Set the compilation properties. ms.Seek(0, SeekOrigin.Begin); pdbStream.Seek(0, SeekOrigin.Begin); compilation.Code = code; compilation.Reference = compiled.ToMetadataReference(); compilation.CompiledAssembly = System.Runtime.Loader.AssemblyLoadContext.Default.LoadFromStream(ms, pdbStream); } } } else { newlyCompiled = false; } if (compilation != null) { // We have a compiled assembly so get the class name. var regEx = new Regex(@"class\s+(\w+)\s"); var match = regEx.Match(code); if (!match.Success) { throw new Exception($"Cannot find a class declaration in script:{Environment.NewLine}{code}"); } var className = match.Groups[1].Value; // Create an instance of the class and give it to the model. var instanceType = compilation.CompiledAssembly.GetTypes().ToList().Find(t => t.Name == className); return(new Results(compilation.CompiledAssembly, instanceType.FullName, newlyCompiled)); } else { return(new Results(errors)); } } return(null); }
protected static Assembly?RunGeneratorAndGenerateAssembly( ISourceGenerator generator, string source, out ImmutableArray <Diagnostic> diagnostics, CSharpParseOptions?parseOptions = null, AnalyzerConfigOptions?configOptions = null, IEnumerable <MetadataReference>?additionalReferences = null, CSharpCompilationOptions?compilationOptions = null, EmitOptions?emitOptions = null, bool printDiagnostics = true, bool makeTestFailIfError = true) { if (generator is null) { throw new ArgumentNullException(nameof(generator)); } if (source is null) { throw new ArgumentNullException(nameof(source)); } parseOptions ??= CSharpParseOptions.Default .WithLanguageVersion(LanguageVersion.CSharp9); configOptions ??= TestAnalyzerConfigOptions.Empty; compilationOptions ??= new CSharpCompilationOptions( OutputKind.DynamicallyLinkedLibrary, nullableContextOptions: NullableContextOptions.Enable); emitOptions ??= new EmitOptions( debugInformationFormat: DebugInformationFormat.PortablePdb); var optionsProvider = new TestAnalyzerConfigOptionsProvider(configOptions); var driver = CSharpGeneratorDriver.Create( new[] { generator }, parseOptions: parseOptions, optionsProvider: optionsProvider); string assemblyName = Guid.NewGuid().ToString("D"); var syntaxTree = CSharpSyntaxTree.ParseText( source, parseOptions, "Main.cs", Encoding.UTF8); var references = new List <MetadataReference> { MetadataReference.CreateFromFile(typeof(object).Assembly.Location), MetadataReference.CreateFromFile(typeof(ITestHooks).Assembly.Location) }; if (additionalReferences is not null) { references.AddRange(additionalReferences); } var compilation = CSharpCompilation.Create( assemblyName, new[] { syntaxTree }, references, compilationOptions); var driver2 = driver.RunGeneratorsAndUpdateCompilation( compilation, out var outputCompilation, out _); var runResult = driver2.GetRunResult(); var exceptions = runResult.Results .Select(x => x.Exception) .Where(x => x is not null) .Select(x => x !) .ToArray(); var exception = exceptions.Length switch { 0 => null, 1 => exceptions[0], > 1 => new AggregateException(exceptions) }; if (exception is not null) { ExceptionDispatchInfo.Capture(exception).Throw(); } var embeddedTexts = outputCompilation.SyntaxTrees .Select(x => EmbeddedText.FromSource(x.FilePath, x.GetText())).ToArray(); using var peStream = new MemoryStream(); using var pdbStream = new MemoryStream(); var emitResult = outputCompilation.Emit( peStream, pdbStream, options: emitOptions, embeddedTexts: embeddedTexts); diagnostics = emitResult.Diagnostics; if (printDiagnostics) { foreach (var d in diagnostics .OrderByDescending(x => x.Severity)) { TestContext.WriteLine(d.ToString()); } } if (!emitResult.Success) { if (makeTestFailIfError) { Assert.Fail(); } return(null); } if (makeTestFailIfError) { if (diagnostics.Any(d => d.Severity == DiagnosticSeverity.Error)) { Assert.Fail(); return(null); } } peStream.Seek(0, SeekOrigin.Begin); pdbStream.Seek(0, SeekOrigin.Begin); var assembly = AssemblyLoadContext.Default.LoadFromStream( peStream, pdbStream); return(assembly); }
CodeCompilerResult CompileFileInternal( CodeCompilerArguments arguments, TextWriter log, CancellationToken token) { CSharpCommandLineArguments args = null; if (arguments.AdditionalArguments != null) { var splitArgs = CommandLineParser.SplitCommandLineIntoArguments(arguments.AdditionalArguments, false); if (splitArgs.Any()) { args = CSharpCommandLineParser.Default.Parse(splitArgs, arguments.TempDirectory, null, null); } } var references = new List <MetadataReference> (); foreach (var assemblyReference in AssemblyResolver.GetResolvedReferences(runtime, arguments.AssemblyReferences)) { references.Add(MetadataReference.CreateFromFile(assemblyReference)); } var parseOptions = args?.ParseOptions ?? new CSharpParseOptions(); if (arguments.LangVersion != null) { if (LanguageVersionFacts.TryParse(arguments.LangVersion, out var langVersion)) { parseOptions = parseOptions.WithLanguageVersion(langVersion); } else { throw new System.Exception($"Unknown value '{arguments.LangVersion}' for langversion"); } } else { // need to update this when updating referenced roslyn binaries CSharpLangVersionHelper.GetBestSupportedLangVersion(runtime, CSharpLangVersion.v9_0); } var syntaxTrees = new List <SyntaxTree> (); foreach (var sourceFile in arguments.SourceFiles) { using var stream = File.OpenRead(sourceFile); var sourceText = SourceText.From(stream, Encoding.UTF8, canBeEmbedded: true); SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(sourceText, parseOptions, cancellationToken: token, path: sourceFile); syntaxTrees.Add(syntaxTree); } var compilationOptions = (args?.CompilationOptions ?? new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)) .WithOutputKind(OutputKind.DynamicallyLinkedLibrary); var compilation = CSharpCompilation.Create( "GeneratedTextTransformation", syntaxTrees, references, compilationOptions ); EmitOptions emitOptions = args?.EmitOptions ?? new EmitOptions(); if (arguments.Debug) { var embeddedTexts = syntaxTrees.Select(st => EmbeddedText.FromSource(st.FilePath, st.GetText())).ToList(); emitOptions = emitOptions.WithDebugInformationFormat(DebugInformationFormat.Embedded); } using var fs = File.OpenWrite(arguments.OutputPath); EmitResult result = compilation.Emit(fs, options: emitOptions, cancellationToken: token); if (result.Success) { return(new CodeCompilerResult { Output = new List <string> (), Success = true, Errors = new List <CodeCompilerError> () }); } var failures = result.Diagnostics.Where(x => x.IsWarningAsError || x.Severity == DiagnosticSeverity.Error); var errors = failures.Select(x => { var location = x.Location.GetMappedLineSpan(); var startLinePosition = location.StartLinePosition; var endLinePosition = location.EndLinePosition; return(new CodeCompilerError { Message = x.GetMessage(), Column = startLinePosition.Character, Line = startLinePosition.Line, EndLine = endLinePosition.Line, EndColumn = endLinePosition.Character, IsError = x.Severity == DiagnosticSeverity.Error, Origin = location.Path }); }).ToList(); return(new CodeCompilerResult { Success = false, Output = new List <string> (), Errors = errors }); }
public Assembly CreateAssembly(string code) { var encoding = Encoding.UTF8; var assemblyName = Path.GetRandomFileName(); var symbolsName = Path.ChangeExtension(assemblyName, "pdb"); var sourceCodePath = "generated.cs"; var buffer = encoding.GetBytes(code); var sourceText = SourceText.From(buffer, buffer.Length, encoding, canBeEmbedded: true); var syntaxTree = CSharpSyntaxTree.ParseText( sourceText, new CSharpParseOptions(), path: sourceCodePath); var syntaxRootNode = syntaxTree.GetRoot() as CSharpSyntaxNode; var encoded = CSharpSyntaxTree.Create(syntaxRootNode, null, sourceCodePath, encoding); ReferenceAssemblyContainingType <object>(); ReferenceAssembly(typeof(Enumerable).GetTypeInfo().Assembly); var optimizationLevel = OptimizationLevel.Debug; CSharpCompilation compilation = CSharpCompilation.Create( assemblyName, syntaxTrees: new[] { encoded }, references: references, options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary) .WithOptimizationLevel(optimizationLevel) .WithPlatform(Platform.AnyCpu) ); using (var assemblyStream = new MemoryStream()) using (var symbolsStream = new MemoryStream()) { var emitOptions = new EmitOptions( debugInformationFormat: DebugInformationFormat.PortablePdb, pdbFilePath: symbolsName); var embeddedTexts = new List <EmbeddedText> { EmbeddedText.FromSource(sourceCodePath, sourceText), }; EmitResult result = compilation.Emit( peStream: assemblyStream, pdbStream: symbolsStream, embeddedTexts: embeddedTexts, options: emitOptions); if (!result.Success) { var errors = new List <string>(); IEnumerable <Diagnostic> failures = result.Diagnostics.Where(diagnostic => diagnostic.IsWarningAsError || diagnostic.Severity == DiagnosticSeverity.Error); foreach (Diagnostic diagnostic in failures) { errors.Add($"{diagnostic.Id}: {diagnostic.GetMessage()}"); } throw new Exception(String.Join("\n", errors)); } Console.WriteLine(code); assemblyStream.Seek(0, SeekOrigin.Begin); symbolsStream?.Seek(0, SeekOrigin.Begin); var assembly = AssemblyLoadContext.Default.LoadFromStream(assemblyStream, symbolsStream); return(assembly); } }
/// <summary> /// Compiles <paramref name="code"/> and creates script. /// </summary> /// <param name="options">Compilation options.</param> /// <param name="code">Code to be compiled.</param> /// <param name="builder">Assembly builder.</param> /// <param name="previousSubmissions">Enumeration of scripts that were evaluated within current context. New submission may reference them.</param> /// <returns>New script representing the compiled code.</returns> public static Script Create(Context.ScriptOptions options, string code, PhpCompilationFactory builder, IEnumerable <Script> previousSubmissions) { // use the language version of the requesting context var languageVersion = options.LanguageVersion; var shortOpenTags = false; var language = options.Context.TargetPhpLanguage; if (language != null) { shortOpenTags = language.ShortOpenTag; languageVersion ??= language.LanguageVersion; } // unique in-memory assembly name var name = builder.GetNewSubmissionName(); // submission do not have the opening "<?php" script tag: var kind = options.IsSubmission ? SourceCodeKind.Script : SourceCodeKind.Regular; if (kind == SourceCodeKind.Script && options.EmitDebugInformation) { // since submission do not have the opening "<?php" tag, // add a comment with the opening tag, so source code editors don't get confused and colorize the code properly: code = $"#<?php\n{code}"; } // parse the source code var tree = PhpSyntaxTree.ParseCode( SourceText.From(code, Encoding.UTF8, SourceHashAlgorithm.Sha256), new PhpParseOptions( kind: kind, languageVersion: languageVersion, shortOpenTags: shortOpenTags), PhpParseOptions.Default, options.IsSubmission ? BuildSubmissionFileName(options.Location.Path, name.Name) : options.Location.Path ); var diagnostics = tree.Diagnostics; if (!HasErrors(diagnostics)) { // TODO: collect required types from {tree}, remember as a script dependencies // TODO: perform class autoload (now before compilation, and then always before invocation) // list of scripts that were eval'ed in the context already, // our compilation may depend on them var dependingSubmissions = previousSubmissions.Where(s => !s.Image.IsDefaultOrEmpty); IEnumerable <MetadataReference> metadatareferences = dependingSubmissions.Select(s => MetadataReference.CreateFromImage(s.Image)); if (options.AdditionalReferences != null) { // add additional script references metadatareferences = metadatareferences.Concat(options.AdditionalReferences.Select(r => MetadataReference.CreateFromFile(r))); } // create the compilation object // TODO: add conditionally declared types into the compilation tables var compilation = (PhpCompilation)builder.CoreCompilation .WithLangVersion(languageVersion) .WithAssemblyName(name.Name) .AddSyntaxTrees(tree) .AddReferences(metadatareferences); var emitOptions = new EmitOptions(); var embeddedTexts = default(IEnumerable <EmbeddedText>); if (options.EmitDebugInformation) { compilation = compilation.WithPhpOptions(compilation.Options.WithOptimizationLevel(OptimizationLevel.Debug).WithDebugPlusMode(true)); emitOptions = emitOptions.WithDebugInformationFormat(DebugInformationFormat.PortablePdb); if (options.IsSubmission) { embeddedTexts = new[] { EmbeddedText.FromSource(tree.FilePath, tree.GetText()) }; } } else { compilation = compilation.WithPhpOptions(compilation.Options.WithOptimizationLevel(OptimizationLevel.Release)); } diagnostics = compilation.GetDeclarationDiagnostics(); if (!HasErrors(diagnostics)) { var peStream = new MemoryStream(); var pdbStream = options.EmitDebugInformation ? new MemoryStream() : null; var result = compilation.Emit(peStream, pdbStream: pdbStream, options: emitOptions, embeddedTexts: embeddedTexts ); if (result.Success) { return(new Script(name, peStream, pdbStream, builder, previousSubmissions)); } else { diagnostics = result.Diagnostics; } } } // return(CreateInvalid(diagnostics)); }
public override async Task <CodeCompilerResult> CompileFile( CodeCompilerArguments arguments, TextWriter log, CancellationToken token) { var references = new List <MetadataReference> (); foreach (var assemblyReference in arguments.AssemblyReferences) { var argumentsAssemblyReference = assemblyReference; var path = AssemblyResolver.Resolve(_runtime, argumentsAssemblyReference); references.Add(MetadataReference.CreateFromFile(path)); } references.Add(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); references.Add(MetadataReference.CreateFromFile(typeof(Enumerable).Assembly.Location)); references.Add(MetadataReference.CreateFromFile(typeof(string).Assembly.Location)); references.Add(MetadataReference.CreateFromFile(typeof(Console).Assembly.Location)); references.Add(MetadataReference.CreateFromFile(typeof(IntPtr).Assembly.Location)); references.Add(MetadataReference.CreateFromFile(typeof(AssemblyTargetedPatchBandAttribute).Assembly.Location)); references.Add(MetadataReference.CreateFromFile(Assembly.Load("netstandard, Version=2.0.0.0").Location)); var source = File.ReadAllText(arguments.SourceFiles.Single()); var syntaxTree = CSharpSyntaxTree.ParseText(source); var compilation = CSharpCompilation.Create( "GeneratedTextTransformation", new List <SyntaxTree> { syntaxTree }, references, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary) ); var pdbFilePath = Path.ChangeExtension(arguments.OutputPath, "pdb"); EmitResult result; using (var fs = File.OpenWrite(arguments.OutputPath)) { using (var symbolsStream = File.OpenWrite(pdbFilePath)) { var emitOptions = new EmitOptions( debugInformationFormat: DebugInformationFormat.PortablePdb, pdbFilePath: pdbFilePath); var embeddedTexts = new List <EmbeddedText> { EmbeddedText.FromSource( arguments.SourceFiles.Single(), SourceText.From(source, Encoding.UTF8)), }; result = compilation.Emit( fs, symbolsStream, embeddedTexts: embeddedTexts, options: emitOptions); } } if (result.Success) { return(new CodeCompilerResult { Output = new List <string> (), Success = true, Errors = new List <CodeCompilerError> () }); } var failures = result.Diagnostics.Where(x => x.IsWarningAsError || x.Severity == DiagnosticSeverity.Error); return(new CodeCompilerResult { Success = false, Output = new List <string> (), Errors = failures.Select( x => new CodeCompilerError { Message = x.GetMessage(), Column = x.Location.GetMappedLineSpan().StartLinePosition.Character, Line = x.Location.GetMappedLineSpan().StartLinePosition.Line, EndLine = x.Location.GetMappedLineSpan().EndLinePosition.Line, EndColumn = x.Location.GetMappedLineSpan().EndLinePosition.Character, IsError = x.IsWarningAsError, Origin = x.Location.GetMappedLineSpan().Path }).ToList(), }); }
public Assembly CreateAssembly() { var references = new HashSet <Assembly>(); references.UnionWith(from t in Translators from n in t.TypeNames select n.Key.Assembly); if (_options?.References != null) { references.UnionWith(_options.References); } references.Add(typeof(object).Assembly); #if NETSTANDARD2_0 references.Add(Assembly.Load(new AssemblyName("netstandard"))); references.Add(Assembly.Load(new AssemblyName("System.Runtime"))); references.Add(Assembly.Load(new AssemblyName("System.Collections"))); #endif var assemblyName = Path.GetRandomFileName(); var symbolsName = Path.ChangeExtension(assemblyName, "pdb"); var metadataReferences = references.Select(it => MetadataReference.CreateFromFile(it.Location)); var isRelease = _options?.IsRelease ?? !Debugger.IsAttached; CSharpCompilation compilation = CSharpCompilation.Create( assemblyName, _codes, metadataReferences, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, usings: new[] { "System" }) .WithOptimizationLevel(isRelease ? OptimizationLevel.Release : OptimizationLevel.Debug) .WithPlatform(Platform.AnyCpu) ); using var assemblyStream = new MemoryStream(); using var symbolsStream = new MemoryStream(); var emitOptions = new EmitOptions( debugInformationFormat: DebugInformationFormat.PortablePdb, pdbFilePath: symbolsName); var embeddedTexts = _codes.Select(it => EmbeddedText.FromSource(it.FilePath, it.GetText())); EmitResult result = compilation.Emit( peStream: assemblyStream, pdbStream: symbolsStream, embeddedTexts: embeddedTexts, options: emitOptions); if (!result.Success) { var errors = new List <string>(); IEnumerable <Diagnostic> failures = result.Diagnostics.Where(diagnostic => diagnostic.IsWarningAsError || diagnostic.Severity == DiagnosticSeverity.Error); foreach (Diagnostic diagnostic in failures) { errors.Add($"{diagnostic.Id}: {diagnostic.GetMessage()}"); } throw new InvalidOperationException(string.Join("\n", errors)); } assemblyStream.Seek(0, SeekOrigin.Begin); symbolsStream.Seek(0, SeekOrigin.Begin); #if NETSTANDARD2_0 return(System.Runtime.Loader.AssemblyLoadContext.Default.LoadFromStream(assemblyStream, symbolsStream)); #else return(Assembly.Load(assemblyStream.ToArray(), symbolsStream.ToArray())); #endif }
public override async Task <CodeCompilerResult> CompileFile( CodeCompilerArguments arguments, TextWriter log, CancellationToken token) { var references = new List <MetadataReference> (); foreach (var assemblyReference in AssemblyResolver.GetResolvedReferences(runtime, arguments.AssemblyReferences)) { references.Add(MetadataReference.CreateFromFile(assemblyReference)); try { Assembly.LoadFrom(assemblyReference); } catch (Exception) { } } var syntaxTrees = new List <SyntaxTree> (); foreach (var sourceFile in arguments.SourceFiles) { using var stream = File.OpenRead(sourceFile); var sourceText = SourceText.From(stream, Encoding.UTF8, canBeEmbedded: true); syntaxTrees.Add(CSharpSyntaxTree.ParseText(sourceText, path: sourceFile)); } var compilationoptions = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary); if (arguments.Debug) { compilationoptions = compilationoptions.WithOptimizationLevel(OptimizationLevel.Debug); } var compilation = CSharpCompilation.Create( "GeneratedTextTransformation", syntaxTrees, references, compilationoptions ); EmitOptions emitOptions = null; List <EmbeddedText> embeddedTexts = null; string pdbPath = null; if (arguments.Debug) { pdbPath = Path.ChangeExtension(arguments.OutputPath, "pdb"); embeddedTexts = syntaxTrees.Where(st => !string.IsNullOrEmpty(st.FilePath)).Select(st => EmbeddedText.FromSource(st.FilePath, st.GetText())).ToList(); emitOptions = new EmitOptions(debugInformationFormat: DebugInformationFormat.PortablePdb, pdbFilePath: pdbPath); } EmitResult result; using var fs = File.OpenWrite(arguments.OutputPath); { if (pdbPath != null) { using var pdb = File.OpenWrite(pdbPath); result = compilation.Emit(fs, pdbStream: pdb, options: emitOptions, embeddedTexts: embeddedTexts); } else { result = compilation.Emit(fs, options: emitOptions, embeddedTexts: embeddedTexts); } } if (result.Success) { return(new CodeCompilerResult { Output = new List <string> (), Success = true, Errors = new List <CodeCompilerError> () }); } var failures = result.Diagnostics.Where(x => x.IsWarningAsError || x.Severity == DiagnosticSeverity.Error); var errors = failures.Select(x => { var location = x.Location.GetMappedLineSpan(); var startLinePosition = location.StartLinePosition; var endLinePosition = location.EndLinePosition; return(new CodeCompilerError { Message = x.GetMessage(), Column = startLinePosition.Character, Line = startLinePosition.Line, EndLine = endLinePosition.Line, EndColumn = endLinePosition.Character, IsError = x.Severity == DiagnosticSeverity.Error, Origin = location.Path }); }).ToList(); return(new CodeCompilerResult { Success = false, Output = new List <string> (), Errors = errors }); }
private static void UseRoslyn() { string filename = Path.GetFullPath(@"..\..\..\..\Code.cs"); Console.WriteLine(filename); Encoding encoding = Encoding.UTF8; var buffer = encoding.GetBytes(File.ReadAllText(filename)); SourceText sourceText = SourceText.From(buffer, buffer.Length, encoding, canBeEmbedded: true); var tree = CSharpSyntaxTree.ParseText(sourceText, new CSharpParseOptions(), path: filename); var syntaxRootNode = tree.GetRoot() as CSharpSyntaxNode; var encoded = CSharpSyntaxTree.Create(syntaxRootNode, null, filename, encoding); string dllFileName = "generated.dll"; var pdbFileName = Path.GetFullPath(Path.ChangeExtension(dllFileName, "pdb")); var references = AppDomain.CurrentDomain.GetAssemblies() .Where(a => !a.IsDynamic && a.Location != string.Empty) .Select(a => MetadataReference.CreateFromFile(a.Location)); var compilation = CSharpCompilation.Create(dllFileName) .WithOptions( new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary) .WithOptimizationLevel(OptimizationLevel.Debug) .WithPlatform(Platform.AnyCpu)) .AddReferences(references) .AddSyntaxTrees(tree); var emitOptions = new EmitOptions( debugInformationFormat: DebugInformationFormat.PortablePdb, pdbFilePath: pdbFileName // runtimeMetadataVersion: "1.0" ); var embeddedTexts = new List <EmbeddedText> { EmbeddedText.FromSource(filename, sourceText), }; string path = Path.Combine(Directory.GetCurrentDirectory(), dllFileName); string pdbPath = Path.Combine(Directory.GetCurrentDirectory(), pdbFileName); using (Stream fsDll = File.OpenWrite(path)) using (Stream fsPdb = File.OpenWrite(pdbPath)) { EmitResult compilationResult = compilation.Emit( options: emitOptions, peStream: fsDll, pdbStream: fsPdb, embeddedTexts: embeddedTexts ); } Assembly asm = AssemblyLoadContext.Default.LoadFromAssemblyPath(path); asm.GetType("TestPlayground.TestClass").GetMethod("Run").Invoke(null, new object[] { }); }
public override async Task <CodeCompilerResult> CompileFile( CodeCompilerArguments arguments, TextWriter log, CancellationToken token) { var references = new List <MetadataReference> (); foreach (var assemblyReference in AssemblyResolver.GetResolvedReferences(runtime, arguments.AssemblyReferences)) { references.Add(MetadataReference.CreateFromFile(assemblyReference)); } var syntaxTrees = new List <SyntaxTree> (); foreach (var sourceFile in arguments.SourceFiles) { using var stream = File.OpenRead(sourceFile); var sourceText = SourceText.From(stream, Encoding.UTF8); syntaxTrees.Add(CSharpSyntaxTree.ParseText(sourceText)); } var compilation = CSharpCompilation.Create( "GeneratedTextTransformation", syntaxTrees, references, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary) ); EmitOptions emitOptions = null; if (arguments.Debug) { var embeddedTexts = syntaxTrees.Select(st => EmbeddedText.FromSource(st.FilePath, st.GetText())).ToList(); emitOptions = new EmitOptions(debugInformationFormat: DebugInformationFormat.Embedded); } using var fs = File.OpenWrite(arguments.OutputPath); EmitResult result = compilation.Emit(fs, options: emitOptions); if (result.Success) { return(new CodeCompilerResult { Output = new List <string> (), Success = true, Errors = new List <CodeCompilerError> () }); } var failures = result.Diagnostics.Where(x => x.IsWarningAsError || x.Severity == DiagnosticSeverity.Error); var errors = failures.Select(x => { var location = x.Location.GetMappedLineSpan(); var startLinePosition = location.StartLinePosition; var endLinePosition = location.EndLinePosition; return(new CodeCompilerError { Message = x.GetMessage(), Column = startLinePosition.Character, Line = startLinePosition.Line, EndLine = endLinePosition.Line, EndColumn = endLinePosition.Character, IsError = x.Severity == DiagnosticSeverity.Error, Origin = location.Path }); }).ToList(); return(new CodeCompilerResult { Success = false, Output = new List <string> (), Errors = errors }); }
public void StandalonePdb() { string source1 = @" using System; class C { public static void Main() { Console.WriteLine(); } } "; string source2 = @" // no code "; var tree1 = Parse(source1, "f:/build/goo.cs"); var tree2 = Parse(source2, "f:/build/nocode.cs"); var c = CreateStandardCompilation(new[] { tree1, tree2 }, options: TestOptions.DebugDll); var embeddedTexts = new[] { EmbeddedText.FromSource(tree1.FilePath, tree1.GetText()), EmbeddedText.FromSource(tree2.FilePath, tree2.GetText()) }; c.VerifyPdb(@" <symbols> <files> <file id=""1"" name=""f:/build/goo.cs"" language=""3f5162f8-07c6-11d3-9053-00c04fa302a1"" languageVendor=""994b45c4-e6e9-11d2-903f-00c04fa302a1"" documentType=""5a869d0b-6611-11d3-bd2a-0000f80849bd"" checkSumAlgorithmId=""ff1816ec-aa5e-4d10-87f7-6f4963833460"" checkSum=""5D, 7D, CF, 1B, 79, 12, E, A, 80, 13, E0, 98, 7E, 5C, AA, 3B, 63, D8, 7E, 4F, "" embeddedSourceLength=""98""><![CDATA[ using System; class C { public static void Main() { Console.WriteLine(); } } ]]></file> <file id=""2"" name=""f:/build/nocode.cs"" language=""3f5162f8-07c6-11d3-9053-00c04fa302a1"" languageVendor=""994b45c4-e6e9-11d2-903f-00c04fa302a1"" documentType=""5a869d0b-6611-11d3-bd2a-0000f80849bd"" checkSumAlgorithmId=""ff1816ec-aa5e-4d10-87f7-6f4963833460"" checkSum=""8B, 1D, 3F, 75, E0, A8, 8F, 90, B2, D3, 52, CF, 71, 9B, 17, 29, 3C, 70, 7A, 42, "" embeddedSourceLength=""21""><![CDATA[ // no code ]]></file> </files> <methods> <method containingType=""C"" name=""Main""> <customDebugInfo> <using> <namespace usingCount=""1"" /> </using> </customDebugInfo> <sequencePoints> <entry offset=""0x0"" startLine=""7"" startColumn=""5"" endLine=""7"" endColumn=""6"" document=""1"" /> <entry offset=""0x1"" startLine=""8"" startColumn=""9"" endLine=""8"" endColumn=""29"" document=""1"" /> <entry offset=""0x7"" startLine=""9"" startColumn=""5"" endLine=""9"" endColumn=""6"" document=""1"" /> </sequencePoints> <scope startOffset=""0x0"" endOffset=""0x8""> <namespace name=""System"" /> </scope> </method> </methods> </symbols> ", embeddedTexts); }