Ejemplo n.º 1
0
        public void TopLevelStatements()
        {
            var original = CreateCompilation(
                @"System.Console.WriteLine(""I'm using top-level statements!"");",
                options: TestOptions.DebugExe
                );

            original.VerifyDiagnostics();

            var originalBytes = original.EmitToArray(
                new EmitOptions(debugInformationFormat: DebugInformationFormat.Embedded)
                );
            var originalPeReader  = new PEReader(originalBytes);
            var originalPdbReader = originalPeReader.GetEmbeddedPdbMetadataReader() !;
            var factory           = LoggerFactory.Create(configure => { });
            var logger            = factory.CreateLogger("Test");

            var optionsReader = new CompilationOptionsReader(
                logger,
                originalPdbReader,
                originalPeReader
                );
            var compilationFactory = CompilationFactory.Create("test.exe", optionsReader);

            var sources = original.SyntaxTrees
                          .Select(x => compilationFactory.CreateSyntaxTree(x.FilePath, x.GetText()))
                          .ToImmutableArray();
            var references = original.References.ToImmutableArray();
            var rebuild    = compilationFactory.CreateCompilation(
                sources,
                original.References.ToImmutableArray()
                );

            rebuild.VerifyEmitDiagnostics();
        }
Ejemplo n.º 2
0
        public static void VerifyRoundTrip(
            MemoryStream peStream,
            MemoryStream?pdbStream,
            string assemblyFileName,
            ImmutableArray <SyntaxTree> syntaxTrees,
            ImmutableArray <MetadataReference> metadataReferences,
            CancellationToken cancellationToken = default)
        {
            using var peReader = new PEReader(peStream);
            var embeddedPdbReader = peReader.GetEmbeddedPdbMetadataReader();
            var portablePdbReader = pdbStream is not null?MetadataReaderProvider.FromPortablePdbStream(pdbStream).GetMetadataReader() : null;

            Assert.True(embeddedPdbReader == null ^ portablePdbReader == null);

            var pdbReader     = embeddedPdbReader ?? portablePdbReader ?? throw ExceptionUtilities.Unreachable;
            var factory       = LoggerFactory.Create(configure => { });
            var logger        = factory.CreateLogger("RoundTripVerification");
            var optionsReader = new CompilationOptionsReader(logger, pdbReader, peReader);

            VerifyMetadataReferenceInfo(optionsReader, metadataReferences);

            var compilationFactory = CompilationFactory.Create(
                assemblyFileName,
                optionsReader);

            using var rebuildPeStream  = new MemoryStream();
            using var rebuildPdbStream = optionsReader.HasEmbeddedPdb ? null : new MemoryStream();
            var emitResult = compilationFactory.Emit(rebuildPeStream, rebuildPdbStream, syntaxTrees, metadataReferences, cancellationToken);

            Assert.True(emitResult.Success);
            Assert.Equal(peStream.ToArray(), rebuildPeStream.ToArray());
            Assert.Equal(pdbStream?.ToArray(), rebuildPdbStream?.ToArray());
        }
Ejemplo n.º 3
0
        public void TopLevelStatements()
        {
            const string path = "test";

            var original = CreateCompilation(
                @"System.Console.WriteLine(""I'm using top-level statements!"");",
                options: TestOptions.DebugExe);

            original.VerifyDiagnostics();

            var originalBytes = original.EmitToArray(new EmitOptions(debugInformationFormat: DebugInformationFormat.Embedded));
            var peReader      = new PEReader(originalBytes);

            Assert.True(peReader.TryOpenAssociatedPortablePdb(path, path => null, out var provider, out _));
            var pdbReader = provider !.GetMetadataReader();

            var factory = LoggerFactory.Create(configure => { });
            var logger  = factory.CreateLogger(path);
            var bc      = new BuildConstructor(logger);

            var optionsReader = new CompilationOptionsReader(logger, pdbReader, peReader);

            var sources = original.SyntaxTrees.Select(st =>
            {
                var text = st.GetText();
                return(new SyntaxTreeInfo(path, text));
            }).ToImmutableArray();
            var references  = original.References.ToImmutableArray();
            var compilation = bc.CreateCompilation("test.exe", optionsReader, sources, references);

            compilation.VerifyEmitDiagnostics();
        }
Ejemplo n.º 4
0
        public void Platform_RoundTrip_VB(Platform platform)
        {
            const string path = "test";

            var original = CreateVisualBasicCompilation(
                path,
                compilationOptions: new VisualBasicCompilationOptions(outputKind: OutputKind.ConsoleApplication, platform: platform),
                encoding: Encoding.UTF8,
                code: @"
Class C
    Shared Sub Main()
    End Sub
End Class");

            original.VerifyDiagnostics();

            var originalBytes = original.EmitToArray(new EmitOptions(debugInformationFormat: DebugInformationFormat.Embedded));
            var peReader      = new PEReader(originalBytes);

            Assert.True(peReader.TryOpenAssociatedPortablePdb(path, path => null, out var provider, out _));
            var pdbReader = provider !.GetMetadataReader();

            var factory = LoggerFactory.Create(configure => { });
            var logger  = factory.CreateLogger(path);
            // TODO: shouldn't need to pass a logger.
            var bc = new BuildConstructor(logger);

            var optionsReader = new CompilationOptionsReader(logger, pdbReader, peReader);

            var sources = original.SyntaxTrees.Select(st =>
            {
                var text = st.GetText();
                return(new ResolvedSource(OnDiskPath: null, text, new SourceFileInfo(path, text.ChecksumAlgorithm, text.GetChecksum().ToArray(), text, embeddedCompressedHash: null)));
            }).ToImmutableArray();
            var references = original.References.ToImmutableArray();

            var(compilation, isError) = bc.CreateCompilation(optionsReader, path, sources, references);

            Assert.False(isError);
            Assert.Equal(platform, compilation !.Options.Platform);

            // TODO: we should be able to get byte-for-byte equality here.
            // it will probably be necessary to expose some diagnostic facility in the Rebuild API to figure out what's wrong here.

            // using var rebuildStream = new MemoryStream();
            // var result = BuildConstructor.Emit(rebuildStream, new FileInfo(path), optionsReader, compilation, logger, CancellationToken.None);
            // Assert.Empty(result.Diagnostics);
            // Assert.True(result.Success);
            // Assert.Equal(originalBytes.ToArray(), rebuildStream.ToArray());
        }
        private static void VerifyRoundTrip <TCompilation>(TCompilation original)
            where TCompilation : Compilation
        {
            Assert.True(original.SyntaxTrees.All(x => !string.IsNullOrEmpty(x.FilePath)));
            Assert.True(original.Options.Deterministic);

            original.VerifyDiagnostics();
            var originalBytes     = original.EmitToArray(new EmitOptions(debugInformationFormat: DebugInformationFormat.Embedded));
            var originalReader    = new PEReader(originalBytes);
            var originalPdbReader = originalReader.GetEmbeddedPdbMetadataReader();

            var factory          = LoggerFactory.Create(configure => { });
            var logger           = factory.CreateLogger("RoundTripVerification");
            var buildConstructor = new BuildConstructor(logger);
            var optionsReader    = new CompilationOptionsReader(logger, originalPdbReader, originalReader);
            var assemblyFileName = original.AssemblyName !;

            if (typeof(TCompilation) == typeof(CSharpCompilation))
            {
                var assemblyFileExtension = original.Options.OutputKind switch
                {
                    OutputKind.DynamicallyLinkedLibrary => ".dll",
                    OutputKind.ConsoleApplication => ".exe",
                    _ => throw new InvalidOperationException(),
                };
                assemblyFileName += assemblyFileExtension;
            }

            var rebuild = buildConstructor.CreateCompilation(
                assemblyFileName,
                optionsReader,
                original.SyntaxTrees.Select(x => SyntaxTreeInfo.Create(x)).ToImmutableArray(),
                metadataReferences: original.References.ToImmutableArray());

            Assert.IsType <TCompilation>(rebuild);
            VerifyCompilationOptions(original.Options, rebuild.Options);

            using var rebuildStream = new MemoryStream();
            var result = BuildConstructor.Emit(
                rebuildStream,
                optionsReader,
                rebuild,
                embeddedTexts: ImmutableArray <EmbeddedText> .Empty,
                CancellationToken.None);

            Assert.Empty(result.Diagnostics);
            Assert.True(result.Success);
            Assert.Equal(originalBytes.ToArray(), rebuildStream.ToArray());
        }
Ejemplo n.º 6
0
        public static void VerifyMetadataReferenceInfo(CompilationOptionsReader optionsReader, ImmutableArray <MetadataReference> metadataReferences)
        {
            var count = 0;

            foreach (var info in optionsReader.GetMetadataReferences())
            {
                count++;
                var metadataReference = metadataReferences.FirstOrDefault(x =>
                                                                          info.Mvid == x.GetModuleVersionId() &&
                                                                          info.ExternAlias == GetSingleAlias(x));
                AssertEx.NotNull(metadataReference);

                string?GetSingleAlias(MetadataReference metadataReference)
                {
                    Assert.True(metadataReference.Properties.Aliases.Length is 0 or 1);
                    return(metadataReference.Properties.Aliases.Length == 1
                        ? metadataReference.Properties.Aliases[0]
                        : null);
                }
            }

            Assert.Equal(metadataReferences.Length, count);
        }