Esempio n. 1
0
        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)));
        }
Esempio n. 2
0
        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);
        }
Esempio n. 3
0
        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)
                );
        }
Esempio n. 4
0
            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));
                }
            }
Esempio n. 5
0
        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);
        }
Esempio n. 6
0
        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());
                }
            }
        }
Esempio n. 8
0
        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))
                );
        }
Esempio n. 9
0
        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);
            }
        }
Esempio n. 10
0
        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);
        }
Esempio n. 11
0
        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)));
            }
        }
Esempio n. 12
0
        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());
            }
        }
Esempio n. 13
0
        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);
        }
Esempio n. 16
0
        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);
        }
Esempio n. 17
0
        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);
                }
        }
Esempio n. 18
0
        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);
            }
        }
Esempio n. 19
0
        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 { })
Esempio n. 20
0
        /// <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);
        }
Esempio n. 22
0
        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
            });
        }
Esempio n. 23
0
        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);
                }
        }
Esempio n. 24
0
        /// <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));
        }
Esempio n. 25
0
        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
            });
        }
Esempio n. 28
0
        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[] { });
        }
Esempio n. 29
0
        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
            });
        }
Esempio n. 30
0
        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);
        }