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(); }
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()); }
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(); }
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()); }
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); }