Ejemplo n.º 1
0
 IEnumerable <EmbeddedText> CollectAdditionalEmbeddedTexts()
 {
     return(this.SourceSymbolCollection
            .GetFiles()
            .Select(f => f.SyntaxTree)
            .Where(tree => tree.IsPharEntry || tree.FilePath.IsPharFile())
            .Select(tree => EmbeddedText.FromSource(tree.FilePath, tree.GetText()))
            .ToList());
 }
Ejemplo n.º 2
0
        public void FromStream_IOErrors()
        {
            Assert.Throws <IOException>(() => EmbeddedText.FromStream("path", new HugeStream()));
            Assert.Throws <EndOfStreamException>(() => EmbeddedText.FromStream("path", new TruncatingStream(10)));
            Assert.Throws <EndOfStreamException>(() => EmbeddedText.FromStream("path", new TruncatingStream(1000)));

            // Should be Assert.Throws<IOException>, but impeded by https://github.com/dotnet/roslyn/issues/12926
            Assert.Throws <IOException>(() => EmbeddedText.FromStream("path", new ReadFailsStream()));
        }
Ejemplo n.º 3
0
        public void FromBytes_Empty()
        {
            var text = EmbeddedText.FromBytes("pathToEmpty", new ArraySegment <byte>(new byte[0], 0, 0), SourceHashAlgorithm.Sha1);

            Assert.Equal("pathToEmpty", text.FilePath);
            Assert.Equal(text.ChecksumAlgorithm, SourceHashAlgorithm.Sha1);
            AssertEx.Equal(SourceText.CalculateChecksum(new byte[0], 0, 0, SourceHashAlgorithm.Sha1), text.Checksum);
            AssertEx.Equal(new byte[] { 0, 0, 0, 0 }, text.Blob);
        }
Ejemplo n.º 4
0
 public void FromStream_ArgumentErrors()
 {
     Assert.Throws <ArgumentNullException>("filePath", () => EmbeddedText.FromStream(null, null));
     Assert.Throws <ArgumentException>("filePath", () => EmbeddedText.FromStream("", null));
     Assert.Throws <ArgumentNullException>("stream", () => EmbeddedText.FromStream("path", null));
     Assert.Throws <ArgumentException>("stream", () => EmbeddedText.FromStream("path", new CannotReadStream()));
     Assert.Throws <ArgumentException>("stream", () => EmbeddedText.FromStream("path", new CannotSeekStream()));
     Assert.Throws <ArgumentException>("checksumAlgorithm", () => EmbeddedText.FromStream("path", new MemoryStream(), SourceHashAlgorithm.None));
 }
Ejemplo n.º 5
0
        public void FromBytes_EncodingFallbackCase()
        {
            var source = EncodedStringText.Create(new MemoryStream(new byte[] { 0xA9, 0x0D, 0x0A }), canBeEmbedded: true);
            var text   = EmbeddedText.FromSource("pathToLarge", source);

            Assert.Equal("pathToLarge", text.FilePath);
            Assert.Equal(SourceHashAlgorithm.Sha1, text.ChecksumAlgorithm);
            AssertEx.Equal(source.GetChecksum(), text.Checksum);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Constructs a <see cref="SourceText"/> from stream content.
        /// </summary>
        /// <param name="stream">Stream. The stream must be seekable.</param>
        /// <param name="encoding">
        /// Data encoding to use if the stream doesn't start with Byte Order Mark specifying the encoding.
        /// <see cref="Encoding.UTF8"/> if not specified.
        /// </param>
        /// <param name="checksumAlgorithm">
        /// Hash algorithm to use to calculate checksum of the text that's saved to PDB.
        /// </param>
        /// <param name="throwIfBinaryDetected">If the decoded text contains at least two consecutive NUL
        /// characters, then an <see cref="InvalidDataException"/> is thrown.</param>
        /// <param name="canBeEmbedded">True if the text can be passed to <see cref="EmbeddedText.FromSource"/> and be embedded in a PDB.</param>
        /// <exception cref="ArgumentNullException"><paramref name="stream"/> is null.</exception>
        /// <exception cref="ArgumentException">
        /// <paramref name="stream"/> doesn't support reading or seeking.
        /// <paramref name="checksumAlgorithm"/> is not supported.
        /// </exception>
        /// <exception cref="DecoderFallbackException">If the given encoding is set to use a throwing decoder as a fallback</exception>
        /// <exception cref="InvalidDataException">Two consecutive NUL characters were detected in the decoded text and <paramref name="throwIfBinaryDetected"/> was true.</exception>
        /// <exception cref="IOException">An I/O error occurs.</exception>
        /// <remarks>Reads from the beginning of the stream. Leaves the stream open.</remarks>
        public static SourceText From(
            Stream stream,
            Encoding?encoding = null,
            SourceHashAlgorithm checksumAlgorithm = SourceHashAlgorithm.Sha1,
            bool throwIfBinaryDetected            = false,
            bool canBeEmbedded = false
            )
        {
            if (stream == null)
            {
                throw new ArgumentNullException(nameof(stream));
            }

            if (!stream.CanRead)
            {
                throw new ArgumentException(
                          CodeAnalysisResources.StreamMustSupportReadAndSeek,
                          nameof(stream)
                          );
            }

            ValidateChecksumAlgorithm(checksumAlgorithm);

            encoding = encoding ?? s_utf8EncodingWithNoBOM;

            if (stream.CanSeek)
            {
                // If the resulting string would end up on the large object heap, then use LargeEncodedText.
                if (encoding.GetMaxCharCountOrThrowIfHuge(stream) >= LargeObjectHeapLimitInChars)
                {
                    return(LargeText.Decode(
                               stream,
                               encoding,
                               checksumAlgorithm,
                               throwIfBinaryDetected,
                               canBeEmbedded
                               ));
                }
            }

            string text = Decode(stream, encoding, out encoding);

            if (throwIfBinaryDetected && IsBinary(text))
            {
                throw new InvalidDataException();
            }

            // We must compute the checksum and embedded text blob now while we still have the original bytes in hand.
            // We cannot re-encode to obtain checksum and blob as the encoding is not guaranteed to round-trip.
            var checksum         = CalculateChecksum(stream, checksumAlgorithm);
            var embeddedTextBlob = canBeEmbedded
                ? EmbeddedText.CreateBlob(stream)
                : default(ImmutableArray <byte>);

            return(new StringText(text, encoding, checksum, checksumAlgorithm, embeddedTextBlob));
        }
Ejemplo n.º 7
0
        public void FromStream_Empty()
        {
            var text     = EmbeddedText.FromStream("pathToEmpty", new MemoryStream(new byte[0]), SourceHashAlgorithm.Sha1);
            var checksum = SourceText.CalculateChecksum(new byte[0], 0, 0, SourceHashAlgorithm.Sha1);

            Assert.Equal("pathToEmpty", text.FilePath);
            Assert.Equal(text.ChecksumAlgorithm, SourceHashAlgorithm.Sha1);
            AssertEx.Equal(checksum, text.Checksum);
            AssertEx.Equal(new byte[] { 0, 0, 0, 0 }, text.Blob);
        }
Ejemplo n.º 8
0
        public async Task BuildAndExecuteAsync(string code, OptimizationLevel?optimizationLevel, string codePath,
                                               bool onlyBuild = true)
        {
            await new NoContextYieldAwaitable();
            try
            {
                _running             = true;
                using var executeCts = new CancellationTokenSource();
                var cancellationToken = executeCts.Token;

                _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);

                if (diagnostics.Any(d => d.Severity == DiagnosticSeverity.Error))
                {
                    return;
                }

                _executeCts = executeCts;

                if (!onlyBuild)
                {
                    await RunProcess(_assemblyPath, cancellationToken);
                }
            }
            finally
            {
                _executeCts = null;
                _running    = false;

                if (_initializeBuildPathAfterRun)
                {
                    _initializeBuildPathAfterRun = false;
                    InitializeBuildPath(stop: false);
                }
            }
        }
Ejemplo n.º 9
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)));
        }
Ejemplo n.º 10
0
        public CompileResult Run(string sourceCodePath, string sourceCode, bool isReleaseBuild)
        {
            using var asmImage = new MemoryStream();

            var symbolsName = Path.ChangeExtension("compiled.dll", ".pdb");

            var buffer     = Encoding.UTF8.GetBytes(sourceCode);
            var sourceText = SourceText.From(buffer, buffer.Length, Encoding.UTF8, canBeEmbedded: true);

            var compilation = GenerateCode("compiled.dll", sourceText, sourceCodePath, isReleaseBuild);

            var emitOptions = new EmitOptions(
                debugInformationFormat: DebugInformationFormat.Embedded,
                pdbFilePath: symbolsName
                );

            var result = compilation.Emit(
                asmImage,
                embeddedTexts: new[] { EmbeddedText.FromSource(sourceCodePath, sourceText) },
                options: emitOptions);

            if (result.Success)
            {
                asmImage.Seek(0, SeekOrigin.Begin);

                return(new CompileResult(asmImage.ToArray(), Array.Empty <CompileResult.Message>()));
            }
            else
            {
                var messages = result.Diagnostics
                               .Where(x =>
                                      x.IsWarningAsError ||
                                      x.Severity == DiagnosticSeverity.Error)
                               .OrderBy(x => x.Location.SourceSpan.Start);

                return(new CompileResult(Array.Empty <byte>(),
                                         messages.Select(x =>
                {
                    var lineSpan = x.Location.GetMappedLineSpan().Span;

                    var startLine = lineSpan.Start.Line;
                    var startCharacter = lineSpan.Start.Character;
                    var endLine = lineSpan.End.Line;
                    var endCharacter = lineSpan.End.Character;
                    var severity = x.Severity.ToString().ToLower();

                    return new CompileResult.Message(
                        startLine, startCharacter,
                        endLine, endCharacter,
                        severity, x.Id, x.GetMessage()
                        );
                }).ToArray()));
            }
        }
Ejemplo n.º 11
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);
        }
Ejemplo n.º 12
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));
        }
Ejemplo n.º 13
0
        public Assembly CompileSourceCode(string path, string sourceCode, string dllName)
        {
            var wrapLog  = Log.Call($"Source code compilation: {dllName}.");
            var encoding = Encoding.UTF8;
            var pdbName  = $"{dllName}.pdb";

            using (var peStream = new MemoryStream())
                using (var pdbStream = new MemoryStream())
                {
                    var options = new EmitOptions(
                        debugInformationFormat: DebugInformationFormat.PortablePdb,
                        pdbFilePath: pdbName);

                    var buffer     = encoding.GetBytes(sourceCode);
                    var sourceText = SourceText.From(buffer, buffer.Length, encoding, canBeEmbedded: true);

                    var embeddedTexts = new List <EmbeddedText>
                    {
                        EmbeddedText.FromSource(path, sourceText),
                    };

                    var result = GenerateCode(path, sourceText, dllName).Emit(peStream,
                                                                              pdbStream,
                                                                              embeddedTexts: embeddedTexts,
                                                                              options: options);

                    if (!result.Success)
                    {
                        wrapLog("Compilation done with error.");

                        var errors = new List <string>();

                        var failures = result.Diagnostics.Where(diagnostic => diagnostic.IsWarningAsError || diagnostic.Severity == DiagnosticSeverity.Error);

                        foreach (var diagnostic in failures)
                        {
                            Log.Add("{0}: {1}", diagnostic.Id, diagnostic.GetMessage());
                            errors.Add($"{diagnostic.Id}: {diagnostic.GetMessage()}");
                        }

                        throw new Exception(String.Join("\n", errors));
                    }

                    wrapLog("Compilation done without any error.");

                    peStream.Seek(0, SeekOrigin.Begin);
                    pdbStream?.Seek(0, SeekOrigin.Begin);

                    var assemblyLoadContext = new SimpleUnloadableAssemblyLoadContext();
                    var assembly            = assemblyLoadContext.LoadFromStream(peStream, pdbStream);

                    return(assembly);
                }
        }
Ejemplo n.º 14
0
        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("f:/build/goo.cs", embeddedSource.FilePath);
                    Assert.Equal(source, embeddedSource.Text.ToString());
                }
            }
        }
Ejemplo n.º 15
0
        internal static SourceText Decode(
            Stream stream,
            Encoding encoding,
            SourceHashAlgorithm checksumAlgorithm,
            bool throwIfBinaryDetected,
            bool canBeEmbedded
            )
        {
            stream.Seek(0, SeekOrigin.Begin);

            long longLength = stream.Length;

            if (longLength == 0)
            {
                return(SourceText.From(string.Empty, encoding, checksumAlgorithm));
            }

            var maxCharRemainingGuess = encoding.GetMaxCharCountOrThrowIfHuge(stream);

            Debug.Assert(longLength > 0 && longLength <= int.MaxValue); // GetMaxCharCountOrThrowIfHuge should have thrown.
            int length = (int)longLength;

            using (
                var reader = new StreamReader(
                    stream,
                    encoding,
                    detectEncodingFromByteOrderMarks: true,
                    bufferSize: Math.Min(length, 4096),
                    leaveOpen: true
                    )
                )
            {
                var chunks = ReadChunksFromTextReader(
                    reader,
                    maxCharRemainingGuess,
                    throwIfBinaryDetected
                    );

                // We must compute the checksum and embedded text blob now while we still have the original bytes in hand.
                // We cannot re-encode to obtain checksum and blob as the encoding is not guaranteed to round-trip.
                var checksum         = CalculateChecksum(stream, checksumAlgorithm);
                var embeddedTextBlob = canBeEmbedded
                    ? EmbeddedText.CreateBlob(stream)
                    : default(ImmutableArray <byte>);
                return(new LargeText(
                           chunks,
                           reader.CurrentEncoding,
                           checksum,
                           checksumAlgorithm,
                           embeddedTextBlob
                           ));
            }
        }
Ejemplo n.º 16
0
        public void FromBytes_Large()
        {
            var bytes    = Encoding.Unicode.GetBytes(LargeSource);
            var checksum = SourceText.CalculateChecksum(bytes, 0, bytes.Length, SourceHashAlgorithm.Sha256);
            var text     = EmbeddedText.FromBytes("pathToLarge", new ArraySegment <byte>(bytes, 0, bytes.Length), SourceHashAlgorithm.Sha256);

            Assert.Equal("pathToLarge", text.FilePath);
            Assert.Equal(SourceHashAlgorithm.Sha256, text.ChecksumAlgorithm);
            AssertEx.Equal(checksum, text.Checksum);
            AssertEx.Equal(BitConverter.GetBytes(bytes.Length), text.Blob.Take(4));
            AssertEx.Equal(bytes, Decompress(text.Blob.Skip(4)));
        }
Ejemplo n.º 17
0
        public void FromBytes_Small()
        {
            var bytes    = Encoding.UTF8.GetBytes(SmallSource);
            var checksum = SourceText.CalculateChecksum(bytes, 0, bytes.Length, SourceHashAlgorithm.Sha1);
            var text     = EmbeddedText.FromBytes("pathToSmall", new ArraySegment <byte>(bytes, 0, bytes.Length));

            Assert.Equal("pathToSmall", text.FilePath);
            Assert.Equal(text.ChecksumAlgorithm, SourceHashAlgorithm.Sha1);
            AssertEx.Equal(checksum, text.Checksum);
            AssertEx.Equal(new byte[] { 0, 0, 0, 0 }, text.Blob.Take(4));
            AssertEx.Equal(bytes, text.Blob.Skip(4));
        }
Ejemplo n.º 18
0
        public void FromTextReader_Large()
        {
            var expected        = SourceText.From(LargeSource, Encoding.UTF8, SourceHashAlgorithm.Sha1);
            var expectedEmbeded = EmbeddedText.FromSource("pathToSmall", expected);

            var actual        = SourceText.From(new StringReader(LargeSource), LargeSource.Length, Encoding.UTF8, SourceHashAlgorithm.Sha1);
            var actualEmbeded = EmbeddedText.FromSource(expectedEmbeded.FilePath, actual);

            Assert.Equal(expectedEmbeded.FilePath, actualEmbeded.FilePath);
            Assert.Equal(expectedEmbeded.ChecksumAlgorithm, actualEmbeded.ChecksumAlgorithm);
            AssertEx.Equal(expectedEmbeded.Checksum, actualEmbeded.Checksum);
            AssertEx.Equal(expectedEmbeded.Blob, actualEmbeded.Blob);
        }
Ejemplo n.º 19
0
        IEnumerable <EmbeddedText> CollectAdditionalEmbeddedTexts()
        {
            // TODO: if (EmbedPharContentIntoPdb):

            foreach (var f in this.SourceSymbolCollection.GetFiles())
            {
                var tree = f.SyntaxTree;
                if (tree.IsPharEntry || tree.IsPharStub)
                {
                    yield return(EmbeddedText.FromSource(tree.GetDebugSourceDocumentPath(), tree.GetText()));
                }
            }
        }
Ejemplo n.º 20
0
 public void FromStream_IOErrors()
 {
     Assert.Throws <IOException>(() => EmbeddedText.FromStream("path", new HugeStream()));
     Assert.Throws <EndOfStreamException>(
         () => EmbeddedText.FromStream("path", new TruncatingStream(10))
         );
     Assert.Throws <EndOfStreamException>(
         () => EmbeddedText.FromStream("path", new TruncatingStream(1000))
         );
     Assert.Throws <IOException>(
         () => EmbeddedText.FromStream("path", new ReadFailsStream())
         );
 }
Ejemplo n.º 21
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)));
        }
Ejemplo n.º 22
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));
                }
            }
Ejemplo n.º 23
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);
        }
Ejemplo n.º 24
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));
        }
Ejemplo n.º 25
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);
            }
        }
Ejemplo n.º 26
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)));
            }
        }
Ejemplo n.º 27
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());
            }
        }
Ejemplo n.º 28
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));
        }
Ejemplo n.º 30
0
        /// <summary>
        /// Constructs a <see cref="SourceText"/> from a byte array.
        /// </summary>
        /// <param name="buffer">The encoded source buffer.</param>
        /// <param name="length">The number of bytes to read from the buffer.</param>
        /// <param name="encoding">
        /// Data encoding to use if the encoded buffer doesn't start with Byte Order Mark.
        /// <see cref="Encoding.UTF8"/> if not specified.
        /// </param>
        /// <param name="checksumAlgorithm">
        /// Hash algorithm to use to calculate checksum of the text that's saved to PDB.
        /// </param>
        /// <param name="throwIfBinaryDetected">If the decoded text contains at least two consecutive NUL
        /// characters, then an <see cref="InvalidDataException"/> is thrown.</param>
        /// <returns>The decoded text.</returns>
        /// <param name="canBeEmbedded">True if the text can be passed to <see cref="EmbeddedText.FromSource"/> and be embedded in a PDB.</param>
        /// <exception cref="ArgumentNullException">The <paramref name="buffer"/> is null.</exception>
        /// <exception cref="ArgumentOutOfRangeException">The <paramref name="length"/> is negative or longer than the <paramref name="buffer"/>.</exception>
        /// <exception cref="ArgumentException"><paramref name="checksumAlgorithm"/> is not supported.</exception>
        /// <exception cref="DecoderFallbackException">If the given encoding is set to use a throwing decoder as a fallback</exception>
        /// <exception cref="InvalidDataException">Two consecutive NUL characters were detected in the decoded text and <paramref name="throwIfBinaryDetected"/> was true.</exception>
        public static SourceText From(
            byte[] buffer,
            int length,
            Encoding?encoding = null,
            SourceHashAlgorithm checksumAlgorithm = SourceHashAlgorithm.Sha1,
            bool throwIfBinaryDetected            = false,
            bool canBeEmbedded = false
            )
        {
            if (buffer == null)
            {
                throw new ArgumentNullException(nameof(buffer));
            }

            if (length < 0 || length > buffer.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            ValidateChecksumAlgorithm(checksumAlgorithm);

            string text = Decode(buffer, length, encoding ?? s_utf8EncodingWithNoBOM, out encoding);

            if (throwIfBinaryDetected && IsBinary(text))
            {
                throw new InvalidDataException();
            }

            // We must compute the checksum and embedded text blob now while we still have the original bytes in hand.
            // We cannot re-encode to obtain checksum and blob as the encoding is not guaranteed to round-trip.
            var checksum         = CalculateChecksum(buffer, 0, length, checksumAlgorithm);
            var embeddedTextBlob = canBeEmbedded
                ? EmbeddedText.CreateBlob(new ArraySegment <byte>(buffer, 0, length))
                : default(ImmutableArray <byte>);

            return(new StringText(text, encoding, checksum, checksumAlgorithm, embeddedTextBlob));
        }