From 04a5c0dbda9597cedf0fed33a7a6aa95225e5202 Mon Sep 17 00:00:00 2001 From: Julien Couvreur Date: Fri, 3 Mar 2017 23:09:31 -0800 Subject: [PATCH 01/14] refonly and refout on command-line and msbuild --- .../Portable/CSharpResources.Designer.cs | 9 + .../CSharp/Portable/CSharpResources.resx | 3 + .../CommandLine/CSharpCommandLineParser.cs | 33 +++- .../Portable/Compilation/CSharpCompilation.cs | 2 - .../CSharp/Portable/Errors/ErrorCode.cs | 1 + .../Test/CommandLine/CommandLineTests.cs | 108 ++++++++++++ .../Test/Emit/Emit/CompilationEmitTests.cs | 92 +++++++++- .../Test/Emit/Emit/DeterministicTests.cs | 4 +- .../Core/MSBuildTask/ManagedCompiler.cs | 15 ++ .../Core/MSBuildTaskTests/CscTests.cs | 18 ++ .../Core/MSBuildTaskTests/VbcTests.cs | 18 ++ .../CommandLine/CommonCommandLineArguments.cs | 5 + .../Portable/CommandLine/CommonCompiler.cs | 164 +++++++++++++----- .../Core/Portable/GlobalSuppressions.cs | 2 + .../Core/Portable/PublicAPI.Unshipped.txt | 1 + .../VisualBasicCommandLineParser.vb | 29 +++- .../VisualBasic/Portable/Errors/Errors.vb | 1 + .../Portable/VBResources.Designer.vb | 9 + .../VisualBasic/Portable/VBResources.resx | 3 + .../Test/CommandLine/CommandLineTests.vb | 6 + .../Utilities/Portable/Assert/AssertEx.cs | 2 +- .../Portable/Metadata/MetadataReaderUtils.cs | 92 ++++++++++ 22 files changed, 558 insertions(+), 59 deletions(-) diff --git a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs index 92a0774c3d8fa..334e5df8f435f 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs +++ b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs @@ -6829,6 +6829,15 @@ internal static string ERR_NoPIANestedType { } } + /// + /// Looks up a localized string similar to Do not use refout when using refonly.. + /// + internal static string ERR_NoRefOutWhenRefOnly { + get { + return ResourceManager.GetString("ERR_NoRefOutWhenRefOnly", resourceCulture); + } + } + /// /// Looks up a localized string similar to '{0}': cannot override because '{1}' does not have an overridable set accessor. /// diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 4a782f374669a..d696a46fa4ab5 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -2288,6 +2288,9 @@ If such a class is used as a base class and if the deriving class defines a dest Merge conflict marker encountered + + Do not use refout when using refonly. + Overloadable operator expected diff --git a/src/Compilers/CSharp/Portable/CommandLine/CSharpCommandLineParser.cs b/src/Compilers/CSharp/Portable/CommandLine/CSharpCommandLineParser.cs index f83230991b3f1..14e62586d2199 100644 --- a/src/Compilers/CSharp/Portable/CommandLine/CSharpCommandLineParser.cs +++ b/src/Compilers/CSharp/Portable/CommandLine/CSharpCommandLineParser.cs @@ -67,6 +67,8 @@ internal sealed override CommandLineArguments CommonParse(IEnumerable ar string outputDirectory = baseDirectory; ImmutableArray> pathMap = ImmutableArray>.Empty; string outputFileName = null; + string outputRefFilePath = null; + bool metadataOnly = false; string documentationPath = null; string errorLogPath = null; bool parseDocumentationComments = false; //Don't just null check documentationFileName because we want to do this even if the file name is invalid. @@ -379,6 +381,7 @@ internal sealed override CommandLineArguments CommonParse(IEnumerable ar } continue; + case "out": if (string.IsNullOrWhiteSpace(value)) { @@ -391,6 +394,26 @@ internal sealed override CommandLineArguments CommonParse(IEnumerable ar continue; + case "refout": + value = RemoveQuotesAndSlashes(value); + if (string.IsNullOrEmpty(value)) + { + AddDiagnostic(diagnostics, ErrorCode.ERR_NoFileSpec, arg); + } + else + { + outputRefFilePath = ParseGenericPathToFile(value, diagnostics, baseDirectory); + } + + continue; + + case "refonly": + if (value != null) + break; + + metadataOnly = true; + continue; + case "t": case "target": if (value == null) @@ -1141,6 +1164,11 @@ internal sealed override CommandLineArguments CommonParse(IEnumerable ar diagnosticOptions[o.Key] = o.Value; } + if (metadataOnly && outputRefFilePath != null) + { + AddDiagnostic(diagnostics, diagnosticOptions, ErrorCode.ERR_NoRefOutWhenRefOnly); + } + if (!IsScriptRunner && !sourceFilesSpecified && (outputKind.IsNetModule() || !resourcesOrModulesSpecified)) { AddDiagnostic(diagnostics, diagnosticOptions, ErrorCode.WRN_NoSources); @@ -1257,7 +1285,7 @@ internal sealed override CommandLineArguments CommonParse(IEnumerable ar var emitOptions = new EmitOptions ( - metadataOnly: false, + metadataOnly: metadataOnly, debugInformationFormat: debugInformationFormat, pdbFilePath: null, // to be determined later outputNameOverride: null, // to be determined later @@ -1282,8 +1310,9 @@ internal sealed override CommandLineArguments CommonParse(IEnumerable ar Utf8Output = utf8output, CompilationName = compilationName, OutputFileName = outputFileName, + OutputRefFilePath = outputRefFilePath, PdbPath = pdbPath, - EmitPdb = emitPdb, + EmitPdb = emitPdb && !metadataOnly, SourceLink = sourceLink, OutputDirectory = outputDirectory, DocumentationPath = documentationPath, diff --git a/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs b/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs index f1c43315e2751..c6a3c6f9668f9 100644 --- a/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs +++ b/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs @@ -2358,8 +2358,6 @@ internal override bool GenerateResourcesAndDocumentationComments( DiagnosticBag diagnostics, CancellationToken cancellationToken) { - Debug.Assert(!moduleBuilder.EmitOptions.EmitMetadataOnly); - // Use a temporary bag so we don't have to refilter pre-existing diagnostics. var resourceDiagnostics = DiagnosticBag.GetInstance(); diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index 27c870578cf9c..fcf79b3f0f500 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -1460,5 +1460,6 @@ internal enum ErrorCode #endregion more stragglers for C# 7 ERR_Merge_conflict_marker_encountered = 8300, + ERR_NoRefOutWhenRefOnly = 8301, } } \ No newline at end of file diff --git a/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs b/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs index a698a74eb27f9..eb0b6bd31641e 100644 --- a/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs +++ b/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs @@ -2784,6 +2784,16 @@ public void ParseOut() // error CS2005: Missing file specification for '/out:' option Diagnostic(ErrorCode.ERR_NoFileSpec).WithArguments("/out:")); + parsedArgs = DefaultParse(new[] { @"/refout:", "a.cs" }, baseDirectory); + parsedArgs.Errors.Verify( + // error CS2005: Missing file specification for '/refout:' option + Diagnostic(ErrorCode.ERR_NoFileSpec).WithArguments("/refout:")); + + parsedArgs = DefaultParse(new[] { @"/refout:ref.dll", "/refonly", "a.cs" }, baseDirectory); + parsedArgs.Errors.Verify( + // error CS8301: Do not use refout when using refonly. + Diagnostic(ErrorCode.ERR_NoRefOutWhenRefOnly).WithLocation(1, 1)); + // Dev11 reports CS2007: Unrecognized option: '/out' parsedArgs = DefaultParse(new[] { @"/out", "a.cs" }, baseDirectory); parsedArgs.Errors.Verify( @@ -8845,6 +8855,104 @@ public void Version() } } + [Fact] + public void RefOut() + { + var dir = Temp.CreateDirectory(); + dir.CreateDirectory("ref"); + + var src = dir.CreateFile("a.cs"); + src.WriteAllText(@"class C { public static void Main() { } }"); + + var outWriter = new StringWriter(CultureInfo.InvariantCulture); + var csc = new MockCSharpCompiler(null, dir.Path, new[] { "/nologo", "/out:a.dll", "/refout:ref/a.dll", "/deterministic", "a.cs" }); + + int exitCode = csc.Run(outWriter); + Assert.Equal(0, exitCode); + + var refDll = Path.Combine(dir.Path, "ref\\a.dll"); + Assert.True(File.Exists(refDll)); + var refPeStream = File.OpenRead(refDll); + + using (var refPeReader = new PEReader(refPeStream)) + { + var metadataReader = refPeReader.GetMetadataReader(); + + // The types and members that are included needs further refinement. + // See issue https://github.com/dotnet/roslyn/issues/17612 + AssertEx.SetEqual(metadataReader.TypeDefinitions.Select(t => metadataReader.Dump(t)), + new[] { "TypeDef:", "TypeDef:C" }); + + AssertEx.SetEqual(metadataReader.MethodDefinitions.Select(t => metadataReader.Dump(t)), + new[] { "MethodDef: Void Main()", "MethodDef: Void .ctor()" }); + + // ReferenceAssemblyAttribute is missing. + // See issue https://github.com/dotnet/roslyn/issues/17612 + AssertEx.SetEqual( + metadataReader.CustomAttributes.Select(a => metadataReader.GetCustomAttribute(a).Constructor) + .Select(c => metadataReader.GetMemberReference((MemberReferenceHandle)c).Parent) + .Select(p => metadataReader.GetTypeReference((TypeReferenceHandle)p).Name) + .Select(n => metadataReader.GetString(n)), + new[] { "CompilationRelaxationsAttribute", "RuntimeCompatibilityAttribute", "DebuggableAttribute" }); + + // no method implementations + foreach (var typeDef in metadataReader.TypeDefinitions) + { + Assert.Equal(0, metadataReader.GetTypeDefinition(typeDef).GetMethodImplementations().Count()); + } + } + + // Clean up temp files + CleanupAllGeneratedFiles(dir.Path); + } + + [Fact] + public void RefOutWithError() + { + var dir = Temp.CreateDirectory(); + dir.CreateDirectory("ref"); + + var src = dir.CreateFile("a.cs"); + src.WriteAllText(@"class C { public static void Main() { error(); } }"); + + var outWriter = new StringWriter(CultureInfo.InvariantCulture); + var csc = new MockCSharpCompiler(null, dir.Path, new[] { "/nologo", "/out:a.dll", "/refout:ref/a.dll", "/deterministic", "a.cs" }); + int exitCode = csc.Run(outWriter); + Assert.Equal(1, exitCode); + + var dll = Path.Combine(dir.Path, "a.dll"); + Assert.False(File.Exists(dll)); + + var refDll = Path.Combine(dir.Path, "ref\\a.dll"); + Assert.True(File.Exists(refDll)); + + // Clean up temp files + CleanupAllGeneratedFiles(dir.Path); + } + + [Fact] + public void RefOnly() + { + var dir = Temp.CreateDirectory(); + + var src = dir.CreateFile("a.cs"); + src.WriteAllText(@"class C { public static void Main() { error(); } }"); // semantic error in method body + + var outWriter = new StringWriter(CultureInfo.InvariantCulture); + var csc = new MockCSharpCompiler(null, dir.Path, new[] { "/nologo", "/out:a.dll", "/refonly", "/debug", "/deterministic", "a.cs" }); + int exitCode = csc.Run(outWriter); + Assert.Equal(0, exitCode); + + var refDll = Path.Combine(dir.Path, "a.dll"); + Assert.True(File.Exists(refDll)); + + var pdb = Path.Combine(dir.Path, "a.pdb"); + Assert.False(File.Exists(pdb)); + + // Clean up temp files + CleanupAllGeneratedFiles(dir.Path); + } + public class QuotedArgumentTests { private void VerifyQuotedValid(string name, string value, T expected, Func getValue) diff --git a/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs b/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs index 222d01b278298..3f090cbe836bc 100644 --- a/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs +++ b/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs @@ -40,7 +40,7 @@ public void Main() EmitResult emitResult; using (var output = new MemoryStream()) { - emitResult = compilation.Emit(output, null, null, null); + emitResult = compilation.Emit(output, pdbStream: null, xmlDocumentationStream: null, win32Resources: null); } emitResult.Diagnostics.Verify( @@ -148,7 +148,7 @@ namespace N.Foo; EmitResult emitResult; using (var output = new MemoryStream()) { - emitResult = comp.Emit(output, null, null, null); + emitResult = comp.Emit(output, pdbStream: null, xmlDocumentationStream: null, win32Resources: null); } Assert.False(emitResult.Success); @@ -236,6 +236,84 @@ public static void Main() } } + [Theory, + InlineData("public int M() { return 1; }", "public int M() { return 2; }", true), + InlineData("public int M() { return 1; }", "public int M() { error(); }", true), + InlineData("", "private void M() { }", false), // Should be true. See follow-up issue https://github.com/dotnet/roslyn/issues/17612 + InlineData("internal void M() { }", "", false), + InlineData("public struct S { private int i; }", "public struct S { }", false)] + public void RefAssemblyChanges(string change1, string change2, bool expectMatch) + { + string sourceTemplate = @" +public class C +{ + CHANGE +} +"; + string name = GetUniqueName(); + string source1 = sourceTemplate.Replace("CHANGE", change1); + CSharpCompilation comp1 = CreateCompilationWithMscorlib(Parse(source1), + options: TestOptions.DebugDll.WithDeterministic(true), assemblyName: name); + + byte[] image1; + + using (var output = new MemoryStream()) + using (var pdbOutput = new MemoryStream()) + { + var emitResult = comp1.Emit(output, pdbOutput, options: EmitOptions.Default.WithEmitMetadataOnly(true)); + Assert.True(emitResult.Success); + emitResult.Diagnostics.Verify(); + image1 = output.ToArray(); + } + + var source2 = sourceTemplate.Replace("CHANGE", change2); + Compilation comp2 = CreateCompilationWithMscorlib(Parse(source2), + options: TestOptions.DebugDll.WithDeterministic(true), assemblyName: name); + + byte[] image2; + + using (var output = new MemoryStream()) + using (var pdbOutput = new MemoryStream()) + { + var emitResult = comp2.Emit(output, pdbOutput, options: EmitOptions.Default.WithEmitMetadataOnly(true)); + Assert.True(emitResult.Success); + emitResult.Diagnostics.Verify(); + image2 = output.ToArray(); + } + + Assert.True(AssertEx.SequenceEqual(image1, image2) == expectMatch); + } + + [Theory, + InlineData("public int M() { error(); }", true), + InlineData("public int M() { error() }", false), // Should be true. See follow-up issue https://github.com/dotnet/roslyn/issues/17612 + InlineData("public Error M() { return null; }", false), // Should be true. See follow-up issue https://github.com/dotnet/roslyn/issues/17612 + ] + public void RefAssemblyDiagnostics(string change, bool expectSuccess) + { + string sourceTemplate = @" +public class C +{ + CHANGE +} +"; + string source = sourceTemplate.Replace("CHANGE", change); + string name = GetUniqueName(); + CSharpCompilation comp1 = CreateCompilationWithMscorlib(Parse(source), + options: TestOptions.DebugDll.WithDeterministic(true), assemblyName: name); + + byte[] image; + + using (var output = new MemoryStream()) + using (var pdbOutput = new MemoryStream()) + { + var emitResult = comp1.Emit(output, pdbOutput, options: EmitOptions.Default.WithEmitMetadataOnly(true)); + Assert.Equal(expectSuccess, emitResult.Success); + Assert.Equal(!expectSuccess, emitResult.Diagnostics.Any()); + image = output.ToArray(); + } + } + /// /// Check that when we emit metadata only, we include metadata for /// compiler generate methods (e.g. the ones for implicit interface @@ -939,7 +1017,7 @@ public class Test EmitResult emitResult; using (var output = new MemoryStream()) { - emitResult = compilation.Emit(output, null, null, null); + emitResult = compilation.Emit(output, pdbStream: null, xmlDocumentationStream: null, win32Resources: null); } Assert.False(emitResult.Success); @@ -972,7 +1050,7 @@ public static void Main() EmitResult emitResult; using (var output = new MemoryStream()) { - emitResult = compilation.Emit(output, null, null, null); + emitResult = compilation.Emit(output, pdbStream: null, xmlDocumentationStream: null, win32Resources: null); } Assert.True(emitResult.Success); @@ -1010,7 +1088,7 @@ public static void Main() EmitResult emitResult; using (var output = new MemoryStream()) { - emitResult = compilation.Emit(output, null, null, null); + emitResult = compilation.Emit(output, pdbStream: null, xmlDocumentationStream: null, win32Resources: null); } Assert.True(emitResult.Success); @@ -2726,7 +2804,7 @@ public void BrokenPDBStream() var output = new MemoryStream(); var pdb = new BrokenStream(); pdb.BreakHow = BrokenStream.BreakHowType.ThrowOnSetLength; - var result = compilation.Emit(output, pdb); + var result = compilation.Emit(output, pdbStream: pdb); // error CS0041: Unexpected error writing debug information -- 'Exception from HRESULT: 0x806D0004' var err = result.Diagnostics.Single(); @@ -2737,7 +2815,7 @@ public void BrokenPDBStream() Assert.Equal(ioExceptionMessage, (string)err.Arguments[0]); pdb.Dispose(); - result = compilation.Emit(output, pdb); + result = compilation.Emit(output, pdbStream: pdb); // error CS0041: Unexpected error writing debug information -- 'Exception from HRESULT: 0x806D0004' err = result.Diagnostics.Single(); diff --git a/src/Compilers/CSharp/Test/Emit/Emit/DeterministicTests.cs b/src/Compilers/CSharp/Test/Emit/Emit/DeterministicTests.cs index 7af8a4edd7fee..12c92566cb4d3 100644 --- a/src/Compilers/CSharp/Test/Emit/Emit/DeterministicTests.cs +++ b/src/Compilers/CSharp/Test/Emit/Emit/DeterministicTests.cs @@ -66,8 +66,8 @@ public void BanVersionWildcards() references: new[] { MscorlibRef }, options: TestOptions.DebugDll.WithDeterministic(false)); - var resultDeterministic = compilationDeterministic.Emit(Stream.Null, Stream.Null); - var resultNonDeterministic = compilationNonDeterministic.Emit(Stream.Null, Stream.Null); + var resultDeterministic = compilationDeterministic.Emit(Stream.Null, pdbStream: Stream.Null); + var resultNonDeterministic = compilationNonDeterministic.Emit(Stream.Null, pdbStream: Stream.Null); Assert.False(resultDeterministic.Success); Assert.True(resultNonDeterministic.Success); diff --git a/src/Compilers/Core/MSBuildTask/ManagedCompiler.cs b/src/Compilers/Core/MSBuildTask/ManagedCompiler.cs index b137cf9c561e6..19a35ca4cb08a 100644 --- a/src/Compilers/Core/MSBuildTask/ManagedCompiler.cs +++ b/src/Compilers/Core/MSBuildTask/ManagedCompiler.cs @@ -227,6 +227,13 @@ public ITaskItem OutputAssembly get { return (ITaskItem)_store[nameof(OutputAssembly)]; } } + [Output] + public ITaskItem OutputRefAssembly + { + set { _store[nameof(OutputRefAssembly)] = value; } + get { return (ITaskItem)_store[nameof(OutputRefAssembly)]; } + } + public string Platform { set { _store[nameof(Platform)] = value; } @@ -251,6 +258,12 @@ public ITaskItem[] References get { return (ITaskItem[])_store[nameof(References)]; } } + public bool RefOnly + { + set { _store[nameof(RefOnly)] = value; } + get { return _store.GetOrDefault(nameof(RefOnly), false); } + } + public bool ReportAnalyzer { set { _store[nameof(ReportAnalyzer)] = value; } @@ -705,6 +718,8 @@ protected internal virtual void AddResponseFileCommands(CommandLineBuilderExtens commandLine.AppendPlusOrMinusSwitch("/optimize", _store, nameof(Optimize)); commandLine.AppendSwitchIfNotNull("/pathmap:", PathMap); commandLine.AppendSwitchIfNotNull("/out:", OutputAssembly); + commandLine.AppendSwitchIfNotNull("/outref:", OutputRefAssembly); + commandLine.AppendWhenTrue("/refonly", _store, nameof(RefOnly)); commandLine.AppendSwitchIfNotNull("/ruleset:", CodeAnalysisRuleSet); commandLine.AppendSwitchIfNotNull("/errorlog:", ErrorLog); commandLine.AppendSwitchIfNotNull("/subsystemversion:", SubsystemVersion); diff --git a/src/Compilers/Core/MSBuildTaskTests/CscTests.cs b/src/Compilers/Core/MSBuildTaskTests/CscTests.cs index 3f538e72d9d7e..d35b02527e48e 100644 --- a/src/Compilers/Core/MSBuildTaskTests/CscTests.cs +++ b/src/Compilers/Core/MSBuildTaskTests/CscTests.cs @@ -286,5 +286,23 @@ public void Embed() csc.EmbeddedFiles = MSBuildUtil.CreateTaskItems(); Assert.Equal(@"/debug:portable /out:test.exe test.cs", csc.GenerateResponseFileContents()); } + + [Fact] + public void RefOut() + { + var csc = new Csc(); + csc.Sources = MSBuildUtil.CreateTaskItems("test.cs"); + csc.OutputRefAssembly = MSBuildUtil.CreateTaskItem("ref\\test.dll"); + Assert.Equal("/out:test.exe /outref:ref\\test.dll test.cs", csc.GenerateResponseFileContents()); + } + + [Fact] + public void RefOnly() + { + var csc = new Csc(); + csc.Sources = MSBuildUtil.CreateTaskItems("test.cs"); + csc.RefOnly = true; + Assert.Equal("/out:test.exe /refonly test.cs", csc.GenerateResponseFileContents()); + } } } diff --git a/src/Compilers/Core/MSBuildTaskTests/VbcTests.cs b/src/Compilers/Core/MSBuildTaskTests/VbcTests.cs index 554cc2b11043e..91c4333271da3 100644 --- a/src/Compilers/Core/MSBuildTaskTests/VbcTests.cs +++ b/src/Compilers/Core/MSBuildTaskTests/VbcTests.cs @@ -283,5 +283,23 @@ public void Embed() vbc.EmbeddedFiles = MSBuildUtil.CreateTaskItems(); Assert.Equal(@"/optionstrict:custom /debug:portable /out:test.exe test.vb", vbc.GenerateResponseFileContents()); } + + [Fact] + public void RefOut() + { + var vbc = new Vbc(); + vbc.Sources = MSBuildUtil.CreateTaskItems("test.vb"); + vbc.OutputRefAssembly = MSBuildUtil.CreateTaskItem("ref\\test.dll"); + Assert.Equal("/optionstrict:custom /out:test.exe /outref:ref\\test.dll test.vb", vbc.GenerateResponseFileContents()); + } + + [Fact] + public void RefOnly() + { + var vbc = new Vbc(); + vbc.Sources = MSBuildUtil.CreateTaskItems("test.vb"); + vbc.RefOnly = true; + Assert.Equal("/optionstrict:custom /out:test.exe /refonly test.vb", vbc.GenerateResponseFileContents()); + } } } diff --git a/src/Compilers/Core/Portable/CommandLine/CommonCommandLineArguments.cs b/src/Compilers/Core/Portable/CommandLine/CommonCommandLineArguments.cs index 75c37feaf7c6e..ee5f34e2d4b71 100644 --- a/src/Compilers/Core/Portable/CommandLine/CommonCommandLineArguments.cs +++ b/src/Compilers/Core/Portable/CommandLine/CommonCommandLineArguments.cs @@ -85,6 +85,11 @@ public abstract class CommandLineArguments /// public string OutputFileName { get; internal set; } + /// + /// Path of the output ref assembly or null if not specified. + /// + public string OutputRefFilePath { get; internal set; } + /// /// Path of the PDB file or null if same as output binary path with .pdb extension. /// diff --git a/src/Compilers/Core/Portable/CommandLine/CommonCompiler.cs b/src/Compilers/Core/Portable/CommandLine/CommonCompiler.cs index 8aeb8b3515313..79dbabaec8b64 100644 --- a/src/Compilers/Core/Portable/CommandLine/CommonCompiler.cs +++ b/src/Compilers/Core/Portable/CommandLine/CommonCompiler.cs @@ -238,7 +238,7 @@ private static FileStream OpenFileForReadWithSmallBufferOptimization(string file // size, FileStream.Read still allocates the internal buffer. return new FileStream( filePath, - FileMode.Open, + FileMode.Open, FileAccess.Read, FileShare.ReadWrite, bufferSize: 1, @@ -546,7 +546,7 @@ internal int RunCore(TextWriter consoleOutput, ErrorLogger errorLogger, Cancella { return Failed; } - + bool reportAnalyzer = false; CancellationTokenSource analyzerCts = null; AnalyzerManager analyzerManager = null; @@ -628,6 +628,16 @@ internal int RunCore(TextWriter consoleOutput, ErrorLogger errorLogger, Cancella } } + string finalRefPeFilePath = Arguments.OutputRefFilePath; + if (finalRefPeFilePath != null) + { + if (!CompileAndEmitRefAssembly(compilation, emitOptions.WithEmitMetadataOnly(true), + finalRefPeFilePath, touchedFilesLogger, diagnosticBag, cancellationToken)) + { + return Failed; + } + } + var moduleBeingBuilt = compilation.CheckOptionsAndCreateModuleBuilder( diagnosticBag, Arguments.ManifestResources, @@ -803,48 +813,9 @@ internal int RunCore(TextWriter consoleOutput, ErrorLogger errorLogger, Cancella } cancellationToken.ThrowIfCancellationRequested(); - - if (Arguments.TouchedFilesPath != null) + if (!WriteTouchedFiles(consoleOutput, touchedFilesLogger, finalXmlFilePath)) { - Debug.Assert(touchedFilesLogger != null); - - if (finalXmlFilePath != null) - { - touchedFilesLogger.AddWritten(finalXmlFilePath); - } - - string readFilesPath = Arguments.TouchedFilesPath + ".read"; - string writtenFilesPath = Arguments.TouchedFilesPath + ".write"; - - var readStream = OpenFile(readFilesPath, consoleOutput, mode: FileMode.OpenOrCreate); - var writtenStream = OpenFile(writtenFilesPath, consoleOutput, mode: FileMode.OpenOrCreate); - - if (readStream == null || writtenStream == null) - { - return Failed; - } - - string filePath = null; - try - { - filePath = readFilesPath; - using (var writer = new StreamWriter(readStream)) - { - touchedFilesLogger.WriteReadPaths(writer); - } - - filePath = writtenFilesPath; - using (var writer = new StreamWriter(writtenStream)) - { - touchedFilesLogger.WriteWrittenPaths(writer); - } - } - catch (Exception e) - { - Debug.Assert(filePath != null); - MessageProvider.ReportStreamWriteException(e, filePath, consoleOutput); - return Failed; - } + return Failed; } } finally @@ -873,6 +844,113 @@ internal int RunCore(TextWriter consoleOutput, ErrorLogger errorLogger, Cancella return Succeeded; } + private bool CompileAndEmitRefAssembly(Compilation compilation, EmitOptions refEmitOptions, string finalRefPeFilePath, + TouchedFileLogger touchedFilesLogger, DiagnosticBag diagnosticBag, CancellationToken cancellationToken) + { + var refModuleBeingBuilt = compilation.CheckOptionsAndCreateModuleBuilder( + diagnosticBag, + Arguments.ManifestResources, + refEmitOptions, + debugEntryPoint: null, + sourceLinkStream: null, + embeddedTexts: null, + testData: null, + cancellationToken: cancellationToken); + + bool success = true; + if (refModuleBeingBuilt != null) + { + try + { + success = compilation.CompileMethods( + refModuleBeingBuilt, + emittingPdb: false, + diagnostics: diagnosticBag, + filterOpt: null, + cancellationToken: cancellationToken); + } + finally + { + refModuleBeingBuilt.CompilationFinished(); + } + + if (success) + { + var refPeStreamProvider = new CompilerEmitStreamProvider(this, finalRefPeFilePath); + + try + { + success = compilation.SerializeToPeStream( + refModuleBeingBuilt, + refPeStreamProvider, + pdbStreamProvider: null, + testSymWriterFactory: null, + diagnostics: diagnosticBag, + metadataOnly: true, + cancellationToken: cancellationToken); + } + finally + { + refPeStreamProvider.Close(diagnosticBag); + } + + if (success && touchedFilesLogger != null) + { + touchedFilesLogger.AddWritten(finalRefPeFilePath); + } + } + } + return success; + } + + private bool WriteTouchedFiles(TextWriter consoleOutput, TouchedFileLogger touchedFilesLogger, string finalXmlFilePath) + { + if (Arguments.TouchedFilesPath != null) + { + Debug.Assert(touchedFilesLogger != null); + + if (finalXmlFilePath != null) + { + touchedFilesLogger.AddWritten(finalXmlFilePath); + } + + string readFilesPath = Arguments.TouchedFilesPath + ".read"; + string writtenFilesPath = Arguments.TouchedFilesPath + ".write"; + + var readStream = OpenFile(readFilesPath, consoleOutput, mode: FileMode.OpenOrCreate); + var writtenStream = OpenFile(writtenFilesPath, consoleOutput, mode: FileMode.OpenOrCreate); + + if (readStream == null || writtenStream == null) + { + return false; + } + + string filePath = null; + try + { + filePath = readFilesPath; + using (var writer = new StreamWriter(readStream)) + { + touchedFilesLogger.WriteReadPaths(writer); + } + + filePath = writtenFilesPath; + using (var writer = new StreamWriter(writtenStream)) + { + touchedFilesLogger.WriteWrittenPaths(writer); + } + } + catch (Exception e) + { + Debug.Assert(filePath != null); + MessageProvider.ReportStreamWriteException(e, filePath, consoleOutput); + return false; + } + } + + return true; + } + protected virtual ImmutableArray ResolveAdditionalFilesFromArguments(List diagnostics, CommonMessageProvider messageProvider, TouchedFileLogger touchedFilesLogger) { var builder = ImmutableArray.CreateBuilder(); diff --git a/src/Compilers/Core/Portable/GlobalSuppressions.cs b/src/Compilers/Core/Portable/GlobalSuppressions.cs index e05dbf22d3d2a..e27d0752ba4d5 100644 --- a/src/Compilers/Core/Portable/GlobalSuppressions.cs +++ b/src/Compilers/Core/Portable/GlobalSuppressions.cs @@ -13,4 +13,6 @@ [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "", Scope = "member", Target = "~M:Microsoft.CodeAnalysis.Text.SourceText.From(System.Byte[],System.Int32,System.Text.Encoding,Microsoft.CodeAnalysis.Text.SourceHashAlgorithm,System.Boolean,System.Boolean)~Microsoft.CodeAnalysis.Text.SourceText")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "", Scope = "member", Target = "~M:Microsoft.CodeAnalysis.Text.SourceText.From(System.IO.TextReader,System.Int32,System.Text.Encoding,Microsoft.CodeAnalysis.Text.SourceHashAlgorithm)~Microsoft.CodeAnalysis.Text.SourceText")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0027:Public API with optional parameter(s) should have the most parameters amongst its public overloads.", Justification = "", Scope = "member", Target = "~M:Microsoft.CodeAnalysis.Text.SourceText.From(System.String,System.Text.Encoding,Microsoft.CodeAnalysis.Text.SourceHashAlgorithm)~Microsoft.CodeAnalysis.Text.SourceText")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "", Scope = "member", Target = "~M:Microsoft.CodeAnalysis.Compilation.Emit(System.IO.Stream,System.IO.Stream,System.IO.Stream,System.IO.Stream,System.Collections.Generic.IEnumerable{Microsoft.CodeAnalysis.ResourceDescription},Microsoft.CodeAnalysis.Emit.EmitOptions,Microsoft.CodeAnalysis.IMethodSymbol,System.IO.Stream,System.Collections.Generic.IEnumerable{Microsoft.CodeAnalysis.EmbeddedText},System.Threading.CancellationToken)~Microsoft.CodeAnalysis.Emit.EmitResult")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "", Scope = "member", Target = "~M:Microsoft.CodeAnalysis.Compilation.Emit(System.IO.Stream,System.IO.Stream,System.IO.Stream,System.IO.Stream,System.Collections.Generic.IEnumerable{Microsoft.CodeAnalysis.ResourceDescription},Microsoft.CodeAnalysis.Emit.EmitOptions,Microsoft.CodeAnalysis.IMethodSymbol,System.IO.Stream,System.Collections.Generic.IEnumerable{Microsoft.CodeAnalysis.EmbeddedText},System.IO.Stream,System.Threading.CancellationToken)~Microsoft.CodeAnalysis.Emit.EmitResult")] diff --git a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt index 04a4963d5f804..bd2a2e0940e6e 100644 --- a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt @@ -9,6 +9,7 @@ *REMOVED*static Microsoft.CodeAnalysis.Text.SourceText.From(byte[] buffer, int length, System.Text.Encoding encoding = null, Microsoft.CodeAnalysis.Text.SourceHashAlgorithm checksumAlgorithm = Microsoft.CodeAnalysis.Text.SourceHashAlgorithm.Sha1, bool throwIfBinaryDetected = false) -> Microsoft.CodeAnalysis.Text.SourceText Microsoft.CodeAnalysis.CommandLineArguments.DisplayVersion.get -> bool Microsoft.CodeAnalysis.CommandLineArguments.EmbeddedFiles.get -> System.Collections.Immutable.ImmutableArray +Microsoft.CodeAnalysis.CommandLineArguments.OutputRefFilePath.get -> string Microsoft.CodeAnalysis.CommandLineArguments.SourceLink.get -> string Microsoft.CodeAnalysis.Compilation.CreateAnonymousTypeSymbol(System.Collections.Immutable.ImmutableArray memberTypes, System.Collections.Immutable.ImmutableArray memberNames, System.Collections.Immutable.ImmutableArray memberIsReadOnly = default(System.Collections.Immutable.ImmutableArray), System.Collections.Immutable.ImmutableArray memberLocations = default(System.Collections.Immutable.ImmutableArray)) -> Microsoft.CodeAnalysis.INamedTypeSymbol Microsoft.CodeAnalysis.Compilation.CreateErrorNamespaceSymbol(Microsoft.CodeAnalysis.INamespaceSymbol container, string name) -> Microsoft.CodeAnalysis.INamespaceSymbol diff --git a/src/Compilers/VisualBasic/Portable/CommandLine/VisualBasicCommandLineParser.vb b/src/Compilers/VisualBasic/Portable/CommandLine/VisualBasicCommandLineParser.vb index 0ff31b101c10c..2872d0fb9e87e 100644 --- a/src/Compilers/VisualBasic/Portable/CommandLine/VisualBasicCommandLineParser.vb +++ b/src/Compilers/VisualBasic/Portable/CommandLine/VisualBasicCommandLineParser.vb @@ -96,6 +96,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Dim noStdLib As Boolean = False Dim utf8output As Boolean = False Dim outputFileName As String = Nothing + Dim outputRefFileName As String = Nothing + Dim metadataOnly As Boolean = False Dim outputDirectory As String = baseDirectory Dim documentationPath As String = Nothing Dim errorLogPath As String = Nothing @@ -455,6 +457,24 @@ Namespace Microsoft.CodeAnalysis.VisualBasic End If Continue For + Case "refout" + Dim unquoted = RemoveQuotesAndSlashes(value) + If String.IsNullOrEmpty(unquoted) Then + AddDiagnostic(diagnostics, ERRID.ERR_ArgumentRequired, name, ":") + Else + errorLogPath = ParseGenericPathToFile(unquoted, diagnostics, baseDirectory) + End If + Continue For + + Case "refonly", "refonly+" + If value IsNot Nothing Then + AddDiagnostic(diagnostics, ERRID.ERR_SwitchNeedsBool, "refonly") + End If + + metadataOnly = True + Continue For + + Case "t", "target" value = RemoveQuotesAndSlashes(value) outputKind = ParseTarget(name, value, diagnostics) @@ -1194,6 +1214,10 @@ lVbRuntimePlus: specificDiagnosticOptions(item.Key) = item.Value Next + If metadataOnly AndAlso outputRefFileName IsNot Nothing Then + AddDiagnostic(diagnostics, ERRID.ERR_NoRefOutWhenRefOnly) + End If + If Not IsScriptRunner AndAlso Not hasSourceFiles AndAlso managedResources.IsEmpty() Then ' VB displays help when there is nothing specified on the command line If flattenedArgs.Any Then @@ -1344,7 +1368,7 @@ lVbRuntimePlus: reportSuppressedDiagnostics:=reportSuppressedDiagnostics) Dim emitOptions = New EmitOptions( - metadataOnly:=False, + metadataOnly:=metadataOnly, debugInformationFormat:=debugInformationFormat, pdbFilePath:=Nothing, ' to be determined later outputNameOverride:=Nothing, ' to be determined later @@ -1376,6 +1400,7 @@ lVbRuntimePlus: .Utf8Output = utf8output, .CompilationName = compilationName, .OutputFileName = outputFileName, + .OutputRefFilePath = outputRefFileName, .OutputDirectory = outputDirectory, .DocumentationPath = documentationPath, .ErrorLogPath = errorLogPath, @@ -1403,7 +1428,7 @@ lVbRuntimePlus: .ScriptArguments = scriptArgs.AsImmutableOrEmpty(), .TouchedFilesPath = touchedFilesPath, .OutputLevel = outputLevel, - .EmitPdb = emitPdb, + .EmitPdb = emitPdb And Not metadataOnly, .SourceLink = sourceLink, .DefaultCoreLibraryReference = defaultCoreLibraryReference, .PreferredUILang = preferredUILang, diff --git a/src/Compilers/VisualBasic/Portable/Errors/Errors.vb b/src/Compilers/VisualBasic/Portable/Errors/Errors.vb index 1d21dcb6380ec..8a1590c3faa59 100644 --- a/src/Compilers/VisualBasic/Portable/Errors/Errors.vb +++ b/src/Compilers/VisualBasic/Portable/Errors/Errors.vb @@ -1725,6 +1725,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ERR_BadAssemblyName = 37283 ERR_Merge_conflict_marker_encountered = 37284 + ERR_NoRefOutWhenRefOnly = 37285 '// WARNINGS BEGIN HERE WRN_UseOfObsoleteSymbol2 = 40000 diff --git a/src/Compilers/VisualBasic/Portable/VBResources.Designer.vb b/src/Compilers/VisualBasic/Portable/VBResources.Designer.vb index d0a6f6a7876b2..1dd9a3c2313a4 100644 --- a/src/Compilers/VisualBasic/Portable/VBResources.Designer.vb +++ b/src/Compilers/VisualBasic/Portable/VBResources.Designer.vb @@ -8142,6 +8142,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic End Get End Property + ''' + ''' Looks up a localized string similar to Do not use refout when using refonly.. + ''' + Friend ReadOnly Property ERR_NoRefOutWhenRefOnly() As String + Get + Return ResourceManager.GetString("ERR_NoRefOutWhenRefOnly", resourceCulture) + End Get + End Property + ''' ''' Looks up a localized string similar to unable to open response file '{0}'. ''' diff --git a/src/Compilers/VisualBasic/Portable/VBResources.resx b/src/Compilers/VisualBasic/Portable/VBResources.resx index 766722e4338af..b24563d895c33 100644 --- a/src/Compilers/VisualBasic/Portable/VBResources.resx +++ b/src/Compilers/VisualBasic/Portable/VBResources.resx @@ -5467,4 +5467,7 @@ Merge conflict marker encountered + + Do not use refout when using refonly. + \ No newline at end of file diff --git a/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb b/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb index 7d1d9b1232cc1..525368ddf5b44 100644 --- a/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb +++ b/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb @@ -2901,6 +2901,12 @@ print Goodbye, World" parsedArgs = DefaultParse({"/OUT:", "a.vb"}, baseDirectory) parsedArgs.Errors.Verify(Diagnostic(ERRID.ERR_ArgumentRequired).WithArguments("out", ":")) + parsedArgs = DefaultParse({"/REFOUT:", "a.vb"}, baseDirectory) + parsedArgs.Errors.Verify(Diagnostic(ERRID.ERR_ArgumentRequired).WithArguments("refout", ":")) + + parsedArgs = DefaultParse({"/refout:ref.dll", "/refonly", "a.vb"}, baseDirectory) + parsedArgs.Errors.Verify(Diagnostic(ERRID.ERR_NoRefOutWhenRefOnly).WithLocation(1, 1)) + parsedArgs = DefaultParse({"/out+", "a.vb"}, baseDirectory) parsedArgs.Errors.Verify(Diagnostic(ERRID.WRN_BadSwitch).WithArguments("/out+")) ' TODO: Dev11 reports ERR_ArgumentRequired diff --git a/src/Test/Utilities/Portable/Assert/AssertEx.cs b/src/Test/Utilities/Portable/Assert/AssertEx.cs index 55f36d0a7b1bd..37256108733ae 100644 --- a/src/Test/Utilities/Portable/Assert/AssertEx.cs +++ b/src/Test/Utilities/Portable/Assert/AssertEx.cs @@ -210,7 +210,7 @@ public static void Equal(IEnumerable expected, IEnumerable actual, IEqu } } - private static bool SequenceEqual(IEnumerable expected, IEnumerable actual, IEqualityComparer comparer = null) + public static bool SequenceEqual(IEnumerable expected, IEnumerable actual, IEqualityComparer comparer = null) { var enumerator1 = expected.GetEnumerator(); var enumerator2 = actual.GetEnumerator(); diff --git a/src/Test/Utilities/Portable/Metadata/MetadataReaderUtils.cs b/src/Test/Utilities/Portable/Metadata/MetadataReaderUtils.cs index 025cf50f99b6d..5749417ce8617 100644 --- a/src/Test/Utilities/Portable/Metadata/MetadataReaderUtils.cs +++ b/src/Test/Utilities/Portable/Metadata/MetadataReaderUtils.cs @@ -265,9 +265,101 @@ public static string Dump(this MetadataReader reader, EntityHandle handle) { case HandleKind.AssemblyReference: return "AssemblyRef:" + reader.GetString(reader.GetAssemblyReference((AssemblyReferenceHandle)handle).Name); + case HandleKind.TypeDefinition: + return "TypeDef:" + reader.GetString(reader.GetTypeDefinition((TypeDefinitionHandle)handle).Name); + case HandleKind.MethodDefinition: + var method = reader.GetMethodDefinition((MethodDefinitionHandle)handle); + var blob = reader.GetBlobReader(method.Signature); + var decoder = new SignatureDecoder(ConstantSignatureVisualizer.Instance, reader, genericContext: null); + var signature = decoder.DecodeMethodSignature(ref blob); + var parameters = signature.ParameterTypes.Join(", "); + return $"MethodDef: {signature.ReturnType} {reader.GetString(method.Name)}({parameters})"; default: return handle.Kind.ToString(); } } + + // PROTOTYPE it would be better to shared the implementation with PdbToXml + private sealed class ConstantSignatureVisualizer : ISignatureTypeProvider + { + public static readonly ConstantSignatureVisualizer Instance = new ConstantSignatureVisualizer(); + + public string GetArrayType(string elementType, ArrayShape shape) + { + return elementType + "[" + new string(',', shape.Rank) + "]"; + } + + public string GetByReferenceType(string elementType) + { + return elementType + "&"; + } + + public string GetFunctionPointerType(MethodSignature signature) + { + // TODO: + return "method-ptr"; + } + + public string GetGenericInstantiation(string genericType, ImmutableArray typeArguments) + { + // using {} since the result is embedded in XML + return genericType + "{" + string.Join(", ", typeArguments) + "}"; + } + + public string GetGenericMethodParameter(object genericContext, int index) + { + return "!!" + index; + } + + public string GetGenericTypeParameter(object genericContext, int index) + { + return "!" + index; + } + + public string GetModifiedType(string modifier, string unmodifiedType, bool isRequired) + { + return (isRequired ? "modreq" : "modopt") + "(" + modifier + ") " + unmodifiedType; + } + + public string GetPinnedType(string elementType) + { + return "pinned " + elementType; + } + + public string GetPointerType(string elementType) + { + return elementType + "*"; + } + + public string GetPrimitiveType(PrimitiveTypeCode typeCode) + { + return typeCode.ToString(); + } + + public string GetSZArrayType(string elementType) + { + return elementType + "[]"; + } + + public string GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind) + { + var typeDef = reader.GetTypeDefinition(handle); + var name = reader.GetString(typeDef.Name); + return typeDef.Namespace.IsNil ? name : reader.GetString(typeDef.Namespace) + "." + name; + } + + public string GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind) + { + var typeRef = reader.GetTypeReference(handle); + var name = reader.GetString(typeRef.Name); + return typeRef.Namespace.IsNil ? name : reader.GetString(typeRef.Namespace) + "." + name; + } + + public string GetTypeFromSpecification(MetadataReader reader, object genericContext, TypeSpecificationHandle handle, byte rawTypeKind) + { + var sigReader = reader.GetBlobReader(reader.GetTypeSpecification(handle).Signature); + return new SignatureDecoder(Instance, reader, genericContext).DecodeType(ref sigReader); + } + } } } From 49a84f559de7a3f8014c7bf9c9d7f73b3bb25f06 Mon Sep 17 00:00:00 2001 From: Julien Couvreur Date: Thu, 9 Mar 2017 14:37:07 -0800 Subject: [PATCH 02/14] Getting ParseOut test passing again --- .../Portable/CommandLine/VisualBasicCommandLineParser.vb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compilers/VisualBasic/Portable/CommandLine/VisualBasicCommandLineParser.vb b/src/Compilers/VisualBasic/Portable/CommandLine/VisualBasicCommandLineParser.vb index 2872d0fb9e87e..7fb53e6ddaefb 100644 --- a/src/Compilers/VisualBasic/Portable/CommandLine/VisualBasicCommandLineParser.vb +++ b/src/Compilers/VisualBasic/Portable/CommandLine/VisualBasicCommandLineParser.vb @@ -462,7 +462,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic If String.IsNullOrEmpty(unquoted) Then AddDiagnostic(diagnostics, ERRID.ERR_ArgumentRequired, name, ":") Else - errorLogPath = ParseGenericPathToFile(unquoted, diagnostics, baseDirectory) + outputRefFileName = ParseGenericPathToFile(unquoted, diagnostics, baseDirectory) End If Continue For From 89aede67b5962cde470ed4af9074eb0b37c4d333 Mon Sep 17 00:00:00 2001 From: jcouv Date: Thu, 9 Mar 2017 22:20:33 -0800 Subject: [PATCH 03/14] Checking ref assembly via Symbol --- .../Test/Emit/Emit/CompilationEmitTests.cs | 38 +++++++++++++++++++ .../Portable/CommandLine/CommonCompiler.cs | 4 +- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs b/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs index 3f090cbe836bc..5d48df10a3124 100644 --- a/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs +++ b/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs @@ -314,6 +314,44 @@ public class C } } + [Fact] + public void VerifyRefAssembly() + { + string source = @" +public class PublicClass +{ + public void PublicMethod() { } + private void PrivateMethod() { } + protected void ProtectedMethod() { } + internal void InternalMethod() { } +} +"; + CSharpCompilation comp = CreateCompilation(source, references: new[] { MscorlibRef }, + options: TestOptions.DebugDll.WithDeterministic(true)); + + var emitRefOnly = EmitOptions.Default.WithEmitMetadataOnly(true); + + var verifier = CompileAndVerify(comp, emitOptions: emitRefOnly, verify: false); + Assert.True(verifier.TestData.Methods.IsEmpty); // no method bodies + + var image = comp.EmitToImageReference(emitRefOnly); + var comp2 = CreateCompilation("", references: new[] { MscorlibRef, image }, + options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All)); + AssemblySymbol assembly = comp2.SourceModule.GetReferencedAssemblySymbols().Last(); + var members = assembly.GlobalNamespace.GetMembers(); + AssertEx.SetEqual(members.Select(m => m.ToDisplayString()), + new[] { "", "PublicClass" }); + + AssertEx.SetEqual(((NamedTypeSymbol)assembly.GlobalNamespace.GetMember("PublicClass")).GetMembers().Select(m => m.ToTestDisplayString()), + new[] { "void PublicClass.PublicMethod()", "void PublicClass.PrivateMethod()", + "void PublicClass.InternalMethod()", "void PublicClass.ProtectedMethod()", "PublicClass..ctor()" }); + + AssertEx.SetEqual(assembly.GetAttributes().Select(a => a.AttributeClass.ToTestDisplayString()), + new[] { "System.Runtime.CompilerServices.CompilationRelaxationsAttribute", + "System.Runtime.CompilerServices.RuntimeCompatibilityAttribute", + "System.Diagnostics.DebuggableAttribute" }); + } + /// /// Check that when we emit metadata only, we include metadata for /// compiler generate methods (e.g. the ones for implicit interface diff --git a/src/Compilers/Core/Portable/CommandLine/CommonCompiler.cs b/src/Compilers/Core/Portable/CommandLine/CommonCompiler.cs index 79dbabaec8b64..46fa6717cc9dd 100644 --- a/src/Compilers/Core/Portable/CommandLine/CommonCompiler.cs +++ b/src/Compilers/Core/Portable/CommandLine/CommonCompiler.cs @@ -862,10 +862,12 @@ private bool CompileAndEmitRefAssembly(Compilation compilation, EmitOptions refE { try { + var diagnostics = DiagnosticBag.GetInstance(); + success = compilation.CompileMethods( refModuleBeingBuilt, emittingPdb: false, - diagnostics: diagnosticBag, + diagnostics: diagnostics, filterOpt: null, cancellationToken: cancellationToken); } From 1243e70487179321da00b5d5f47c1102314b6da3 Mon Sep 17 00:00:00 2001 From: Julien Couvreur Date: Fri, 10 Mar 2017 14:31:20 -0800 Subject: [PATCH 04/14] Changing back to producing two outputs from PeWriter --- .../Test/CommandLine/CommandLineTests.cs | 8 +- .../Test/Emit/Emit/CompilationEmitTests.cs | 2 +- .../CSharp/Test/Emit/PDB/PDBTests.cs | 3 + .../Portable/CommandLine/CommonCompiler.cs | 80 +++---------------- .../Core/Portable/Compilation/Compilation.cs | 62 ++++++++++++++ .../EditAndContinue/DeltaMetadataWriter.cs | 2 +- .../Portable/PEWriter/FullMetadataWriter.cs | 8 +- .../Core/Portable/PEWriter/MetadataWriter.cs | 10 +-- .../Core/Portable/PEWriter/PeWriter.cs | 55 ++++++++++++- .../Portable/PEWriter/ReferenceIndexer.cs | 2 +- .../Core/Portable/PublicAPI.Unshipped.txt | 3 +- .../ExpressionCompiler/EvaluationContext.cs | 6 +- .../ExpressionCompilerTestHelpers.cs | 2 +- .../ExpressionCompiler/EvaluationContext.vb | 6 +- .../Compilation/CompilationExtensions.cs | 1 + .../Compilation/IRuntimeEnvironment.cs | 1 + 16 files changed, 149 insertions(+), 102 deletions(-) diff --git a/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs b/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs index eb0b6bd31641e..e7cca10dc0470 100644 --- a/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs +++ b/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs @@ -8894,12 +8894,6 @@ public void RefOut() .Select(p => metadataReader.GetTypeReference((TypeReferenceHandle)p).Name) .Select(n => metadataReader.GetString(n)), new[] { "CompilationRelaxationsAttribute", "RuntimeCompatibilityAttribute", "DebuggableAttribute" }); - - // no method implementations - foreach (var typeDef in metadataReader.TypeDefinitions) - { - Assert.Equal(0, metadataReader.GetTypeDefinition(typeDef).GetMethodImplementations().Count()); - } } // Clean up temp files @@ -8924,7 +8918,7 @@ public void RefOutWithError() Assert.False(File.Exists(dll)); var refDll = Path.Combine(dir.Path, "ref\\a.dll"); - Assert.True(File.Exists(refDll)); + Assert.False(File.Exists(refDll)); // PROTOTYPE Should we produce ref assemblies on method body errors? // Clean up temp files CleanupAllGeneratedFiles(dir.Path); diff --git a/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs b/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs index 5d48df10a3124..3f39245c1f710 100644 --- a/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs +++ b/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs @@ -331,7 +331,7 @@ internal void InternalMethod() { } var emitRefOnly = EmitOptions.Default.WithEmitMetadataOnly(true); - var verifier = CompileAndVerify(comp, emitOptions: emitRefOnly, verify: false); + var verifier = CompileAndVerify(comp, emitOptions: emitRefOnly, verify: false); // PROTOTYPE(refout) PEVerify fails Assert.True(verifier.TestData.Methods.IsEmpty); // no method bodies var image = comp.EmitToImageReference(emitRefOnly); diff --git a/src/Compilers/CSharp/Test/Emit/PDB/PDBTests.cs b/src/Compilers/CSharp/Test/Emit/PDB/PDBTests.cs index a0fa5bba7f79f..97817fcf5278a 100644 --- a/src/Compilers/CSharp/Test/Emit/PDB/PDBTests.cs +++ b/src/Compilers/CSharp/Test/Emit/PDB/PDBTests.cs @@ -133,6 +133,7 @@ public void SymWriterErrors() { var result = compilation.Emit( peStream: peStream, + metadataPeStream: null, pdbStream: pdbStream, xmlDocumentationStream: null, cancellationToken: default(CancellationToken), @@ -166,6 +167,7 @@ public void SymWriterErrors2() { var result = compilation.Emit( peStream: peStream, + metadataPeStream: null, pdbStream: pdbStream, xmlDocumentationStream: null, cancellationToken: default(CancellationToken), @@ -199,6 +201,7 @@ public void SymWriterErrors3() { var result = compilation.Emit( peStream: peStream, + metadataPeStream: null, pdbStream: pdbStream, xmlDocumentationStream: null, cancellationToken: default(CancellationToken), diff --git a/src/Compilers/Core/Portable/CommandLine/CommonCompiler.cs b/src/Compilers/Core/Portable/CommandLine/CommonCompiler.cs index 46fa6717cc9dd..21702d732cdd5 100644 --- a/src/Compilers/Core/Portable/CommandLine/CommonCompiler.cs +++ b/src/Compilers/Core/Portable/CommandLine/CommonCompiler.cs @@ -628,16 +628,6 @@ internal int RunCore(TextWriter consoleOutput, ErrorLogger errorLogger, Cancella } } - string finalRefPeFilePath = Arguments.OutputRefFilePath; - if (finalRefPeFilePath != null) - { - if (!CompileAndEmitRefAssembly(compilation, emitOptions.WithEmitMetadataOnly(true), - finalRefPeFilePath, touchedFilesLogger, diagnosticBag, cancellationToken)) - { - return Failed; - } - } - var moduleBeingBuilt = compilation.CheckOptionsAndCreateModuleBuilder( diagnosticBag, Arguments.ManifestResources, @@ -746,11 +736,15 @@ internal int RunCore(TextWriter consoleOutput, ErrorLogger errorLogger, Cancella var peStreamProvider = new CompilerEmitStreamProvider(this, finalPeFilePath); var pdbStreamProviderOpt = emitPdbFile ? new CompilerEmitStreamProvider(this, finalPdbFilePath) : null; + string finalRefPeFilePath = Arguments.OutputRefFilePath; + var refPeStreamProviderOpt = finalRefPeFilePath != null ? new CompilerEmitStreamProvider(this, finalRefPeFilePath) : null; + try { success = compilation.SerializeToPeStream( moduleBeingBuilt, peStreamProvider, + refPeStreamProviderOpt, pdbStreamProviderOpt, testSymWriterFactory: null, diagnostics: diagnosticBag, @@ -760,6 +754,7 @@ internal int RunCore(TextWriter consoleOutput, ErrorLogger errorLogger, Cancella finally { peStreamProvider.Close(diagnosticBag); + refPeStreamProviderOpt?.Close(diagnosticBag); pdbStreamProviderOpt?.Close(diagnosticBag); } @@ -769,6 +764,10 @@ internal int RunCore(TextWriter consoleOutput, ErrorLogger errorLogger, Cancella { touchedFilesLogger.AddWritten(finalPdbFilePath); } + if (refPeStreamProviderOpt != null) + { + touchedFilesLogger.AddWritten(finalRefPeFilePath); + } touchedFilesLogger.AddWritten(finalPeFilePath); } } @@ -844,67 +843,6 @@ internal int RunCore(TextWriter consoleOutput, ErrorLogger errorLogger, Cancella return Succeeded; } - private bool CompileAndEmitRefAssembly(Compilation compilation, EmitOptions refEmitOptions, string finalRefPeFilePath, - TouchedFileLogger touchedFilesLogger, DiagnosticBag diagnosticBag, CancellationToken cancellationToken) - { - var refModuleBeingBuilt = compilation.CheckOptionsAndCreateModuleBuilder( - diagnosticBag, - Arguments.ManifestResources, - refEmitOptions, - debugEntryPoint: null, - sourceLinkStream: null, - embeddedTexts: null, - testData: null, - cancellationToken: cancellationToken); - - bool success = true; - if (refModuleBeingBuilt != null) - { - try - { - var diagnostics = DiagnosticBag.GetInstance(); - - success = compilation.CompileMethods( - refModuleBeingBuilt, - emittingPdb: false, - diagnostics: diagnostics, - filterOpt: null, - cancellationToken: cancellationToken); - } - finally - { - refModuleBeingBuilt.CompilationFinished(); - } - - if (success) - { - var refPeStreamProvider = new CompilerEmitStreamProvider(this, finalRefPeFilePath); - - try - { - success = compilation.SerializeToPeStream( - refModuleBeingBuilt, - refPeStreamProvider, - pdbStreamProvider: null, - testSymWriterFactory: null, - diagnostics: diagnosticBag, - metadataOnly: true, - cancellationToken: cancellationToken); - } - finally - { - refPeStreamProvider.Close(diagnosticBag); - } - - if (success && touchedFilesLogger != null) - { - touchedFilesLogger.AddWritten(finalRefPeFilePath); - } - } - } - return success; - } - private bool WriteTouchedFiles(TextWriter consoleOutput, TouchedFileLogger touchedFilesLogger, string finalXmlFilePath) { if (Arguments.TouchedFilesPath != null) diff --git a/src/Compilers/Core/Portable/Compilation/Compilation.cs b/src/Compilers/Core/Portable/Compilation/Compilation.cs index 4eeb2bfd0298b..0c12327dff12c 100644 --- a/src/Compilers/Core/Portable/Compilation/Compilation.cs +++ b/src/Compilers/Core/Portable/Compilation/Compilation.cs @@ -1964,10 +1964,38 @@ public EmitResult Emit( cancellationToken); } + // 2.0 BACKCOMPAT OVERLOAD -- DO NOT TOUCH + public EmitResult Emit( + Stream peStream, + Stream pdbStream, + Stream xmlDocumentationStream, + Stream win32Resources, + IEnumerable manifestResources, + EmitOptions options, + IMethodSymbol debugEntryPoint, + Stream sourceLinkStream, + IEnumerable embeddedTexts, + CancellationToken cancellationToken) + { + return Emit( + peStream, + pdbStream, + xmlDocumentationStream, + win32Resources, + manifestResources, + options, + debugEntryPoint, + sourceLinkStream, + embeddedTexts, + metadataPeStream: null, + cancellationToken: cancellationToken); + } + /// /// Emit the IL for the compiled source code into the specified stream. /// /// Stream to which the compilation will be written. + /// Stream to which the metadata-only output will be written. /// Stream to which the compilation's debug info will be written. Null to forego PDB generation. /// Stream to which the compilation's XML documentation will be written. Null to forego XML generation. /// Stream from which the compilation's Win32 resources will be read (in RES format). @@ -2008,6 +2036,7 @@ public EmitResult Emit( IMethodSymbol debugEntryPoint = null, Stream sourceLinkStream = null, IEnumerable embeddedTexts = null, + Stream metadataPeStream = null, CancellationToken cancellationToken = default(CancellationToken)) { if (peStream == null) @@ -2033,6 +2062,11 @@ public EmitResult Emit( } } + if (metadataPeStream != null && options.EmitMetadataOnly) + { + throw new ArgumentException(CodeAnalysisResources.StreamMustSupportWrite, nameof(metadataPeStream)); // PROTOTYPE(refout) fix error message and add test + } + if (win32Resources != null) { if (!win32Resources.CanRead || !win32Resources.CanSeek) @@ -2055,6 +2089,7 @@ public EmitResult Emit( throw new ArgumentException(CodeAnalysisResources.StreamMustSupportRead, nameof(sourceLinkStream)); } } + if (embeddedTexts != null && !embeddedTexts.IsEmpty()) { if (options == null || @@ -2067,6 +2102,7 @@ public EmitResult Emit( return Emit( peStream, + metadataPeStream, pdbStream, xmlDocumentationStream, win32Resources, @@ -2085,6 +2121,7 @@ public EmitResult Emit( /// internal EmitResult Emit( Stream peStream, + Stream metadataPeStream, Stream pdbStream, Stream xmlDocumentationStream, Stream win32Resources, @@ -2152,6 +2189,7 @@ internal EmitResult Emit( success = SerializeToPeStream( moduleBeingBuilt, new SimpleEmitStreamProvider(peStream), + (metadataPeStream != null) ? new SimpleEmitStreamProvider(metadataPeStream) : null, (pdbStream != null) ? new SimpleEmitStreamProvider(pdbStream) : null, testData?.SymWriterFactory, diagnostics, @@ -2318,6 +2356,7 @@ internal CommonPEModuleBuilder CheckOptionsAndCreateModuleBuilder( internal bool SerializeToPeStream( CommonPEModuleBuilder moduleBeingBuilt, EmitStreamProvider peStreamProvider, + EmitStreamProvider metadataPeStreamProvider, EmitStreamProvider pdbStreamProvider, Func testSymWriterFactory, DiagnosticBag diagnostics, @@ -2331,6 +2370,7 @@ internal bool SerializeToPeStream( DiagnosticBag metadataDiagnostics = null; DiagnosticBag pdbBag = null; Stream peStream = null; + Stream refPeStream = null; Stream portablePdbStream = null; bool deterministic = IsEmitDeterministic; @@ -2429,12 +2469,33 @@ internal bool SerializeToPeStream( return retStream; }; + Func getRefPeStream; + if (metadataPeStreamProvider != null) + { + getRefPeStream = () => + { + if (metadataDiagnostics.HasAnyErrors()) + { + return null; + } + + refPeStream = metadataPeStreamProvider.GetOrCreateStream(metadataDiagnostics); + Debug.Assert(refPeStream != null || metadataDiagnostics.HasAnyErrors()); + return refPeStream; + }; + } + else + { + getRefPeStream = null; + } + try { if (Cci.PeWriter.WritePeToStream( new EmitContext(moduleBeingBuilt, null, metadataDiagnostics), this.MessageProvider, getPeStream, + getRefPeStream, getPortablePdbStream, nativePdbWriter, pePdbPath, @@ -2506,6 +2567,7 @@ internal bool SerializeToPeStream( { nativePdbWriter?.Dispose(); signingInputStream?.Dispose(); + refPeStream?.Dispose(); pdbBag?.Free(); metadataDiagnostics?.Free(); } diff --git a/src/Compilers/Core/Portable/Emit/EditAndContinue/DeltaMetadataWriter.cs b/src/Compilers/Core/Portable/Emit/EditAndContinue/DeltaMetadataWriter.cs index 8cc8d4d317326..7c8b2fdb0ec67 100644 --- a/src/Compilers/Core/Portable/Emit/EditAndContinue/DeltaMetadataWriter.cs +++ b/src/Compilers/Core/Portable/Emit/EditAndContinue/DeltaMetadataWriter.cs @@ -55,7 +55,7 @@ public DeltaMetadataWriter( dynamicAnalysisDataWriterOpt: null, context: context, messageProvider: messageProvider, - allowMissingMethodBodies: false, + metadataOnly: false, deterministic: false, cancellationToken: cancellationToken) { diff --git a/src/Compilers/Core/Portable/PEWriter/FullMetadataWriter.cs b/src/Compilers/Core/Portable/PEWriter/FullMetadataWriter.cs index ddca0955c2b60..47e8694c2b927 100644 --- a/src/Compilers/Core/Portable/PEWriter/FullMetadataWriter.cs +++ b/src/Compilers/Core/Portable/PEWriter/FullMetadataWriter.cs @@ -37,7 +37,7 @@ internal sealed class FullMetadataWriter : MetadataWriter public static MetadataWriter Create( EmitContext context, CommonMessageProvider messageProvider, - bool allowMissingMethodBodies, + bool metadataOnly, bool deterministic, bool hasPdbStream, CancellationToken cancellationToken) @@ -63,7 +63,7 @@ public static MetadataWriter Create( new DynamicAnalysisDataWriter(context.Module.DebugDocumentCount, context.Module.HintNumberOfMethodDefinitions) : null; - return new FullMetadataWriter(context, builder, debugBuilderOpt, dynamicAnalysisDataWriterOpt, messageProvider, allowMissingMethodBodies, deterministic, cancellationToken); + return new FullMetadataWriter(context, builder, debugBuilderOpt, dynamicAnalysisDataWriterOpt, messageProvider, metadataOnly, deterministic, cancellationToken); } private FullMetadataWriter( @@ -72,10 +72,10 @@ private FullMetadataWriter( MetadataBuilder debugBuilderOpt, DynamicAnalysisDataWriter dynamicAnalysisDataWriterOpt, CommonMessageProvider messageProvider, - bool allowMissingMethodBodies, + bool metadataOnly, bool deterministic, CancellationToken cancellationToken) - : base(builder, debugBuilderOpt, dynamicAnalysisDataWriterOpt, context, messageProvider, allowMissingMethodBodies, deterministic, cancellationToken) + : base(builder, debugBuilderOpt, dynamicAnalysisDataWriterOpt, context, messageProvider, metadataOnly, deterministic, cancellationToken) { // EDMAURER make some intelligent guesses for the initial sizes of these things. int numMethods = this.module.HintNumberOfMethodDefinitions; diff --git a/src/Compilers/Core/Portable/PEWriter/MetadataWriter.cs b/src/Compilers/Core/Portable/PEWriter/MetadataWriter.cs index c65fe050a3595..d863e34c21229 100644 --- a/src/Compilers/Core/Portable/PEWriter/MetadataWriter.cs +++ b/src/Compilers/Core/Portable/PEWriter/MetadataWriter.cs @@ -65,8 +65,7 @@ internal abstract partial class MetadataWriter private readonly int _numTypeDefsEstimate; private readonly bool _deterministic; - // If true, it is allowed to have methods not have bodies (for emitting metadata-only assembly) - internal readonly bool allowMissingMethodBodies; + internal readonly bool metadataOnly; // A map of method body before token translation to RVA. Used for deduplication of small bodies. private readonly Dictionary, int> _smallMethodBodies; @@ -77,13 +76,13 @@ protected MetadataWriter( DynamicAnalysisDataWriter dynamicAnalysisDataWriterOpt, EmitContext context, CommonMessageProvider messageProvider, - bool allowMissingMethodBodies, + bool metadataOnly, bool deterministic, CancellationToken cancellationToken) { this.module = context.Module; _deterministic = deterministic; - this.allowMissingMethodBodies = allowMissingMethodBodies; + this.metadataOnly = metadataOnly; // EDMAURER provide some reasonable size estimates for these that will avoid // much of the reallocation that would occur when growing these from empty. @@ -2829,10 +2828,9 @@ private int[] SerializeMethodBodies(BlobBuilder ilBuilder, PdbWriter nativePdbWr IMethodBody body; StandaloneSignatureHandle localSignatureHandleOpt; - if (method.HasBody()) + if (method.HasBody() && !metadataOnly) { body = method.GetBody(Context); - Debug.Assert(body != null || allowMissingMethodBodies); if (body != null) { diff --git a/src/Compilers/Core/Portable/PEWriter/PeWriter.cs b/src/Compilers/Core/Portable/PEWriter/PeWriter.cs index b2d4a571f38ac..ab65cf637ea89 100644 --- a/src/Compilers/Core/Portable/PEWriter/PeWriter.cs +++ b/src/Compilers/Core/Portable/PEWriter/PeWriter.cs @@ -26,21 +26,70 @@ public PeWritingException(Exception inner) internal static class PeWriter { - public static bool WritePeToStream( + internal static bool WritePeToStream( + EmitContext context, + CommonMessageProvider messageProvider, + Func getPeStream, + Func getMetadataPeStreamOpt, + Func getPortablePdbStreamOpt, + PdbWriter nativePdbWriterOpt, + string pdbPathOpt, + bool metadataOnly, + bool isDeterministic, + CancellationToken cancellationToken) + { + if (!WritePeToStream( + context, + messageProvider, + getPeStream, + getPortablePdbStreamOpt, + nativePdbWriterOpt, + pdbPathOpt, + metadataOnly, + isDeterministic, + cancellationToken)) + { + return false; + } + + // produce the secondary output (ref assembly) if needed + if (getMetadataPeStreamOpt != null) + { + Debug.Assert(!metadataOnly); + + if (!WritePeToStream( + context, + messageProvider, + getMetadataPeStreamOpt, + getPortablePdbStreamOpt: null, + nativePdbWriterOpt: null, + pdbPathOpt: null, + metadataOnly: true, + isDeterministic: isDeterministic, + cancellationToken: cancellationToken)) + { + return false; + } + } + + return true; + } + + internal static bool WritePeToStream( EmitContext context, CommonMessageProvider messageProvider, Func getPeStream, Func getPortablePdbStreamOpt, PdbWriter nativePdbWriterOpt, string pdbPathOpt, - bool allowMissingMethodBodies, + bool metadataOnly, bool isDeterministic, CancellationToken cancellationToken) { // If PDB writer is given, we have to have PDB path. Debug.Assert(nativePdbWriterOpt == null || pdbPathOpt != null); - var mdWriter = FullMetadataWriter.Create(context, messageProvider, allowMissingMethodBodies, isDeterministic, getPortablePdbStreamOpt != null, cancellationToken); + var mdWriter = FullMetadataWriter.Create(context, messageProvider, metadataOnly, isDeterministic, getPortablePdbStreamOpt != null, cancellationToken); var properties = context.Module.SerializationProperties; diff --git a/src/Compilers/Core/Portable/PEWriter/ReferenceIndexer.cs b/src/Compilers/Core/Portable/PEWriter/ReferenceIndexer.cs index 8e4b4e3c166ff..e748b6398d1e1 100644 --- a/src/Compilers/Core/Portable/PEWriter/ReferenceIndexer.cs +++ b/src/Compilers/Core/Portable/PEWriter/ReferenceIndexer.cs @@ -119,7 +119,7 @@ protected override void ProcessMethodBody(IMethodDefinition method) } } } - else if (!metadataWriter.allowMissingMethodBodies) + else if (!metadataWriter.metadataOnly) { throw ExceptionUtilities.Unreachable; } diff --git a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt index bd2a2e0940e6e..8e0ebfab4b46c 100644 --- a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt @@ -15,7 +15,8 @@ Microsoft.CodeAnalysis.Compilation.CreateAnonymousTypeSymbol(System.Collections. Microsoft.CodeAnalysis.Compilation.CreateErrorNamespaceSymbol(Microsoft.CodeAnalysis.INamespaceSymbol container, string name) -> Microsoft.CodeAnalysis.INamespaceSymbol Microsoft.CodeAnalysis.Compilation.CreateTupleTypeSymbol(Microsoft.CodeAnalysis.INamedTypeSymbol underlyingType, System.Collections.Immutable.ImmutableArray elementNames = default(System.Collections.Immutable.ImmutableArray), System.Collections.Immutable.ImmutableArray elementLocations = default(System.Collections.Immutable.ImmutableArray)) -> Microsoft.CodeAnalysis.INamedTypeSymbol Microsoft.CodeAnalysis.Compilation.CreateTupleTypeSymbol(System.Collections.Immutable.ImmutableArray elementTypes, System.Collections.Immutable.ImmutableArray elementNames = default(System.Collections.Immutable.ImmutableArray), System.Collections.Immutable.ImmutableArray elementLocations = default(System.Collections.Immutable.ImmutableArray)) -> Microsoft.CodeAnalysis.INamedTypeSymbol -Microsoft.CodeAnalysis.Compilation.Emit(System.IO.Stream peStream, System.IO.Stream pdbStream = null, System.IO.Stream xmlDocumentationStream = null, System.IO.Stream win32Resources = null, System.Collections.Generic.IEnumerable manifestResources = null, Microsoft.CodeAnalysis.Emit.EmitOptions options = null, Microsoft.CodeAnalysis.IMethodSymbol debugEntryPoint = null, System.IO.Stream sourceLinkStream = null, System.Collections.Generic.IEnumerable embeddedTexts = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> Microsoft.CodeAnalysis.Emit.EmitResult +Microsoft.CodeAnalysis.Compilation.Emit(System.IO.Stream peStream, System.IO.Stream pdbStream = null, System.IO.Stream xmlDocumentationStream = null, System.IO.Stream win32Resources = null, System.Collections.Generic.IEnumerable manifestResources = null, Microsoft.CodeAnalysis.Emit.EmitOptions options = null, Microsoft.CodeAnalysis.IMethodSymbol debugEntryPoint = null, System.IO.Stream sourceLinkStream = null, System.Collections.Generic.IEnumerable embeddedTexts = null, System.IO.Stream metadataPeStream = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> Microsoft.CodeAnalysis.Emit.EmitResult +Microsoft.CodeAnalysis.Compilation.Emit(System.IO.Stream peStream, System.IO.Stream pdbStream, System.IO.Stream xmlDocumentationStream, System.IO.Stream win32Resources, System.Collections.Generic.IEnumerable manifestResources, Microsoft.CodeAnalysis.Emit.EmitOptions options, Microsoft.CodeAnalysis.IMethodSymbol debugEntryPoint, System.IO.Stream sourceLinkStream, System.Collections.Generic.IEnumerable embeddedTexts, System.Threading.CancellationToken cancellationToken) -> Microsoft.CodeAnalysis.Emit.EmitResult Microsoft.CodeAnalysis.Compilation.Emit(System.IO.Stream peStream, System.IO.Stream pdbStream, System.IO.Stream xmlDocumentationStream, System.IO.Stream win32Resources, System.Collections.Generic.IEnumerable manifestResources, Microsoft.CodeAnalysis.Emit.EmitOptions options, Microsoft.CodeAnalysis.IMethodSymbol debugEntryPoint, System.Threading.CancellationToken cancellationToken) -> Microsoft.CodeAnalysis.Emit.EmitResult Microsoft.CodeAnalysis.Compilation.GetUnreferencedAssemblyIdentities(Microsoft.CodeAnalysis.Diagnostic diagnostic) -> System.Collections.Immutable.ImmutableArray Microsoft.CodeAnalysis.CompilationOptions.WithConcurrentBuild(bool concurrent) -> Microsoft.CodeAnalysis.CompilationOptions diff --git a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/EvaluationContext.cs b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/EvaluationContext.cs index cda9d235db5cc..cc1ba417828aa 100644 --- a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/EvaluationContext.cs +++ b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/EvaluationContext.cs @@ -263,7 +263,7 @@ internal override CompileResult CompileExpression( getPortablePdbStreamOpt: null, nativePdbWriterOpt: null, pdbPathOpt: null, - allowMissingMethodBodies: false, + metadataOnly: false, isDeterministic: false, cancellationToken: default(CancellationToken)); @@ -352,7 +352,7 @@ internal override CompileResult CompileAssignment( getPortablePdbStreamOpt: null, nativePdbWriterOpt: null, pdbPathOpt: null, - allowMissingMethodBodies: false, + metadataOnly: false, isDeterministic: false, cancellationToken: default(CancellationToken)); @@ -396,7 +396,7 @@ internal override ReadOnlyCollection CompileGetLocals( getPortablePdbStreamOpt: null, nativePdbWriterOpt: null, pdbPathOpt: null, - allowMissingMethodBodies: false, + metadataOnly: false, isDeterministic: false, cancellationToken: default(CancellationToken)); diff --git a/src/ExpressionEvaluator/Core/Test/ExpressionCompiler/ExpressionCompilerTestHelpers.cs b/src/ExpressionEvaluator/Core/Test/ExpressionCompiler/ExpressionCompilerTestHelpers.cs index 2d4096440e450..64257ff58dd09 100644 --- a/src/ExpressionEvaluator/Core/Test/ExpressionCompiler/ExpressionCompilerTestHelpers.cs +++ b/src/ExpressionEvaluator/Core/Test/ExpressionCompiler/ExpressionCompilerTestHelpers.cs @@ -789,7 +789,7 @@ internal static void EmitCorLibWithAssemblyReferences( () => peStream, () => pdbStream, null, null, - allowMissingMethodBodies: true, + metadataOnly: true, isDeterministic: false, cancellationToken: default(CancellationToken)); diff --git a/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/EvaluationContext.vb b/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/EvaluationContext.vb index 619b89fb23c8b..2dc724c6a37fd 100644 --- a/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/EvaluationContext.vb +++ b/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/EvaluationContext.vb @@ -398,7 +398,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator getPortablePdbStreamOpt:=Nothing, nativePdbWriterOpt:=Nothing, pdbPathOpt:=Nothing, - allowMissingMethodBodies:=False, + metadataOnly:=False, isDeterministic:=False, cancellationToken:=Nothing) @@ -442,7 +442,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator getPortablePdbStreamOpt:=Nothing, nativePdbWriterOpt:=Nothing, pdbPathOpt:=Nothing, - allowMissingMethodBodies:=False, + metadataOnly:=False, isDeterministic:=False, cancellationToken:=Nothing) @@ -486,7 +486,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator getPortablePdbStreamOpt:=Nothing, nativePdbWriterOpt:=Nothing, pdbPathOpt:=Nothing, - allowMissingMethodBodies:=False, + metadataOnly:=False, isDeterministic:=False, cancellationToken:=Nothing) diff --git a/src/Test/Utilities/Portable/Compilation/CompilationExtensions.cs b/src/Test/Utilities/Portable/Compilation/CompilationExtensions.cs index acb32e390b463..f3bcd50536fbf 100644 --- a/src/Test/Utilities/Portable/Compilation/CompilationExtensions.cs +++ b/src/Test/Utilities/Portable/Compilation/CompilationExtensions.cs @@ -45,6 +45,7 @@ internal static ImmutableArray EmitToArray( var emitResult = compilation.Emit( peStream: peStream, + metadataPeStream: null, pdbStream: pdbStream, xmlDocumentationStream: null, win32Resources: null, diff --git a/src/Test/Utilities/Portable/Compilation/IRuntimeEnvironment.cs b/src/Test/Utilities/Portable/Compilation/IRuntimeEnvironment.cs index bee66b9519f56..b767804c589bb 100644 --- a/src/Test/Utilities/Portable/Compilation/IRuntimeEnvironment.cs +++ b/src/Test/Utilities/Portable/Compilation/IRuntimeEnvironment.cs @@ -235,6 +235,7 @@ EmitOptions emitOptions { result = compilation.Emit( executableStream, + metadataPeStream: null, pdbStream: pdbStream, xmlDocumentationStream: null, win32Resources: null, From 86d247383cbd72de865f150e060d1c12978c8ffd Mon Sep 17 00:00:00 2001 From: Julien Couvreur Date: Mon, 13 Mar 2017 13:41:05 -0700 Subject: [PATCH 05/14] Refining tests and adding throw null bodies --- .../Test/CommandLine/CommandLineTests.cs | 110 +++++++++++++++--- .../Test/Emit/Emit/CompilationEmitTests.cs | 12 +- .../Core/Portable/PEWriter/MetadataWriter.cs | 66 +++++++++-- 3 files changed, 155 insertions(+), 33 deletions(-) diff --git a/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs b/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs index e7cca10dc0470..0952e0067d9c9 100644 --- a/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs +++ b/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs @@ -8862,29 +8862,81 @@ public void RefOut() dir.CreateDirectory("ref"); var src = dir.CreateFile("a.cs"); - src.WriteAllText(@"class C { public static void Main() { } }"); + src.WriteAllText(@" +class C +{ + /// Main method + public static void Main() + { + System.Console.Write(""Hello""); + } +}"); var outWriter = new StringWriter(CultureInfo.InvariantCulture); - var csc = new MockCSharpCompiler(null, dir.Path, new[] { "/nologo", "/out:a.dll", "/refout:ref/a.dll", "/deterministic", "a.cs" }); + var csc = new MockCSharpCompiler(null, dir.Path, new[] { "/nologo", "/out:a.exe", "/refout:ref/a.dll", "/doc:doc.xml", "/deterministic", "a.cs" }); int exitCode = csc.Run(outWriter); Assert.Equal(0, exitCode); + var exe = Path.Combine(dir.Path, "a.exe"); + Assert.True(File.Exists(exe)); + + VerifyPEMetadata(File.OpenRead(exe), + new[] { "TypeDef:", "TypeDef:C" }, + new[] { "MethodDef: Void Main()", "MethodDef: Void .ctor()" }, + new[] { "CompilationRelaxationsAttribute", "RuntimeCompatibilityAttribute", "DebuggableAttribute" } + ); + + var doc = Path.Combine(dir.Path, "doc.xml"); + Assert.True(File.Exists(doc)); + + using (var reader = new StreamReader(doc)) + { + var content = reader.ReadToEnd(); + var expectedDoc = +@" + + + a + + + + Main method + + +"; + Assert.Equal(expectedDoc, content.Trim()); + } + + var output = ProcessUtilities.RunAndGetOutput(exe, startFolder: dir.ToString()); + Assert.Equal("Hello", output.Trim()); + var refDll = Path.Combine(dir.Path, "ref\\a.dll"); Assert.True(File.Exists(refDll)); - var refPeStream = File.OpenRead(refDll); - using (var refPeReader = new PEReader(refPeStream)) + VerifyPEMetadata(File.OpenRead(refDll), + new[] { "TypeDef:", "TypeDef:C" }, + new[] { "MethodDef: Void Main()", "MethodDef: Void .ctor()" }, + new[] { "CompilationRelaxationsAttribute", "RuntimeCompatibilityAttribute", "DebuggableAttribute" } + ); + + output = ProcessUtilities.RunAndGetOutput(refDll, startFolder: dir.ToString(), expectedRetCode: -532462766); + + // Clean up temp files + CleanupAllGeneratedFiles(dir.Path); + } + + private static void VerifyPEMetadata(FileStream peStream, string[] types, string[] methods, string[] attributes) + { + using (var refPeReader = new PEReader(peStream)) { var metadataReader = refPeReader.GetMetadataReader(); // The types and members that are included needs further refinement. // See issue https://github.com/dotnet/roslyn/issues/17612 - AssertEx.SetEqual(metadataReader.TypeDefinitions.Select(t => metadataReader.Dump(t)), - new[] { "TypeDef:", "TypeDef:C" }); + AssertEx.SetEqual(metadataReader.TypeDefinitions.Select(t => metadataReader.Dump(t)), types); - AssertEx.SetEqual(metadataReader.MethodDefinitions.Select(t => metadataReader.Dump(t)), - new[] { "MethodDef: Void Main()", "MethodDef: Void .ctor()" }); + AssertEx.SetEqual(metadataReader.MethodDefinitions.Select(t => metadataReader.Dump(t)), methods); // ReferenceAssemblyAttribute is missing. // See issue https://github.com/dotnet/roslyn/issues/17612 @@ -8893,11 +8945,8 @@ public void RefOut() .Select(c => metadataReader.GetMemberReference((MemberReferenceHandle)c).Parent) .Select(p => metadataReader.GetTypeReference((TypeReferenceHandle)p).Name) .Select(n => metadataReader.GetString(n)), - new[] { "CompilationRelaxationsAttribute", "RuntimeCompatibilityAttribute", "DebuggableAttribute" }); + attributes); } - - // Clean up temp files - CleanupAllGeneratedFiles(dir.Path); } [Fact] @@ -8918,7 +8967,9 @@ public void RefOutWithError() Assert.False(File.Exists(dll)); var refDll = Path.Combine(dir.Path, "ref\\a.dll"); - Assert.False(File.Exists(refDll)); // PROTOTYPE Should we produce ref assemblies on method body errors? + Assert.False(File.Exists(refDll)); + + Assert.Equal("a.cs(1,39): error CS0103: The name 'error' does not exist in the current context", outWriter.ToString().Trim()); // Clean up temp files CleanupAllGeneratedFiles(dir.Path); @@ -8930,10 +8981,18 @@ public void RefOnly() var dir = Temp.CreateDirectory(); var src = dir.CreateFile("a.cs"); - src.WriteAllText(@"class C { public static void Main() { error(); } }"); // semantic error in method body + src.WriteAllText(@" +class C +{ + /// Main method + public static void Main() + { + error(); // semantic error in method body + } +}"); var outWriter = new StringWriter(CultureInfo.InvariantCulture); - var csc = new MockCSharpCompiler(null, dir.Path, new[] { "/nologo", "/out:a.dll", "/refonly", "/debug", "/deterministic", "a.cs" }); + var csc = new MockCSharpCompiler(null, dir.Path, new[] { "/nologo", "/out:a.dll", "/refonly", "/debug", "/deterministic", "/doc:doc.xml", "a.cs" }); int exitCode = csc.Run(outWriter); Assert.Equal(0, exitCode); @@ -8943,6 +9002,27 @@ public void RefOnly() var pdb = Path.Combine(dir.Path, "a.pdb"); Assert.False(File.Exists(pdb)); + var doc = Path.Combine(dir.Path, "doc.xml"); + Assert.True(File.Exists(doc)); + + using (var reader = new StreamReader(doc)) + { + var content = reader.ReadToEnd(); + var expectedDoc = +@" + + + a + + + + Main method + + +"; + Assert.Equal(expectedDoc, content.Trim()); + } + // Clean up temp files CleanupAllGeneratedFiles(dir.Path); } diff --git a/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs b/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs index 3f39245c1f710..1544ca2e72e95 100644 --- a/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs +++ b/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs @@ -320,10 +320,10 @@ public void VerifyRefAssembly() string source = @" public class PublicClass { - public void PublicMethod() { } - private void PrivateMethod() { } - protected void ProtectedMethod() { } - internal void InternalMethod() { } + public void PublicMethod() { System.Console.Write(""Hello""); } + private void PrivateMethod() { System.Console.Write(""Hello""); } + protected void ProtectedMethod() { System.Console.Write(""Hello""); } + internal void InternalMethod() { System.Console.Write(""Hello""); } } "; CSharpCompilation comp = CreateCompilation(source, references: new[] { MscorlibRef }, @@ -331,8 +331,8 @@ internal void InternalMethod() { } var emitRefOnly = EmitOptions.Default.WithEmitMetadataOnly(true); - var verifier = CompileAndVerify(comp, emitOptions: emitRefOnly, verify: false); // PROTOTYPE(refout) PEVerify fails - Assert.True(verifier.TestData.Methods.IsEmpty); // no method bodies + var verifier = CompileAndVerify(comp, emitOptions: emitRefOnly, verify: true); + // PROTOTYPE(refout) Not sure best way to verify that method bodies are "throw null" var image = comp.EmitToImageReference(emitRefOnly); var comp2 = CreateCompilation("", references: new[] { MscorlibRef, image }, diff --git a/src/Compilers/Core/Portable/PEWriter/MetadataWriter.cs b/src/Compilers/Core/Portable/PEWriter/MetadataWriter.cs index d863e34c21229..690c3c7bed2e7 100644 --- a/src/Compilers/Core/Portable/PEWriter/MetadataWriter.cs +++ b/src/Compilers/Core/Portable/PEWriter/MetadataWriter.cs @@ -70,6 +70,9 @@ internal abstract partial class MetadataWriter // A map of method body before token translation to RVA. Used for deduplication of small bodies. private readonly Dictionary, int> _smallMethodBodies; + private ImmutableArray ThrowNullIL { get; } = ImmutableArray.Create((byte)ILOpCode.Ldnull, (byte)ILOpCode.Throw); + private const int ThrowNullMaxStack = 1; + protected MetadataWriter( MetadataBuilder metadata, MetadataBuilder debugMetadataOpt, @@ -2828,23 +2831,32 @@ private int[] SerializeMethodBodies(BlobBuilder ilBuilder, PdbWriter nativePdbWr IMethodBody body; StandaloneSignatureHandle localSignatureHandleOpt; - if (method.HasBody() && !metadataOnly) + if (method.HasBody()) { - body = method.GetBody(Context); - - if (body != null) + if (metadataOnly) { - localSignatureHandleOpt = this.SerializeLocalVariablesSignature(body); - - // TODO: consider parallelizing these (local signature tokens can be piped into IL serialization & debug info generation) - bodyOffset = SerializeMethodBody(encoder, body, localSignatureHandleOpt, ref mvidStringHandle, ref mvidStringFixup); - - nativePdbWriterOpt?.SerializeDebugInfo(body, localSignatureHandleOpt, customDebugInfoWriter); + bodyOffset = SerializeThrowNullMethodBody(encoder, ref mvidStringHandle, ref mvidStringFixup); + localSignatureHandleOpt = default(StandaloneSignatureHandle); + body = null; } else { - bodyOffset = 0; - localSignatureHandleOpt = default(StandaloneSignatureHandle); + body = method.GetBody(Context); + + if (body != null) + { + localSignatureHandleOpt = this.SerializeLocalVariablesSignature(body); + + // TODO: consider parallelizing these (local signature tokens can be piped into IL serialization & debug info generation) + bodyOffset = SerializeMethodBody(encoder, body, localSignatureHandleOpt, ref mvidStringHandle, ref mvidStringFixup); + + nativePdbWriterOpt?.SerializeDebugInfo(body, localSignatureHandleOpt, customDebugInfoWriter); + } + else + { + bodyOffset = 0; + localSignatureHandleOpt = default(StandaloneSignatureHandle); + } } } else @@ -2870,6 +2882,36 @@ private int[] SerializeMethodBodies(BlobBuilder ilBuilder, PdbWriter nativePdbWr return bodyOffsets; } + private int SerializeThrowNullMethodBody(MethodBodyStreamEncoder encoder, ref UserStringHandle mvidStringHandle, ref Blob mvidStringFixup) + { + var il = ThrowNullIL; + + // Don't do small body method caching during deterministic builds until this issue is fixed + // https://github.com/dotnet/roslyn/issues/7595 + int bodyOffset; + if (!_deterministic && _smallMethodBodies.TryGetValue(il, out bodyOffset)) + { + return bodyOffset; + } + + var encodedBody = encoder.AddMethodBody( + codeSize: il.Length, + maxStack: ThrowNullMaxStack, + exceptionRegionCount: 0, + hasSmallExceptionRegions: false); + + // Don't do small body method caching during deterministic builds until this issue is fixed + // https://github.com/dotnet/roslyn/issues/7595 + if (!_deterministic) + { + _smallMethodBodies.Add(il, encodedBody.Offset); + } + + WriteInstructions(encodedBody.Instructions, il, ref mvidStringHandle, ref mvidStringFixup); + + return encodedBody.Offset; + } + private int SerializeMethodBody(MethodBodyStreamEncoder encoder, IMethodBody methodBody, StandaloneSignatureHandle localSignatureHandleOpt, ref UserStringHandle mvidStringHandle, ref Blob mvidStringFixup) { int ilLength = methodBody.IL.Length; From cdebcc039ecd431d44873b058f26e5f8e39b0b14 Mon Sep 17 00:00:00 2001 From: Julien Couvreur Date: Tue, 14 Mar 2017 14:46:41 -0700 Subject: [PATCH 06/14] Verify throw null bodies --- .../Test/CommandLine/CommandLineTests.cs | 6 + .../Test/Emit/Emit/CompilationEmitTests.cs | 118 ++++++++++++++++-- .../CodeAnalysisResources.Designer.cs | 18 +++ .../Core/Portable/CodeAnalysisResources.resx | 6 + .../Core/Portable/Compilation/Compilation.cs | 10 +- .../Core/Portable/GlobalSuppressions.cs | 2 - .../Core/Portable/PEWriter/MetadataWriter.cs | 10 +- .../Portable/PEWriter/ReferenceIndexer.cs | 6 +- .../Utilities/Portable/Assert/AssertEx.cs | 20 ++- 9 files changed, 169 insertions(+), 27 deletions(-) diff --git a/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs b/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs index 0952e0067d9c9..85cb3f4ae5ae1 100644 --- a/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs +++ b/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs @@ -8999,6 +8999,12 @@ public static void Main() var refDll = Path.Combine(dir.Path, "a.dll"); Assert.True(File.Exists(refDll)); + VerifyPEMetadata(File.OpenRead(refDll), + new[] { "TypeDef:", "TypeDef:C" }, + new[] { "MethodDef: Void Main()", "MethodDef: Void .ctor()" }, + new[] { "CompilationRelaxationsAttribute", "RuntimeCompatibilityAttribute", "DebuggableAttribute" } + ); + var pdb = Path.Combine(dir.Path, "a.pdb"); Assert.False(File.Exists(pdb)); diff --git a/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs b/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs index 1544ca2e72e95..f41c8bd28a6fe 100644 --- a/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs +++ b/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs @@ -242,7 +242,7 @@ public static void Main() InlineData("", "private void M() { }", false), // Should be true. See follow-up issue https://github.com/dotnet/roslyn/issues/17612 InlineData("internal void M() { }", "", false), InlineData("public struct S { private int i; }", "public struct S { }", false)] - public void RefAssemblyChanges(string change1, string change2, bool expectMatch) + public void RefAssembly_InvariantToSomeChanges(string change1, string change2, bool expectMatch) { string sourceTemplate = @" public class C @@ -258,9 +258,8 @@ public class C byte[] image1; using (var output = new MemoryStream()) - using (var pdbOutput = new MemoryStream()) { - var emitResult = comp1.Emit(output, pdbOutput, options: EmitOptions.Default.WithEmitMetadataOnly(true)); + var emitResult = comp1.Emit(output, options: EmitOptions.Default.WithEmitMetadataOnly(true)); Assert.True(emitResult.Success); emitResult.Diagnostics.Verify(); image1 = output.ToArray(); @@ -273,15 +272,21 @@ public class C byte[] image2; using (var output = new MemoryStream()) - using (var pdbOutput = new MemoryStream()) { - var emitResult = comp2.Emit(output, pdbOutput, options: EmitOptions.Default.WithEmitMetadataOnly(true)); + var emitResult = comp2.Emit(output, options: EmitOptions.Default.WithEmitMetadataOnly(true)); Assert.True(emitResult.Success); emitResult.Diagnostics.Verify(); image2 = output.ToArray(); } - Assert.True(AssertEx.SequenceEqual(image1, image2) == expectMatch); + if (expectMatch) + { + AssertEx.Equal(image1, image2); + } + else + { + AssertEx.NotEqual(image1, image2); + } } [Theory, @@ -289,7 +294,7 @@ public class C InlineData("public int M() { error() }", false), // Should be true. See follow-up issue https://github.com/dotnet/roslyn/issues/17612 InlineData("public Error M() { return null; }", false), // Should be true. See follow-up issue https://github.com/dotnet/roslyn/issues/17612 ] - public void RefAssemblyDiagnostics(string change, bool expectSuccess) + public void RefAssembly_IgnoresSomeDiagnostics(string change, bool expectSuccess) { string sourceTemplate = @" public class C @@ -305,9 +310,8 @@ public class C byte[] image; using (var output = new MemoryStream()) - using (var pdbOutput = new MemoryStream()) { - var emitResult = comp1.Emit(output, pdbOutput, options: EmitOptions.Default.WithEmitMetadataOnly(true)); + var emitResult = comp1.Emit(output, options: EmitOptions.Default.WithEmitMetadataOnly(true)); Assert.Equal(expectSuccess, emitResult.Success); Assert.Equal(!expectSuccess, emitResult.Diagnostics.Any()); image = output.ToArray(); @@ -318,12 +322,13 @@ public class C public void VerifyRefAssembly() { string source = @" -public class PublicClass +public abstract class PublicClass { public void PublicMethod() { System.Console.Write(""Hello""); } private void PrivateMethod() { System.Console.Write(""Hello""); } protected void ProtectedMethod() { System.Console.Write(""Hello""); } internal void InternalMethod() { System.Console.Write(""Hello""); } + public abstract void AbstractMethod(); } "; CSharpCompilation comp = CreateCompilation(source, references: new[] { MscorlibRef }, @@ -332,8 +337,8 @@ public class PublicClass var emitRefOnly = EmitOptions.Default.WithEmitMetadataOnly(true); var verifier = CompileAndVerify(comp, emitOptions: emitRefOnly, verify: true); - // PROTOTYPE(refout) Not sure best way to verify that method bodies are "throw null" + // verify metadata (types, members, attributes) var image = comp.EmitToImageReference(emitRefOnly); var comp2 = CreateCompilation("", references: new[] { MscorlibRef, image }, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All)); @@ -342,14 +347,101 @@ public class PublicClass AssertEx.SetEqual(members.Select(m => m.ToDisplayString()), new[] { "", "PublicClass" }); - AssertEx.SetEqual(((NamedTypeSymbol)assembly.GlobalNamespace.GetMember("PublicClass")).GetMembers().Select(m => m.ToTestDisplayString()), + AssertEx.SetEqual( + ((NamedTypeSymbol)assembly.GlobalNamespace.GetMember("PublicClass")).GetMembers() + .Select(m => m.ToTestDisplayString()), new[] { "void PublicClass.PublicMethod()", "void PublicClass.PrivateMethod()", - "void PublicClass.InternalMethod()", "void PublicClass.ProtectedMethod()", "PublicClass..ctor()" }); + "void PublicClass.InternalMethod()", "void PublicClass.ProtectedMethod()", + "void PublicClass.AbstractMethod()", "PublicClass..ctor()" }); AssertEx.SetEqual(assembly.GetAttributes().Select(a => a.AttributeClass.ToTestDisplayString()), new[] { "System.Runtime.CompilerServices.CompilationRelaxationsAttribute", "System.Runtime.CompilerServices.RuntimeCompatibilityAttribute", "System.Diagnostics.DebuggableAttribute" }); + + var peImage = comp.EmitToArray(emitRefOnly); + VerifyMethodBodies(peImage, expectEmptyOrThrowNull: true); + } + + private static void VerifyMethodBodies(System.Collections.Immutable.ImmutableArray peImage, bool expectEmptyOrThrowNull) + { + using (var peReader = new PEReader(peImage)) + { + var metadataReader = peReader.GetMetadataReader(); + foreach (var method in metadataReader.MethodDefinitions) + { + var rva = metadataReader.GetMethodDefinition(method).RelativeVirtualAddress; + if (rva != 0) + { + var il = peReader.GetMethodBody(rva).GetILBytes(); + var throwNull = new[] { (byte)ILOpCode.Ldnull, (byte)ILOpCode.Throw }; + + if (expectEmptyOrThrowNull) + { + AssertEx.Equal(throwNull, il); + } + else + { + AssertEx.NotEqual(throwNull, il); + } + } + } + } + } + + [Fact] + public void EmitMetadataOnly_NoPdbs() + { + CSharpCompilation comp = CreateCompilation("", references: new[] { MscorlibRef }, + options: TestOptions.DebugDll.WithDeterministic(true)); + + using (var output = new MemoryStream()) + using (var pdbOutput = new MemoryStream()) + { + Assert.Throws(() => comp.Emit(output, pdbOutput, + options: EmitOptions.Default.WithEmitMetadataOnly(true))); + } + } + + [Fact] + public void EmitMetadataOnly_NoMetadataPeStream() + { + CSharpCompilation comp = CreateCompilation("", references: new[] { MscorlibRef }, + options: TestOptions.DebugDll.WithDeterministic(true)); + + using (var output = new MemoryStream()) + using (var metadataPeOutput = new MemoryStream()) + { + Assert.Throws(() => comp.Emit(output, metadataPeStream: metadataPeOutput, + options: EmitOptions.Default.WithEmitMetadataOnly(true))); + } + } + + [Fact] + public void EmitMetadata() + { + string source = @" +public abstract class PublicClass +{ + public void PublicMethod() { System.Console.Write(""Hello""); } +} +"; + CSharpCompilation comp = CreateCompilation(source, references: new[] { MscorlibRef }, + options: TestOptions.DebugDll.WithDeterministic(true)); + + using (var output = new MemoryStream()) + using (var pdbOutput = new MemoryStream()) + using (var metadataOutput = new MemoryStream()) + { + var result = comp.Emit(output, pdbOutput, metadataPeStream: metadataOutput); + Assert.True(result.Success); + Assert.NotEqual(0, output.Position); + Assert.NotEqual(0, pdbOutput.Position); + Assert.NotEqual(0, metadataOutput.Position); + } + + var peImage = comp.EmitToArray(); + VerifyMethodBodies(peImage, expectEmptyOrThrowNull: false); } /// diff --git a/src/Compilers/Core/Portable/CodeAnalysisResources.Designer.cs b/src/Compilers/Core/Portable/CodeAnalysisResources.Designer.cs index f7d3bbd3e231d..e89dfe380ab29 100644 --- a/src/Compilers/Core/Portable/CodeAnalysisResources.Designer.cs +++ b/src/Compilers/Core/Portable/CodeAnalysisResources.Designer.cs @@ -847,6 +847,15 @@ internal static string KeyInPathMapEndsWithSeparator { } } + /// + /// Looks up a localized string similar to Metadata PE stream should not be given when emitting metadata only.. + /// + internal static string MetadataPeStreamUnexpectedWhenEmittingMetadataOnly { + get { + return ResourceManager.GetString("MetadataPeStreamUnexpectedWhenEmittingMetadataOnly", resourceCulture); + } + } + /// /// Looks up a localized string similar to MetadataReference '{0}' not found to remove.. /// @@ -1027,6 +1036,15 @@ internal static string PdbStreamUnexpectedWhenEmbedding { } } + /// + /// Looks up a localized string similar to PDB stream should not be given when emitting metadata only.. + /// + internal static string PdbStreamUnexpectedWhenEmittingMetadataOnly { + get { + return ResourceManager.GetString("PdbStreamUnexpectedWhenEmittingMetadataOnly", resourceCulture); + } + } + /// /// Looks up a localized string similar to PE image doesn't contain managed metadata.. /// diff --git a/src/Compilers/Core/Portable/CodeAnalysisResources.resx b/src/Compilers/Core/Portable/CodeAnalysisResources.resx index 3af8d6f2de563..198b316cb4b53 100644 --- a/src/Compilers/Core/Portable/CodeAnalysisResources.resx +++ b/src/Compilers/Core/Portable/CodeAnalysisResources.resx @@ -330,6 +330,12 @@ PDB stream should not be given when embedding PDB into the PE stream. + + PDB stream should not be given when emitting metadata only. + + + Metadata PE stream should not be given when emitting metadata only. + Invalid hash. diff --git a/src/Compilers/Core/Portable/Compilation/Compilation.cs b/src/Compilers/Core/Portable/Compilation/Compilation.cs index 0c12327dff12c..0a9d62660e8ab 100644 --- a/src/Compilers/Core/Portable/Compilation/Compilation.cs +++ b/src/Compilers/Core/Portable/Compilation/Compilation.cs @@ -2060,11 +2060,16 @@ public EmitResult Emit( { throw new ArgumentException(CodeAnalysisResources.StreamMustSupportWrite, nameof(pdbStream)); } + + if (options?.EmitMetadataOnly == true) + { + throw new ArgumentException(CodeAnalysisResources.PdbStreamUnexpectedWhenEmittingMetadataOnly, nameof(pdbStream)); + } } - if (metadataPeStream != null && options.EmitMetadataOnly) + if (metadataPeStream != null && options?.EmitMetadataOnly == true) { - throw new ArgumentException(CodeAnalysisResources.StreamMustSupportWrite, nameof(metadataPeStream)); // PROTOTYPE(refout) fix error message and add test + throw new ArgumentException(CodeAnalysisResources.MetadataPeStreamUnexpectedWhenEmittingMetadataOnly, nameof(metadataPeStream)); } if (win32Resources != null) @@ -2567,7 +2572,6 @@ internal bool SerializeToPeStream( { nativePdbWriter?.Dispose(); signingInputStream?.Dispose(); - refPeStream?.Dispose(); pdbBag?.Free(); metadataDiagnostics?.Free(); } diff --git a/src/Compilers/Core/Portable/GlobalSuppressions.cs b/src/Compilers/Core/Portable/GlobalSuppressions.cs index e27d0752ba4d5..e05dbf22d3d2a 100644 --- a/src/Compilers/Core/Portable/GlobalSuppressions.cs +++ b/src/Compilers/Core/Portable/GlobalSuppressions.cs @@ -13,6 +13,4 @@ [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "", Scope = "member", Target = "~M:Microsoft.CodeAnalysis.Text.SourceText.From(System.Byte[],System.Int32,System.Text.Encoding,Microsoft.CodeAnalysis.Text.SourceHashAlgorithm,System.Boolean,System.Boolean)~Microsoft.CodeAnalysis.Text.SourceText")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "", Scope = "member", Target = "~M:Microsoft.CodeAnalysis.Text.SourceText.From(System.IO.TextReader,System.Int32,System.Text.Encoding,Microsoft.CodeAnalysis.Text.SourceHashAlgorithm)~Microsoft.CodeAnalysis.Text.SourceText")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0027:Public API with optional parameter(s) should have the most parameters amongst its public overloads.", Justification = "", Scope = "member", Target = "~M:Microsoft.CodeAnalysis.Text.SourceText.From(System.String,System.Text.Encoding,Microsoft.CodeAnalysis.Text.SourceHashAlgorithm)~Microsoft.CodeAnalysis.Text.SourceText")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "", Scope = "member", Target = "~M:Microsoft.CodeAnalysis.Compilation.Emit(System.IO.Stream,System.IO.Stream,System.IO.Stream,System.IO.Stream,System.Collections.Generic.IEnumerable{Microsoft.CodeAnalysis.ResourceDescription},Microsoft.CodeAnalysis.Emit.EmitOptions,Microsoft.CodeAnalysis.IMethodSymbol,System.IO.Stream,System.Collections.Generic.IEnumerable{Microsoft.CodeAnalysis.EmbeddedText},System.Threading.CancellationToken)~Microsoft.CodeAnalysis.Emit.EmitResult")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "", Scope = "member", Target = "~M:Microsoft.CodeAnalysis.Compilation.Emit(System.IO.Stream,System.IO.Stream,System.IO.Stream,System.IO.Stream,System.Collections.Generic.IEnumerable{Microsoft.CodeAnalysis.ResourceDescription},Microsoft.CodeAnalysis.Emit.EmitOptions,Microsoft.CodeAnalysis.IMethodSymbol,System.IO.Stream,System.Collections.Generic.IEnumerable{Microsoft.CodeAnalysis.EmbeddedText},System.IO.Stream,System.Threading.CancellationToken)~Microsoft.CodeAnalysis.Emit.EmitResult")] diff --git a/src/Compilers/Core/Portable/PEWriter/MetadataWriter.cs b/src/Compilers/Core/Portable/PEWriter/MetadataWriter.cs index 690c3c7bed2e7..a8f27302e642c 100644 --- a/src/Compilers/Core/Portable/PEWriter/MetadataWriter.cs +++ b/src/Compilers/Core/Portable/PEWriter/MetadataWriter.cs @@ -70,7 +70,7 @@ internal abstract partial class MetadataWriter // A map of method body before token translation to RVA. Used for deduplication of small bodies. private readonly Dictionary, int> _smallMethodBodies; - private ImmutableArray ThrowNullIL { get; } = ImmutableArray.Create((byte)ILOpCode.Ldnull, (byte)ILOpCode.Throw); + private static ImmutableArray ThrowNullIL { get; } = ImmutableArray.Create((byte)ILOpCode.Ldnull, (byte)ILOpCode.Throw); private const int ThrowNullMaxStack = 1; protected MetadataWriter( @@ -2835,7 +2835,7 @@ private int[] SerializeMethodBodies(BlobBuilder ilBuilder, PdbWriter nativePdbWr { if (metadataOnly) { - bodyOffset = SerializeThrowNullMethodBody(encoder, ref mvidStringHandle, ref mvidStringFixup); + bodyOffset = SerializeThrowNullMethodBody(encoder); localSignatureHandleOpt = default(StandaloneSignatureHandle); body = null; } @@ -2882,7 +2882,7 @@ private int[] SerializeMethodBodies(BlobBuilder ilBuilder, PdbWriter nativePdbWr return bodyOffsets; } - private int SerializeThrowNullMethodBody(MethodBodyStreamEncoder encoder, ref UserStringHandle mvidStringHandle, ref Blob mvidStringFixup) + private int SerializeThrowNullMethodBody(MethodBodyStreamEncoder encoder) { var il = ThrowNullIL; @@ -2907,8 +2907,12 @@ private int SerializeThrowNullMethodBody(MethodBodyStreamEncoder encoder, ref Us _smallMethodBodies.Add(il, encodedBody.Offset); } + UserStringHandle mvidStringHandle = default(UserStringHandle); + Blob mvidStringFixup = default(Blob); WriteInstructions(encodedBody.Instructions, il, ref mvidStringHandle, ref mvidStringFixup); + Debug.Assert(mvidStringHandle.Equals(default(UserStringHandle)) && mvidStringFixup.Equals(default(Blob))); + return encodedBody.Offset; } diff --git a/src/Compilers/Core/Portable/PEWriter/ReferenceIndexer.cs b/src/Compilers/Core/Portable/PEWriter/ReferenceIndexer.cs index e748b6398d1e1..0b545af969782 100644 --- a/src/Compilers/Core/Portable/PEWriter/ReferenceIndexer.cs +++ b/src/Compilers/Core/Portable/PEWriter/ReferenceIndexer.cs @@ -99,7 +99,7 @@ protected override void RecordAssemblyReference(IAssemblyReference assemblyRefer protected override void ProcessMethodBody(IMethodDefinition method) { - if (method.HasBody()) + if (method.HasBody() && !metadataWriter.metadataOnly) { var body = method.GetBody(Context); @@ -119,10 +119,6 @@ protected override void ProcessMethodBody(IMethodDefinition method) } } } - else if (!metadataWriter.metadataOnly) - { - throw ExceptionUtilities.Unreachable; - } } } diff --git a/src/Test/Utilities/Portable/Assert/AssertEx.cs b/src/Test/Utilities/Portable/Assert/AssertEx.cs index 37256108733ae..b52bb6578990c 100644 --- a/src/Test/Utilities/Portable/Assert/AssertEx.cs +++ b/src/Test/Utilities/Portable/Assert/AssertEx.cs @@ -210,7 +210,25 @@ public static void Equal(IEnumerable expected, IEnumerable actual, IEqu } } - public static bool SequenceEqual(IEnumerable expected, IEnumerable actual, IEqualityComparer comparer = null) + public static void NotEqual(IEnumerable expected, IEnumerable actual, IEqualityComparer comparer = null, string message = null, + string itemSeparator = null, Func itemInspector = null) + { + if (ReferenceEquals(expected, actual)) + { + Fail("expected and actual references are identical\r\n" + message); + } + + if (expected == null || actual == null) + { + return; + } + else if (SequenceEqual(expected, actual, comparer)) + { + Fail("expected and actual sequences match\r\n" + message); + } + } + + private static bool SequenceEqual(IEnumerable expected, IEnumerable actual, IEqualityComparer comparer = null) { var enumerator1 = expected.GetEnumerator(); var enumerator2 = actual.GetEnumerator(); From 43db8ac2b4ae563202a52fce6e83cc84960575cc Mon Sep 17 00:00:00 2001 From: jcouv Date: Wed, 15 Mar 2017 21:10:37 -0700 Subject: [PATCH 07/14] Adding corresponding VB tests --- .../Test/Emit/Emit/CompilationEmitTests.cs | 3 - .../VisualBasicCommandLineParser.vb | 2 +- .../Compilation/VisualBasicCompilation.vb | 2 - .../Test/CommandLine/CommandLineTests.vb | 198 +++++++ .../Test/Emit/Emit/CompilationEmitTests.vb | 530 +++++++++++++----- .../Portable/Metadata/MetadataReaderUtils.cs | 3 - 6 files changed, 581 insertions(+), 157 deletions(-) diff --git a/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs b/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs index f41c8bd28a6fe..c12df3de95fbb 100644 --- a/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs +++ b/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs @@ -307,14 +307,11 @@ public class C CSharpCompilation comp1 = CreateCompilationWithMscorlib(Parse(source), options: TestOptions.DebugDll.WithDeterministic(true), assemblyName: name); - byte[] image; - using (var output = new MemoryStream()) { var emitResult = comp1.Emit(output, options: EmitOptions.Default.WithEmitMetadataOnly(true)); Assert.Equal(expectSuccess, emitResult.Success); Assert.Equal(!expectSuccess, emitResult.Diagnostics.Any()); - image = output.ToArray(); } } diff --git a/src/Compilers/VisualBasic/Portable/CommandLine/VisualBasicCommandLineParser.vb b/src/Compilers/VisualBasic/Portable/CommandLine/VisualBasicCommandLineParser.vb index 7fb53e6ddaefb..ec391826b1dc5 100644 --- a/src/Compilers/VisualBasic/Portable/CommandLine/VisualBasicCommandLineParser.vb +++ b/src/Compilers/VisualBasic/Portable/CommandLine/VisualBasicCommandLineParser.vb @@ -1428,7 +1428,7 @@ lVbRuntimePlus: .ScriptArguments = scriptArgs.AsImmutableOrEmpty(), .TouchedFilesPath = touchedFilesPath, .OutputLevel = outputLevel, - .EmitPdb = emitPdb And Not metadataOnly, + .EmitPdb = emitPdb AndAlso Not metadataOnly, .SourceLink = sourceLink, .DefaultCoreLibraryReference = defaultCoreLibraryReference, .PreferredUILang = preferredUILang, diff --git a/src/Compilers/VisualBasic/Portable/Compilation/VisualBasicCompilation.vb b/src/Compilers/VisualBasic/Portable/Compilation/VisualBasicCompilation.vb index d7431601b8c8f..2902afdc37514 100644 --- a/src/Compilers/VisualBasic/Portable/Compilation/VisualBasicCompilation.vb +++ b/src/Compilers/VisualBasic/Portable/Compilation/VisualBasicCompilation.vb @@ -2270,8 +2270,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic diagnostics As DiagnosticBag, cancellationToken As CancellationToken) As Boolean - Debug.Assert(Not moduleBuilder.EmitOptions.EmitMetadataOnly) - ' Use a temporary bag so we don't have to refilter pre-existing diagnostics. Dim resourceDiagnostics = DiagnosticBag.GetInstance() diff --git a/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb b/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb index 525368ddf5b44..01b6632208cae 100644 --- a/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb +++ b/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb @@ -2765,6 +2765,14 @@ print Goodbye, World" Assert.Equal("MyBinary.dll", parsedArgs.CompilationOptions.ModuleName) Assert.Equal("C:\My Folder", parsedArgs.OutputDirectory) + parsedArgs = DefaultParse({"/refout:", "a.cs"}, baseDirectory) + parsedArgs.Errors.Verify( + Diagnostic(ERRID.ERR_ArgumentRequired).WithArguments("refout", ":").WithLocation(1, 1)) + + parsedArgs = DefaultParse({"/refout:ref.dll", "/refonly", "a.cs"}, baseDirectory) + parsedArgs.Errors.Verify( + Diagnostic(ERRID.ERR_NoRefOutWhenRefOnly).WithLocation(1, 1)) + parsedArgs = DefaultParse({"/out:C:\""My Folder""\MyBinary.dll", "/t:library", "a.vb"}, baseDirectory) parsedArgs.Errors.Verify( Diagnostic(ERRID.FTL_InputFileNameTooLong).WithArguments("C:""My Folder\MyBinary.dll").WithLocation(1, 1)) @@ -7979,6 +7987,196 @@ End Class Next End Sub + + Sub RefOut() + Dim dir = Temp.CreateDirectory() + dir.CreateDirectory("ref") + + Dim src = dir.CreateFile("a.vb") + src.WriteAllText(" +Class C + ''' Main method + Public Shared Sub Main() + System.Console.Write(""Hello"") + End Sub +End Class") + + Dim outWriter = New StringWriter(CultureInfo.InvariantCulture) + Dim vbc = New MockVisualBasicCompiler(Nothing, dir.Path, + {"/define:_MYTYPE=""Empty"" ", "/nologo", "/out:a.exe", "/refout:ref/a.dll", "/doc:doc.xml", "/deterministic", "a.vb"}) + + Dim exitCode = vbc.Run(outWriter) + Assert.Equal(0, exitCode) + + Dim exe = Path.Combine(dir.Path, "a.exe") + Assert.True(File.Exists(exe)) + + VerifyPEMetadata(File.OpenRead(exe), + {"TypeDef:", "TypeDef:C"}, + {"MethodDef: Void Main()", "MethodDef: Void .ctor()"}, + {"CompilationRelaxationsAttribute", "RuntimeCompatibilityAttribute", "DebuggableAttribute", "STAThreadAttribute"} + ) + + + Dim doc = Path.Combine(dir.Path, "doc.xml") + Assert.True(File.Exists(doc)) + + Using reader As New StreamReader(doc) + Dim content = reader.ReadToEnd() + Dim expectedDoc = +" + + + +a + + + + + Main method + + +" + Assert.Equal(expectedDoc, content.Trim()) + + End Using + + Dim output = ProcessUtilities.RunAndGetOutput(exe, startFolder:=dir.ToString()) + Assert.Equal("Hello", output.Trim()) + + Dim refDll = Path.Combine(dir.Path, "ref\\a.dll") + Assert.True(File.Exists(refDll)) + + VerifyPEMetadata(File.OpenRead(refDll), + {"TypeDef:", "TypeDef:C"}, + {"MethodDef: Void Main()", "MethodDef: Void .ctor()"}, + {"CompilationRelaxationsAttribute", "RuntimeCompatibilityAttribute", "DebuggableAttribute", "STAThreadAttribute"} + ) + + output = ProcessUtilities.RunAndGetOutput(refDll, startFolder:=dir.ToString(), expectedRetCode:=-532462766) + + ' Clean up temp files + CleanupAllGeneratedFiles(dir.Path) + End Sub + + Private Shared Sub VerifyPEMetadata(peStream As FileStream, types As String(), methods As String(), attributes As String()) + Using refPeReader As New PEReader(peStream) + Dim metadataReader = refPeReader.GetMetadataReader() + + ' The types And members that are included needs further refinement. + ' See issue https://github.com/dotnet/roslyn/issues/17612 + AssertEx.SetEqual(metadataReader.TypeDefinitions.Select(Function(t) metadataReader.Dump(t)), types) + + AssertEx.SetEqual(metadataReader.MethodDefinitions.Select(Function(t) metadataReader.Dump(t)), methods) + + ' ReferenceAssemblyAttribute is missing. + ' See issue https://github.com/dotnet/roslyn/issues/17612 + AssertEx.SetEqual( + metadataReader.CustomAttributes.Select(Function(a) metadataReader.GetCustomAttribute(a).Constructor). + Select(Function(c) metadataReader.GetMemberReference(CType(c, MemberReferenceHandle)).Parent). + Select(Function(p) metadataReader.GetTypeReference(CType(p, TypeReferenceHandle)).Name). + Select(Function(n) metadataReader.GetString(n)), + attributes) + End Using + End Sub + + + Public Sub RefOutWithError() + Dim dir = Temp.CreateDirectory() + dir.CreateDirectory("ref") + + Dim src = dir.CreateFile("a.vb") + src.WriteAllText( +"Class C + Public Shared Sub Main() + Bad() + End Sub +End Class") + + Dim outWriter = New StringWriter(CultureInfo.InvariantCulture) + Dim csc = New MockVisualBasicCompiler(Nothing, dir.Path, + {"/define:_MYTYPE=""Empty"" ", "/nologo", "/out:a.dll", "/refout:ref/a.dll", "/deterministic", "a.vb"}) + + Dim exitCode = csc.Run(outWriter) + Assert.Equal(1, exitCode) + + Dim vb = Path.Combine(dir.Path, "a.vb") + + Dim dll = Path.Combine(dir.Path, "a.dll") + Assert.False(File.Exists(dll)) + + Dim refDll = Path.Combine(dir.Path, "ref\\a.dll") + Assert.False(File.Exists(refDll)) + + Assert.Equal( +$"{vb}(3) : error BC30451: 'Bad' is not declared. It may be inaccessible due to its protection level. + + Bad() + ~~~", +outWriter.ToString().Trim()) + + ' Clean up temp files + CleanupAllGeneratedFiles(dir.Path) + End Sub + + + Sub RefOnly() + Dim dir = Temp.CreateDirectory() + + Dim src = dir.CreateFile("a.vb") + src.WriteAllText( +"Class C + ''' Main method + Public Shared Sub Main() + Bad() + End Sub +End Class") + + Dim outWriter = New StringWriter(CultureInfo.InvariantCulture) + Dim csc = New MockVisualBasicCompiler(Nothing, dir.Path, + {"/define:_MYTYPE=""Empty"" ", "/nologo", "/out:a.dll", "/refonly", "/debug", "/deterministic", "/doc:doc.xml", "a.vb"}) + + Dim exitCode = csc.Run(outWriter) + Assert.Equal(0, exitCode) + + Dim refDll = Path.Combine(dir.Path, "a.dll") + Assert.True(File.Exists(refDll)) + + VerifyPEMetadata(File.OpenRead(refDll), + {"TypeDef:", "TypeDef:C"}, + {"MethodDef: Void Main()", "MethodDef: Void .ctor()"}, + {"CompilationRelaxationsAttribute", "RuntimeCompatibilityAttribute", "DebuggableAttribute", "STAThreadAttribute"} + ) + + Dim pdb = Path.Combine(dir.Path, "a.pdb") + Assert.False(File.Exists(pdb)) + + Dim doc = Path.Combine(dir.Path, "doc.xml") + Assert.True(File.Exists(doc)) + + Using reader As New StreamReader(doc) + Dim content = reader.ReadToEnd() + Dim expectedDoc = +" + + + +a + + + + + Main method + + +" + Assert.Equal(expectedDoc, content.Trim()) + End Using + + ' Clean up temp files + CleanupAllGeneratedFiles(dir.Path) + End Sub + 'Output with known but different extension diff --git a/src/Compilers/VisualBasic/Test/Emit/Emit/CompilationEmitTests.vb b/src/Compilers/VisualBasic/Test/Emit/Emit/CompilationEmitTests.vb index ff3349e10f719..cac1084d6cf3b 100644 --- a/src/Compilers/VisualBasic/Test/Emit/Emit/CompilationEmitTests.vb +++ b/src/Compilers/VisualBasic/Test/Emit/Emit/CompilationEmitTests.vb @@ -260,7 +260,7 @@ End Namespace ) - Dim emitResult As emitResult + Dim emitResult As EmitResult Dim mdOnlyImage As Byte() Using output = New MemoryStream() @@ -297,12 +297,246 @@ End Class End Using End Sub - + Sub RefAssembly_InvariantToSomeChanges() + + RefAssembly_InvariantToSomeChanges( +"Public Function M() As Integer + Return 1 +End Function", +"Public Function M() As Integer + Return 2 +End Function", True) + + RefAssembly_InvariantToSomeChanges( +"Public Function M() As Integer + Return 1 +End Function", +"Public Function M() As Integer +End Function", True) + + RefAssembly_InvariantToSomeChanges( +"", +"Private Sub M() +End Sub", False) ' Should be true. See follow-up issue https://github.com/dotnet/roslyn/issues/17612 + + RefAssembly_InvariantToSomeChanges( +"Friend Sub M() +End Sub", +"", False) + + RefAssembly_InvariantToSomeChanges( +"Public Structure S + Private Dim i As Integer +End Structure", +"Public Structure S +End Structure", False) + + End Sub + + Private Sub RefAssembly_InvariantToSomeChanges(change1 As String, change2 As String, expectMatch As Boolean) + Dim sourceTemplate As String = " +Public Class C + CHANGE +End Class" + + Dim name As String = GetUniqueName() + Dim source1 As String = sourceTemplate.Replace("CHANGE", change1) + Dim comp1 = CreateCompilationWithMscorlib(source1, + options:=TestOptions.DebugDll.WithDeterministic(True), assemblyName:=name) + + Dim image1 As Byte() + + Using output As New MemoryStream() + Dim EmitResult = comp1.Emit(output, options:=EmitOptions.Default.WithEmitMetadataOnly(True)) + Assert.True(EmitResult.Success) + EmitResult.Diagnostics.Verify() + image1 = output.ToArray() + End Using + + Dim source2 = sourceTemplate.Replace("CHANGE", change2) + Dim comp2 = CreateCompilationWithMscorlib(source2, + options:=TestOptions.DebugDll.WithDeterministic(True), assemblyName:=name) + + Dim image2 As Byte() + + Using output As New MemoryStream() + Dim EmitResult = comp2.Emit(output, options:=EmitOptions.Default.WithEmitMetadataOnly(True)) + Assert.True(EmitResult.Success) + EmitResult.Diagnostics.Verify() + image2 = output.ToArray() + End Using + + If expectMatch Then + AssertEx.Equal(image1, image2) + Else + AssertEx.NotEqual(image1, image2) + End If + End Sub + + + Sub RefAssembly_IgnoresSomeDiagnostics() + + RefAssembly_IgnoresSomeDiagnostics( +"Public Function M() As Integer +End Function", True) + + RefAssembly_IgnoresSomeDiagnostics( +"Public Function M() As Integer + Error( +End Function", False) ' Should be true. See follow-up issue https://github.com/dotnet/roslyn/issues/17612 + + RefAssembly_IgnoresSomeDiagnostics( +"Public Function M() As Error +End Function", False) ' Should be True. See follow-up issue https://github.com/dotnet/roslyn/issues/17612 + End Sub + + Private Sub RefAssembly_IgnoresSomeDiagnostics(change As String, expectSuccess As Boolean) + Dim sourceTemplate As String = " +Public Class C + CHANGE +End Class" + + Dim name As String = GetUniqueName() + Dim source As String = sourceTemplate.Replace("CHANGE", change) + Dim comp = CreateCompilationWithMscorlib(source, + options:=TestOptions.DebugDll.WithDeterministic(True), assemblyName:=name) + + Using output As New MemoryStream() + Dim EmitResult = comp.Emit(output, options:=EmitOptions.Default.WithEmitMetadataOnly(True)) + Assert.Equal(expectSuccess, EmitResult.Success) + Assert.Equal(Not expectSuccess, EmitResult.Diagnostics.Any()) + End Using + + End Sub + + + Sub VerifyRefAssembly() + Dim source = " +Public MustInherit Class PublicClass + Public Sub PublicMethod() + System.Console.Write(""Hello"") + End Sub + Private Sub PrivateMethod() + System.Console.Write(""Hello"") + End Sub + Protected Sub ProtectedMethod() + System.Console.Write(""Hello"") + End Sub + Friend Sub InternalMethod() + System.Console.Write(""Hello"") + End Sub + Public MustOverride Sub AbstractMethod() +End Class" + Dim comp As Compilation = CreateCompilation(source, references:={MscorlibRef}, + options:=TestOptions.DebugDll.WithDeterministic(True)) + + Dim emitRefOnly = EmitOptions.Default.WithEmitMetadataOnly(True) + + Dim verifier = CompileAndVerify(comp, emitOptions:=emitRefOnly, verify:=True) + + ' verify metadata (types, members, attributes) + Dim image = comp.EmitToImageReference(emitRefOnly) + Dim comp2 = CreateCompilation("", references:={MscorlibRef, image}, + options:=TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All)) + Dim assembly As AssemblySymbol = comp2.SourceModule.GetReferencedAssemblySymbols().Last() + Dim members = assembly.GlobalNamespace.GetMembers() + AssertEx.SetEqual(members.Select(Function(m) m.ToDisplayString()), + {"", "PublicClass"}) + + AssertEx.SetEqual( + DirectCast(assembly.GlobalNamespace.GetMember("PublicClass"), NamedTypeSymbol).GetMembers(). + Select(Function(m) m.ToTestDisplayString()), + {"Sub PublicClass.PublicMethod()", "Sub PublicClass.PrivateMethod()", + "Sub PublicClass.InternalMethod()", "Sub PublicClass.ProtectedMethod()", + "Sub PublicClass.AbstractMethod()", "Sub PublicClass..ctor()"}) + + AssertEx.SetEqual(assembly.GetAttributes().Select(Function(a) a.AttributeClass.ToTestDisplayString()), + {"System.Runtime.CompilerServices.CompilationRelaxationsAttribute", + "System.Runtime.CompilerServices.RuntimeCompatibilityAttribute", + "System.Diagnostics.DebuggableAttribute"}) + + Dim peImage = comp.EmitToArray(emitRefOnly) + VerifyMethodBodies(peImage, expectEmptyOrThrowNull:=True) + End Sub + + Private Shared Sub VerifyMethodBodies(peImage As ImmutableArray(Of Byte), expectEmptyOrThrowNull As Boolean) + Using peReader As New PEReader(peImage) + Dim metadataReader = peReader.GetMetadataReader() + For Each method In metadataReader.MethodDefinitions + Dim rva = metadataReader.GetMethodDefinition(method).RelativeVirtualAddress + If rva <> 0 Then + Dim il = peReader.GetMethodBody(rva).GetILBytes() + Dim throwNull = {CType(ILOpCode.Ldnull, Byte), CType(ILOpCode.Throw, Byte)} + If expectEmptyOrThrowNull Then + AssertEx.Equal(throwNull, il) + Else + AssertEx.NotEqual(throwNull, il) + End If + End If + Next + End Using + End Sub + + + Sub EmitMetadataOnly_NoPdbs() + Dim comp = CreateCompilation("", references:={MscorlibRef}, + options:=TestOptions.DebugDll.WithDeterministic(True)) + + Using output As New MemoryStream() + Using pdbOutput = New MemoryStream() + Assert.Throws(Of ArgumentException)(Function() comp.Emit(output, pdbOutput, + options:=EmitOptions.Default.WithEmitMetadataOnly(True))) + End Using + End Using + End Sub + + + Sub EmitMetadataOnly_NoMetadataPeStream() + Dim comp = CreateCompilation("", references:={MscorlibRef}, + options:=TestOptions.DebugDll.WithDeterministic(True)) + + Using output As New MemoryStream() + Using metadataPeOutput As New MemoryStream() + Assert.Throws(Of ArgumentException)(Function() comp.Emit(output, metadataPeStream:=metadataPeOutput, + options:=EmitOptions.Default.WithEmitMetadataOnly(True))) + End Using + End Using + End Sub + + + Sub EmitMetadata() + Dim source = +"Public MustInherit Class PublicClass + Public Sub PublicMethod + System.Console.Write(""Hello"") + End Sub +End Class " + Dim comp = CreateCompilation(source, references:={MscorlibRef}, + options:=TestOptions.DebugDll.WithDeterministic(True)) + + Using output As New MemoryStream() + Using pdbOutput As New MemoryStream() + Using metadataOutput As New MemoryStream() + Dim result = comp.Emit(output, pdbOutput, metadataPeStream:=metadataOutput) + Assert.True(result.Success) + Assert.NotEqual(0, output.Position) + Assert.NotEqual(0, pdbOutput.Position) + Assert.NotEqual(0, metadataOutput.Position) + End Using + End Using + End Using + + Dim peImage = comp.EmitToArray() + VerifyMethodBodies(peImage, expectEmptyOrThrowNull:=False) + End Sub + + + Public Sub Bug4344() Dim compilation = CompilationUtils.CreateCompilationWithMscorlibAndVBRuntime( - + Module M Sub Main() Dim a as String = "A" @@ -311,18 +545,18 @@ Module M End Sub End Module -) + ) CompileAndVerify(compilation) End Sub - + Public Sub Bug6981() ' tests different casing of the method Dim source = - + Imports System MustInherit Class Base @@ -343,7 +577,7 @@ Class Derived End Class - + CompileAndVerify(source, expectedOutput:=) source = - + Imports System MustInherit Class Base @@ -378,7 +612,7 @@ Imports System End Class - + CompileAndVerify(source, expectedOutput:=) Dim source = - + Imports System MustInherit Class Base @@ -437,7 +671,7 @@ Imports System End Class - + CompileAndVerify(source, expectedOutput:=) Dim source = - + Imports System Class Derived @@ -485,7 +719,7 @@ Imports System End Class - + Dim verifier = CompileAndVerify(source, additionalRefs:={TestReferences.SymbolsTests.DifferByCase.CsharpDifferCaseOverloads}, @@ -517,13 +751,13 @@ The authorities have been called.]]>) Public Sub EnsureModulesRoundTrip() Dim source = - + Module M Sub F() End Sub End Module - + Dim c As Compilation = CreateCompilationWithMscorlibAndVBRuntime(source) Dim s = New MemoryStream() @@ -543,13 +777,13 @@ End Module Public Sub TestRuntimeMetaDataVersion() Dim source = - + Class C1 Public Shared Sub Main() End Sub End Class - + Dim compilation = CreateCompilationWithReferences(source, {TestReferences.NetFx.v2_0_50727.mscorlib}, Nothing) Dim metadata = ModuleMetadata.CreateFromImage(compilation.EmitToArray()) @@ -564,13 +798,13 @@ End Module Public Sub TestCorFlags() Dim source = - + Class C1 Public Shared Sub Main() End Sub End Class - + Dim compilation = CreateCompilationWithMscorlib(source, options:=Nothing) Dim peHeaders = New peHeaders(compilation.EmitToStream()) @@ -597,13 +831,13 @@ End Module Public Sub TestCOFFAndPEOptionalHeaders32() Dim source = - + Class C1 Public Shared Sub Main() End Sub End Class - + Dim compilation = CreateCompilationWithMscorlib(source, options:=New VisualBasicCompilationOptions(OutputKind.DynamicallyLinkedLibrary).WithPlatform(Platform.AnyCpu)) Dim peHeaders = New peHeaders(compilation.EmitToStream()) @@ -658,13 +892,13 @@ End Module Public Sub TestCOFFAndPEOptionalHeadersArm() Dim source = - + Class C1 Public Shared Sub Main() End Sub End Class - + Dim compilation = CreateCompilationWithMscorlib(source, options:=New VisualBasicCompilationOptions(OutputKind.DynamicallyLinkedLibrary).WithPlatform(Platform.Arm)) Dim peHeaders = New peHeaders(compilation.EmitToStream()) @@ -719,13 +953,13 @@ End Module Public Sub TestCOFFAndPEOptionalHeaders64() Dim source = - + Class C1 Public Shared Sub Main() End Sub End Class - + Dim compilation = CreateCompilationWithMscorlib(source, options:=New VisualBasicCompilationOptions(OutputKind.DynamicallyLinkedLibrary).WithPlatform(Platform.X64)) Dim peHeaders = New peHeaders(compilation.EmitToStream()) @@ -777,13 +1011,13 @@ End Module Public Sub CheckDllCharacteristicsHighEntropyVA() Dim source = - + Class C1 Public Shared Sub Main() End Sub End Class - + Dim compilation = CreateCompilationWithMscorlib(source) Dim peHeaders = New PEHeaders(compilation.EmitToStream(options:=New EmitOptions(highEntropyVirtualAddressSpace:=True))) @@ -791,17 +1025,17 @@ End Module End Sub - + Public Sub CheckDllCharacteristicsWinRtApp() Dim source = - + Class C1 Public Shared Sub Main() End Sub End Class - + Dim compilation = CreateCompilationWithMscorlib(source, options:=New VisualBasicCompilationOptions(OutputKind.WindowsRuntimeApplication)) Dim peHeaders = New peHeaders(compilation.EmitToStream()) @@ -812,13 +1046,13 @@ End Module Public Sub TestBaseAddress() Dim source = - + Class C1 Public Shared Sub Main() End Sub End Class - + ' last four hex digits get zero'ed out Dim compilation = CreateCompilationWithMscorlib(source, options:=TestOptions.ReleaseExe) @@ -854,13 +1088,13 @@ End Module Public Sub TestFileAlignment() Dim source = - + Class C1 Public Shared Sub Main() End Sub End Class - + Dim compilation = CreateCompilationWithMscorlib(source) Dim peHeaders = New PEHeaders(compilation.EmitToStream(options:=New EmitOptions(fileAlignment:=1024))) @@ -879,7 +1113,7 @@ End Module Dim source = - + Imports System Public Structure C @@ -949,7 +1183,7 @@ Imports System Namespace D End Namespace - + Dim sourceSymbolValidator = Sub(m As ModuleSymbol) Dim expectedGlobalMembers = {"C", "B", "A", "F", "G", "E", "D"} @@ -1124,7 +1358,7 @@ Imports System Public Sub TestSecurityPseudoCustomAttributeOnType() Dim source = - + Imports System.Security Imports System.Security.Permissions @@ -1150,7 +1384,7 @@ Module Program End Sub End Module - + Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(source) compilation.VerifyDiagnostics() @@ -1191,7 +1425,7 @@ End Module Public Sub TestSecurityPseudoCustomAttributeOnMethod() Dim source = - + Imports System.Security.Permissions public class C @@ -1205,7 +1439,7 @@ Module Program End Sub End Module - + Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(source) compilation.VerifyDiagnostics() @@ -1235,7 +1469,7 @@ End Module Public Sub TestSecurityPseudoCustomAttributeSameTypeSameAction() Dim source = - + Imports System.Security.Permissions <PrincipalPermission(SecurityAction.Demand, Role:="User1")> @@ -1248,7 +1482,7 @@ Module Program End Sub End Module - + Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(source) compilation.VerifyDiagnostics() @@ -1291,7 +1525,7 @@ End Module Public Sub TestSecurityPseudoCustomAttributeSameMethodSameAction() Dim source = - + Imports System.Security.Permissions public class C @@ -1306,7 +1540,7 @@ Module Program End Sub End Module - + Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(source) compilation.VerifyDiagnostics() @@ -1349,7 +1583,7 @@ End Module Public Sub TestSecurityPseudoCustomAttributeSameTypeDifferentAction() Dim source = - + Imports System.Security.Permissions <PrincipalPermission(SecurityAction.Demand, Role:="User1")> @@ -1362,7 +1596,7 @@ Module Program End Sub End Module - + Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(source) compilation.VerifyDiagnostics() @@ -1410,7 +1644,7 @@ End Module Public Sub TestSecurityPseudoCustomAttributeSameMethodDifferentAction() Dim source = - + Imports System.Security.Permissions public class C @@ -1425,7 +1659,7 @@ Module Program End Sub End Module - + Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(source) compilation.VerifyDiagnostics() @@ -1473,7 +1707,7 @@ End Module Public Sub TestSecurityPseudoCustomAttributeDifferentTypeSameAction() Dim source = - + Imports System.Security.Permissions public class C1 @@ -1494,7 +1728,7 @@ Module Program End Sub End Module - + Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(source) compilation.VerifyDiagnostics() @@ -1542,7 +1776,7 @@ End Module Public Sub TestSecurityPseudoCustomAttributeDifferentMethodSameAction() Dim source = - + Imports System.Security.Permissions <PrincipalPermission(SecurityAction.Demand, Role:="User1")> @@ -1558,7 +1792,7 @@ Module Program End Sub End Module - + Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(source) compilation.VerifyDiagnostics() @@ -1606,7 +1840,7 @@ End Module Public Sub TestSecurityPseudoCustomAttributesMultipleAssemblyTypeMethod() Dim source = - + Imports System.Security.Permissions <assembly: SecurityPermission(SecurityAction.RequestOptional, RemotingConfiguration:=true)> @@ -1624,7 +1858,7 @@ Module Program End Sub End Module - + Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(source) compilation.VerifyDiagnostics( @@ -1706,7 +1940,7 @@ End Module Public Sub TestSecurityPseudoCustomAttributesMultipleAssemblyTypeMethodSymbolApi() Dim source = - + Imports System Imports System.Security Imports System.Security.Permissions @@ -1730,7 +1964,7 @@ Module Program End Module end namespace - + Dim attributeValidator As Action(Of ModuleSymbol) = Sub([module] As ModuleSymbol) @@ -1753,7 +1987,7 @@ end namespace Dim emittedName = MetadataTypeName.FromNamespaceAndTypeName("System.Security.Permissions", "SecurityPermissionAttribute") Dim securityPermissionAttr As NamedTypeSymbol = sourceAssembly.CorLibrary.LookupTopLevelMetadataType(emittedName, True) - ' Verify + ' Verify Dim securityAttribute As Cci.SecurityAttribute = assemblySecurityAttributes.First() Assert.Equal(DeclarativeSecurityAction.RequestOptional, securityAttribute.Action) Dim typeAttribute = DirectCast(securityAttribute.Attribute, VisualBasicAttributeData) @@ -1763,7 +1997,7 @@ end namespace Assert.Equal(1, typeAttribute.CommonNamedArguments.Length) typeAttribute.VerifyNamedArgumentValue(0, "RemotingConfiguration", TypedConstantKind.Primitive, True) - ' Verify + ' Verify securityAttribute = assemblySecurityAttributes.Last() Assert.Equal(DeclarativeSecurityAction.RequestMinimum, securityAttribute.Action) typeAttribute = DirectCast(securityAttribute.Attribute, VisualBasicAttributeData) @@ -1841,11 +2075,11 @@ end namespace Dim source = > - + Class A End Class - + Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(source, TestOptions.ReleaseModule) compilation.VerifyDiagnostics() @@ -1877,11 +2111,11 @@ End Class Dim source = > - + Class A End Class - + Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(source, TestOptions.ReleaseDll) compilation.VerifyDiagnostics() @@ -1914,11 +2148,11 @@ End Class Dim source = > - + Class A End Class - + Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(source, TestOptions.ReleaseDll) compilation.VerifyDiagnostics() @@ -1951,11 +2185,11 @@ End Class Dim source = > - + Class A End Class - + Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(source, TestOptions.ReleaseDll) compilation.VerifyDiagnostics() @@ -1988,11 +2222,11 @@ End Class Dim source = > - + Class A End Class - + Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(source, TestOptions.ReleaseDll) compilation.VerifyDiagnostics() @@ -2020,11 +2254,11 @@ End Class Public Sub IllegalNameOverride() Dim source = - + Class A End Class - + Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(source, TestOptions.ReleaseDll) compilation.VerifyDiagnostics() @@ -2033,7 +2267,7 @@ End Class End Sub - + Public Sub PermissionSetAttribute_Fixup() Dim tempDir = Temp.CreateDirectory() Dim tempFile = tempDir.CreateFile("pset.xml") @@ -2050,7 +2284,7 @@ End Class Dim source = - + imports System.Security.Permissions <PermissionSetAttribute(SecurityAction.Deny, File:="pset.xml")> @@ -2060,7 +2294,7 @@ public class AClass end sub End Class - + Dim syntaxTree = CreateParseTree(source) Dim resolver = New XmlFileResolver(tempDir.Path) @@ -2099,11 +2333,11 @@ End Class End Sub - + Public Sub PermissionSetAttributeInvalidFile() Dim source = - + imports System.Security.Permissions <PermissionSetAttribute(SecurityAction.Deny, File:="NonExistentFile.xml")> @@ -2111,7 +2345,7 @@ imports System.Security.Permissions public class AClass end class - + CreateCompilationWithMscorlib(source, options:=TestOptions.ReleaseDll.WithXmlReferenceResolver(XmlFileResolver.Default)).VerifyDiagnostics( Diagnostic(ERRID.WRN_UseOfObsoleteSymbol2, "SecurityAction.Deny").WithArguments("Deny", "Deny is obsolete and will be removed in a future release of the .NET Framework. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information."), @@ -2124,14 +2358,14 @@ end class Public Sub PermissionSetAttribute_NoResolver() Dim source = - + imports System.Security.Permissions <PermissionSetAttribute(SecurityAction.Deny, File:="NonExistentFile.xml")> public class AClass end class - + CreateCompilationWithMscorlib(source, options:=TestOptions.ReleaseDll.WithXmlReferenceResolver(Nothing)).VerifyDiagnostics( Diagnostic(ERRID.WRN_UseOfObsoleteSymbol2, "SecurityAction.Deny").WithArguments("Deny", "Deny is obsolete and will be removed in a future release of the .NET Framework. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.").WithLocation(3, 25), @@ -2139,11 +2373,11 @@ end class End Sub - + Public Sub ReDimPreserve() Dim source = - + Module MainModule Sub Main() Dim o As Object @@ -2151,18 +2385,18 @@ Module MainModule End Sub End Module - + Dim comp = CreateCompilationWithMscorlibAndVBRuntime(source) CompileAndVerify(comp) End Sub - + Public Sub ReDimPreserve2() Dim source = - + Module MainModule Sub Main() Dim oo(123) As Object @@ -2170,18 +2404,18 @@ Module MainModule End Sub End Module - + Dim comp = CreateCompilationWithMscorlibAndVBRuntime(source) CompileAndVerify(comp) End Sub - + Public Sub ReDimPreserve3() Dim source = - + Module MainModule Sub Main() ReDim Preserve F().M1(15) @@ -2191,21 +2425,21 @@ Module MainModule End Function End Module - + Dim comp = CreateCompilationWithMscorlibAndVBRuntime(source) CompileAndVerify(comp) End Sub - + Public Sub PermissionSetAttributeFileReadError() Dim tempDir = Temp.CreateDirectory() Dim filePath = Path.Combine(tempDir.Path, "pset_01.xml") Dim source = - + imports System.Security.Permissions <PermissionSetAttribute(SecurityAction.Deny, File:="pset_01.xml")> @@ -2215,7 +2449,7 @@ public class AClass end Sub End Class - + Dim syntaxTree = CreateParseTree(source) Dim comp As VisualBasicCompilation @@ -2251,14 +2485,14 @@ End Class End Sub - + Public Sub Bug654522() Dim refSource = - + Public Interface I(Of W As Structure) : End Interface - + Dim comp = CreateCompilationWithMscorlib(refSource).VerifyDiagnostics() @@ -2293,24 +2527,24 @@ Public Interface I(Of W As Structure) : End Interface End Sub - + Public Sub EmitNetModuleWithReferencedNetModule() Dim source1 = - + Public Class A End Class - + Dim source2 = - + Public Class B Inherits A End Class - + Dim comp = CreateCompilationWithMscorlib(source1, OutputKind.NetModule) Dim metadataRef = comp.EmitToImageReference() @@ -2321,11 +2555,11 @@ End Class Public Sub PlatformMismatch_01() Dim refSource = - + public interface ITestPlatform End interface - + Dim refCompilation = CreateCompilationWithReferences(refSource, New MetadataReference() {}, TestOptions.ReleaseDll.WithPlatform(Platform.Itanium)) @@ -2336,12 +2570,12 @@ End interface Dim useSource = - + public interface IUsePlatform Function M() As ITestPlatform End interface - + Dim useCompilation = CreateCompilationWithReferences(useSource, {compRef}, @@ -2414,11 +2648,11 @@ BC42372: Referenced assembly 'PlatformMismatch, Version=0.0.0.0, Culture=neutral Public Sub PlatformMismatch_02() Dim refSource = - + public interface ITestPlatform End interface - + Dim refCompilation = CreateCompilationWithReferences(refSource, New MetadataReference() {}, TestOptions.ReleaseModule.WithPlatform(Platform.Itanium)) @@ -2428,12 +2662,12 @@ End interface Dim useSource = - + public interface IUsePlatform Function M() As ITestPlatform End interface - + Dim useCompilation = CreateCompilationWithReferences(useSource, {imageRef}, @@ -2467,11 +2701,11 @@ BC37214: Assembly and module 'PlatformMismatch.netmodule' cannot target differen Public Sub PlatformMismatch_03() Dim refSource = - + public interface ITestPlatform End interface - + Dim refCompilation = CreateCompilationWithReferences(refSource, New MetadataReference() {}, TestOptions.ReleaseDll.WithPlatform(Platform.X86)) @@ -2482,12 +2716,12 @@ End interface Dim useSource = - + public interface IUsePlatform Function M() As ITestPlatform End interface - + Dim useCompilation = CreateCompilationWithReferences(useSource, @@ -2531,11 +2765,11 @@ BC42372: Referenced assembly 'PlatformMismatch, Version=0.0.0.0, Culture=neutral Public Sub PlatformMismatch_04() Dim refSource = - + public interface ITestPlatform End interface - + Dim refCompilation = CreateCompilationWithReferences(refSource, New MetadataReference() {}, TestOptions.ReleaseModule.WithPlatform(Platform.X86)) @@ -2545,12 +2779,12 @@ End interface Dim useSource = - + public interface IUsePlatform Function M() As ITestPlatform End interface - + Dim useCompilation = CreateCompilationWithReferences(useSource, {imageRef}, @@ -2566,11 +2800,11 @@ BC37214: Assembly and module 'PlatformMismatch.netmodule' cannot target differen Public Sub PlatformMismatch_05() Dim refSource = - + public interface ITestPlatform End interface - + Dim refCompilation = CreateCompilationWithReferences(refSource, New MetadataReference() {}, TestOptions.ReleaseDll.WithPlatform(Platform.AnyCpu)) @@ -2581,12 +2815,12 @@ End interface Dim useSource = - + public interface IUsePlatform Function M() As ITestPlatform End interface - + Dim useCompilation = CreateCompilationWithReferences(useSource, @@ -2595,7 +2829,7 @@ End interface AssertTheseDiagnostics(useCompilation.Emit(New MemoryStream()).Diagnostics, -) + ) useCompilation = CreateCompilationWithReferences(useSource, {imageRef}, @@ -2603,7 +2837,7 @@ End interface AssertTheseDiagnostics(useCompilation.Emit(New MemoryStream()).Diagnostics, -) + ) useCompilation = CreateCompilationWithReferences(useSource, {compRef}, @@ -2611,7 +2845,7 @@ End interface AssertTheseDiagnostics(useCompilation.Emit(New MemoryStream()).Diagnostics, -) + ) useCompilation = CreateCompilationWithReferences(useSource, {imageRef}, @@ -2619,18 +2853,18 @@ End interface AssertTheseDiagnostics(useCompilation.Emit(New MemoryStream()).Diagnostics, -) + ) End Sub Public Sub PlatformMismatch_06() Dim refSource = - + public interface ITestPlatform End interface - + Dim refCompilation = CreateCompilationWithReferences(refSource, New MetadataReference() {}, TestOptions.ReleaseModule.WithPlatform(Platform.AnyCpu)) @@ -2640,12 +2874,12 @@ End interface Dim useSource = - + public interface IUsePlatform Function M() As ITestPlatform End interface - + Dim useCompilation = CreateCompilationWithReferences(useSource, {imageRef}, @@ -2653,18 +2887,18 @@ End interface AssertTheseDiagnostics(useCompilation.Emit(New MemoryStream()).Diagnostics, -) + ) End Sub Public Sub PlatformMismatch_07() Dim refSource = - + public interface ITestPlatform End interface - + Dim refCompilation = CreateCompilationWithReferences(refSource, New MetadataReference() {}, TestOptions.ReleaseDll.WithPlatform(Platform.Itanium)) @@ -2675,12 +2909,12 @@ End interface Dim useSource = - + public interface IUsePlatform Function M() As ITestPlatform End interface - + Dim useCompilation = CreateCompilationWithReferences(useSource, @@ -2689,7 +2923,7 @@ End interface AssertTheseDiagnostics(useCompilation.Emit(New MemoryStream()).Diagnostics, -) + ) useCompilation = CreateCompilationWithReferences(useSource, {imageRef}, @@ -2697,7 +2931,7 @@ End interface AssertTheseDiagnostics(useCompilation.Emit(New MemoryStream()).Diagnostics, -) + ) useCompilation = CreateCompilationWithReferences(useSource, {compRef}, @@ -2705,7 +2939,7 @@ End interface AssertTheseDiagnostics(useCompilation.Emit(New MemoryStream()).Diagnostics, -) + ) useCompilation = CreateCompilationWithReferences(useSource, {imageRef}, @@ -2713,18 +2947,18 @@ End interface AssertTheseDiagnostics(useCompilation.Emit(New MemoryStream()).Diagnostics, -) + ) End Sub Public Sub PlatformMismatch_08() Dim refSource = - + public interface ITestPlatform End interface - + Dim refCompilation = CreateCompilationWithReferences(refSource, New MetadataReference() {}, TestOptions.ReleaseModule.WithPlatform(Platform.Itanium)) @@ -2734,12 +2968,12 @@ End interface Dim useSource = - + public interface IUsePlatform Function M() As ITestPlatform End interface - + Dim useCompilation = CreateCompilationWithReferences(useSource, {imageRef}, @@ -2747,16 +2981,16 @@ End interface AssertTheseDiagnostics(useCompilation.Emit(New MemoryStream()).Diagnostics, -) + ) End Sub Public Sub Bug769741() Dim source = - - - + + + Dim compilation = CreateCompilationWithReferences(source, {TestReferences.SymbolsTests.netModule.x64COFF}, TestOptions.DebugDll) @@ -2770,7 +3004,7 @@ End interface Dim useSource = - + Class Viewable Sub Maine() Dim v = New Viewable() @@ -2792,7 +3026,7 @@ End interface End Property End Class - + Dim compilation = CreateCompilationWithMscorlib(useSource, TestOptions.ReleaseDll) Dim metadataReader = ModuleMetadata.CreateFromImage(compilation.EmitToArray()).Module.GetMetadataReader() @@ -2842,7 +3076,7 @@ End interface ' examining the emitted binary. Dim source = - + Class C Function M() As ULong Return &H8675309ABCDE4225UL @@ -2854,7 +3088,7 @@ Class C End Property End Class - + Dim compilation = CreateCompilationWithMscorlib(source, TestOptions.ReleaseDll) Using stream As Stream = compilation.EmitToStream() @@ -2867,7 +3101,7 @@ End Class Dim firstMatch = IndexOfPattern(bytes, 0, pattern) Assert.True(firstMatch >= 0, "Couldn't find the expected byte pattern in the output.") Dim secondMatch = IndexOfPattern(bytes, firstMatch + 1, pattern) - Assert.True(secondMatch < 0, "Expected to find just one occurrence of the pattern in the output.") + Assert.True(secondMatch <0, "Expected to find just one occurrence of the pattern in the output.") End Using End Sub diff --git a/src/Test/Utilities/Portable/Metadata/MetadataReaderUtils.cs b/src/Test/Utilities/Portable/Metadata/MetadataReaderUtils.cs index 5749417ce8617..e12525d9face3 100644 --- a/src/Test/Utilities/Portable/Metadata/MetadataReaderUtils.cs +++ b/src/Test/Utilities/Portable/Metadata/MetadataReaderUtils.cs @@ -279,7 +279,6 @@ public static string Dump(this MetadataReader reader, EntityHandle handle) } } - // PROTOTYPE it would be better to shared the implementation with PdbToXml private sealed class ConstantSignatureVisualizer : ISignatureTypeProvider { public static readonly ConstantSignatureVisualizer Instance = new ConstantSignatureVisualizer(); @@ -296,13 +295,11 @@ public string GetByReferenceType(string elementType) public string GetFunctionPointerType(MethodSignature signature) { - // TODO: return "method-ptr"; } public string GetGenericInstantiation(string genericType, ImmutableArray typeArguments) { - // using {} since the result is embedded in XML return genericType + "{" + string.Join(", ", typeArguments) + "}"; } From 41399cd5f1e85b91e9e3a736838bf213bbb63deb Mon Sep 17 00:00:00 2001 From: Julien Couvreur Date: Thu, 16 Mar 2017 11:25:40 -0700 Subject: [PATCH 08/14] PR feedback --- .../Portable/CSharpResources.Designer.cs | 9 + .../CSharp/Portable/CSharpResources.resx | 3 + .../CommandLine/CSharpCommandLineParser.cs | 5 + .../CSharp/Portable/Errors/ErrorCode.cs | 1 + .../Test/CommandLine/CommandLineTests.cs | 12 + .../VisualBasicCommandLineParser.vb | 4 + .../VisualBasic/Portable/Errors/Errors.vb | 1 + .../Portable/VBResources.Designer.vb | 9 + .../VisualBasic/Portable/VBResources.resx | 3 + .../Test/CommandLine/CommandLineTests.vb | 14 +- .../Test/Emit/Emit/CompilationEmitTests.vb | 294 +++++++++--------- 11 files changed, 205 insertions(+), 150 deletions(-) diff --git a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs index 334e5df8f435f..1ee083781590c 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs +++ b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs @@ -6766,6 +6766,15 @@ internal static string ERR_NoNamespacePrivate { } } + /// + /// Looks up a localized string similar to Cannot compile net modules when using /refout or /refonly.. + /// + internal static string ERR_NoNetModuleOutputWhenRefOutOrRefOnly { + get { + return ResourceManager.GetString("ERR_NoNetModuleOutputWhenRefOutOrRefOnly", resourceCulture); + } + } + /// /// Looks up a localized string similar to Cannot create an instance of the abstract class or interface '{0}'. /// diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index d696a46fa4ab5..6f947e4563a11 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -2291,6 +2291,9 @@ If such a class is used as a base class and if the deriving class defines a dest Do not use refout when using refonly. + + Cannot compile net modules when using /refout or /refonly. + Overloadable operator expected diff --git a/src/Compilers/CSharp/Portable/CommandLine/CSharpCommandLineParser.cs b/src/Compilers/CSharp/Portable/CommandLine/CSharpCommandLineParser.cs index 14e62586d2199..eea38cd266404 100644 --- a/src/Compilers/CSharp/Portable/CommandLine/CSharpCommandLineParser.cs +++ b/src/Compilers/CSharp/Portable/CommandLine/CSharpCommandLineParser.cs @@ -1169,6 +1169,11 @@ internal sealed override CommandLineArguments CommonParse(IEnumerable ar AddDiagnostic(diagnostics, diagnosticOptions, ErrorCode.ERR_NoRefOutWhenRefOnly); } + if (outputKind == OutputKind.NetModule && (metadataOnly || outputRefFilePath != null)) + { + AddDiagnostic(diagnostics, diagnosticOptions, ErrorCode.ERR_NoNetModuleOutputWhenRefOutOrRefOnly); + } + if (!IsScriptRunner && !sourceFilesSpecified && (outputKind.IsNetModule() || !resourcesOrModulesSpecified)) { AddDiagnostic(diagnostics, diagnosticOptions, ErrorCode.WRN_NoSources); diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index fcf79b3f0f500..611fdd2512c4d 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -1461,5 +1461,6 @@ internal enum ErrorCode ERR_Merge_conflict_marker_encountered = 8300, ERR_NoRefOutWhenRefOnly = 8301, + ERR_NoNetModuleOutputWhenRefOutOrRefOnly = 8302, } } \ No newline at end of file diff --git a/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs b/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs index 85cb3f4ae5ae1..7ba917dec345f 100644 --- a/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs +++ b/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs @@ -2794,6 +2794,18 @@ public void ParseOut() // error CS8301: Do not use refout when using refonly. Diagnostic(ErrorCode.ERR_NoRefOutWhenRefOnly).WithLocation(1, 1)); + parsedArgs = DefaultParse(new[] { @"/refout:ref.dll", "/target:module", "a.cs" }, baseDirectory); + parsedArgs.Errors.Verify( + // error CS8302: Cannot compile net modules when using /refout or /refonly. + Diagnostic(ErrorCode.ERR_NoNetModuleOutputWhenRefOutOrRefOnly).WithLocation(1, 1) + ); + + parsedArgs = DefaultParse(new[] { @"/refonly", "/target:module", "a.cs" }, baseDirectory); + parsedArgs.Errors.Verify( + // error CS8302: Cannot compile net modules when using /refout or /refonly. + Diagnostic(ErrorCode.ERR_NoNetModuleOutputWhenRefOutOrRefOnly).WithLocation(1, 1) + ); + // Dev11 reports CS2007: Unrecognized option: '/out' parsedArgs = DefaultParse(new[] { @"/out", "a.cs" }, baseDirectory); parsedArgs.Errors.Verify( diff --git a/src/Compilers/VisualBasic/Portable/CommandLine/VisualBasicCommandLineParser.vb b/src/Compilers/VisualBasic/Portable/CommandLine/VisualBasicCommandLineParser.vb index ec391826b1dc5..0b8d40df5a51d 100644 --- a/src/Compilers/VisualBasic/Portable/CommandLine/VisualBasicCommandLineParser.vb +++ b/src/Compilers/VisualBasic/Portable/CommandLine/VisualBasicCommandLineParser.vb @@ -1218,6 +1218,10 @@ lVbRuntimePlus: AddDiagnostic(diagnostics, ERRID.ERR_NoRefOutWhenRefOnly) End If + If outputKind = OutputKind.NetModule AndAlso (metadataOnly OrElse outputRefFileName IsNot Nothing) Then + AddDiagnostic(diagnostics, ERRID.ERR_NoNetModuleOutputWhenRefOutOrRefOnly) + End If + If Not IsScriptRunner AndAlso Not hasSourceFiles AndAlso managedResources.IsEmpty() Then ' VB displays help when there is nothing specified on the command line If flattenedArgs.Any Then diff --git a/src/Compilers/VisualBasic/Portable/Errors/Errors.vb b/src/Compilers/VisualBasic/Portable/Errors/Errors.vb index 8a1590c3faa59..b3e8649f35eb1 100644 --- a/src/Compilers/VisualBasic/Portable/Errors/Errors.vb +++ b/src/Compilers/VisualBasic/Portable/Errors/Errors.vb @@ -1726,6 +1726,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ERR_Merge_conflict_marker_encountered = 37284 ERR_NoRefOutWhenRefOnly = 37285 + ERR_NoNetModuleOutputWhenRefOutOrRefOnly = 37286 '// WARNINGS BEGIN HERE WRN_UseOfObsoleteSymbol2 = 40000 diff --git a/src/Compilers/VisualBasic/Portable/VBResources.Designer.vb b/src/Compilers/VisualBasic/Portable/VBResources.Designer.vb index 1dd9a3c2313a4..1bc0c8a864e7d 100644 --- a/src/Compilers/VisualBasic/Portable/VBResources.Designer.vb +++ b/src/Compilers/VisualBasic/Portable/VBResources.Designer.vb @@ -8070,6 +8070,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic End Get End Property + ''' + ''' Looks up a localized string similar to Cannot compile net modules when using /refout or /refonly.. + ''' + Friend ReadOnly Property ERR_NoNetModuleOutputWhenRefOutOrRefOnly() As String + Get + Return ResourceManager.GetString("ERR_NoNetModuleOutputWhenRefOutOrRefOnly", resourceCulture) + End Get + End Property + ''' ''' Looks up a localized string similar to Member '{0}' cannot be initialized in an object initializer expression because it is not a field or property.. ''' diff --git a/src/Compilers/VisualBasic/Portable/VBResources.resx b/src/Compilers/VisualBasic/Portable/VBResources.resx index b24563d895c33..edebd886374e4 100644 --- a/src/Compilers/VisualBasic/Portable/VBResources.resx +++ b/src/Compilers/VisualBasic/Portable/VBResources.resx @@ -5470,4 +5470,7 @@ Do not use refout when using refonly. + + Cannot compile net modules when using /refout or /refonly. + \ No newline at end of file diff --git a/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb b/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb index 01b6632208cae..7fbd0d3569006 100644 --- a/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb +++ b/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb @@ -2765,14 +2765,22 @@ print Goodbye, World" Assert.Equal("MyBinary.dll", parsedArgs.CompilationOptions.ModuleName) Assert.Equal("C:\My Folder", parsedArgs.OutputDirectory) - parsedArgs = DefaultParse({"/refout:", "a.cs"}, baseDirectory) + parsedArgs = DefaultParse({"/refout:", "a.vb"}, baseDirectory) parsedArgs.Errors.Verify( Diagnostic(ERRID.ERR_ArgumentRequired).WithArguments("refout", ":").WithLocation(1, 1)) - parsedArgs = DefaultParse({"/refout:ref.dll", "/refonly", "a.cs"}, baseDirectory) + parsedArgs = DefaultParse({"/refout:ref.dll", "/refonly", "a.vb"}, baseDirectory) parsedArgs.Errors.Verify( Diagnostic(ERRID.ERR_NoRefOutWhenRefOnly).WithLocation(1, 1)) + parsedArgs = DefaultParse({"/refout:ref.dll", "/target:module", "a.vb"}, baseDirectory) + parsedArgs.Errors.Verify( + Diagnostic(ERRID.ERR_NoNetModuleOutputWhenRefOutOrRefOnly).WithLocation(1, 1)) + + parsedArgs = DefaultParse({"/refonly", "/target:module", "a.vb"}, baseDirectory) + parsedArgs.Errors.Verify( + Diagnostic(ERRID.ERR_NoNetModuleOutputWhenRefOutOrRefOnly).WithLocation(1, 1)) + parsedArgs = DefaultParse({"/out:C:\""My Folder""\MyBinary.dll", "/t:library", "a.vb"}, baseDirectory) parsedArgs.Errors.Verify( Diagnostic(ERRID.FTL_InputFileNameTooLong).WithArguments("C:""My Folder\MyBinary.dll").WithLocation(1, 1)) @@ -8063,7 +8071,7 @@ a Using refPeReader As New PEReader(peStream) Dim metadataReader = refPeReader.GetMetadataReader() - ' The types And members that are included needs further refinement. + ' The types and members that are included needs further refinement. ' See issue https://github.com/dotnet/roslyn/issues/17612 AssertEx.SetEqual(metadataReader.TypeDefinitions.Select(Function(t) metadataReader.Dump(t)), types) diff --git a/src/Compilers/VisualBasic/Test/Emit/Emit/CompilationEmitTests.vb b/src/Compilers/VisualBasic/Test/Emit/Emit/CompilationEmitTests.vb index cac1084d6cf3b..75c11c5af0765 100644 --- a/src/Compilers/VisualBasic/Test/Emit/Emit/CompilationEmitTests.vb +++ b/src/Compilers/VisualBasic/Test/Emit/Emit/CompilationEmitTests.vb @@ -532,11 +532,11 @@ End Class " End Sub - + Public Sub Bug4344() Dim compilation = CompilationUtils.CreateCompilationWithMscorlibAndVBRuntime( - + Module M Sub Main() Dim a as String = "A" @@ -545,18 +545,18 @@ Module M End Sub End Module - ) +) CompileAndVerify(compilation) End Sub - + Public Sub Bug6981() ' tests different casing of the method Dim source = - + Imports System MustInherit Class Base @@ -577,7 +577,7 @@ Class Derived End Class - + CompileAndVerify(source, expectedOutput:=) source = - + Imports System MustInherit Class Base @@ -612,7 +612,7 @@ Imports System End Class - + CompileAndVerify(source, expectedOutput:=) Dim source = - + Imports System MustInherit Class Base @@ -671,7 +671,7 @@ Imports System End Class - + CompileAndVerify(source, expectedOutput:=) Dim source = - + Imports System Class Derived @@ -719,7 +719,7 @@ Imports System End Class - + Dim verifier = CompileAndVerify(source, additionalRefs:={TestReferences.SymbolsTests.DifferByCase.CsharpDifferCaseOverloads}, @@ -751,13 +751,13 @@ The authorities have been called.]]>) Public Sub EnsureModulesRoundTrip() Dim source = - + Module M Sub F() End Sub End Module - + Dim c As Compilation = CreateCompilationWithMscorlibAndVBRuntime(source) Dim s = New MemoryStream() @@ -777,13 +777,13 @@ End Module Public Sub TestRuntimeMetaDataVersion() Dim source = - + Class C1 Public Shared Sub Main() End Sub End Class - + Dim compilation = CreateCompilationWithReferences(source, {TestReferences.NetFx.v2_0_50727.mscorlib}, Nothing) Dim metadata = ModuleMetadata.CreateFromImage(compilation.EmitToArray()) @@ -798,13 +798,13 @@ End Module Public Sub TestCorFlags() Dim source = - + Class C1 Public Shared Sub Main() End Sub End Class - + Dim compilation = CreateCompilationWithMscorlib(source, options:=Nothing) Dim peHeaders = New peHeaders(compilation.EmitToStream()) @@ -831,13 +831,13 @@ End Module Public Sub TestCOFFAndPEOptionalHeaders32() Dim source = - + Class C1 Public Shared Sub Main() End Sub End Class - + Dim compilation = CreateCompilationWithMscorlib(source, options:=New VisualBasicCompilationOptions(OutputKind.DynamicallyLinkedLibrary).WithPlatform(Platform.AnyCpu)) Dim peHeaders = New peHeaders(compilation.EmitToStream()) @@ -892,13 +892,13 @@ End Module Public Sub TestCOFFAndPEOptionalHeadersArm() Dim source = - + Class C1 Public Shared Sub Main() End Sub End Class - + Dim compilation = CreateCompilationWithMscorlib(source, options:=New VisualBasicCompilationOptions(OutputKind.DynamicallyLinkedLibrary).WithPlatform(Platform.Arm)) Dim peHeaders = New peHeaders(compilation.EmitToStream()) @@ -953,13 +953,13 @@ End Module Public Sub TestCOFFAndPEOptionalHeaders64() Dim source = - + Class C1 Public Shared Sub Main() End Sub End Class - + Dim compilation = CreateCompilationWithMscorlib(source, options:=New VisualBasicCompilationOptions(OutputKind.DynamicallyLinkedLibrary).WithPlatform(Platform.X64)) Dim peHeaders = New peHeaders(compilation.EmitToStream()) @@ -1011,13 +1011,13 @@ End Module Public Sub CheckDllCharacteristicsHighEntropyVA() Dim source = - + Class C1 Public Shared Sub Main() End Sub End Class - + Dim compilation = CreateCompilationWithMscorlib(source) Dim peHeaders = New PEHeaders(compilation.EmitToStream(options:=New EmitOptions(highEntropyVirtualAddressSpace:=True))) @@ -1025,17 +1025,17 @@ End Module End Sub - + Public Sub CheckDllCharacteristicsWinRtApp() Dim source = - + Class C1 Public Shared Sub Main() End Sub End Class - + Dim compilation = CreateCompilationWithMscorlib(source, options:=New VisualBasicCompilationOptions(OutputKind.WindowsRuntimeApplication)) Dim peHeaders = New peHeaders(compilation.EmitToStream()) @@ -1046,13 +1046,13 @@ End Module Public Sub TestBaseAddress() Dim source = - + Class C1 Public Shared Sub Main() End Sub End Class - + ' last four hex digits get zero'ed out Dim compilation = CreateCompilationWithMscorlib(source, options:=TestOptions.ReleaseExe) @@ -1088,13 +1088,13 @@ End Module Public Sub TestFileAlignment() Dim source = - + Class C1 Public Shared Sub Main() End Sub End Class - + Dim compilation = CreateCompilationWithMscorlib(source) Dim peHeaders = New PEHeaders(compilation.EmitToStream(options:=New EmitOptions(fileAlignment:=1024))) @@ -1113,7 +1113,7 @@ End Module Dim source = - + Imports System Public Structure C @@ -1183,7 +1183,7 @@ Imports System Namespace D End Namespace - + Dim sourceSymbolValidator = Sub(m As ModuleSymbol) Dim expectedGlobalMembers = {"C", "B", "A", "F", "G", "E", "D"} @@ -1358,7 +1358,7 @@ Imports System Public Sub TestSecurityPseudoCustomAttributeOnType() Dim source = - + Imports System.Security Imports System.Security.Permissions @@ -1384,7 +1384,7 @@ Module Program End Sub End Module - + Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(source) compilation.VerifyDiagnostics() @@ -1425,7 +1425,7 @@ End Module Public Sub TestSecurityPseudoCustomAttributeOnMethod() Dim source = - + Imports System.Security.Permissions public class C @@ -1439,7 +1439,7 @@ Module Program End Sub End Module - + Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(source) compilation.VerifyDiagnostics() @@ -1469,7 +1469,7 @@ End Module Public Sub TestSecurityPseudoCustomAttributeSameTypeSameAction() Dim source = - + Imports System.Security.Permissions <PrincipalPermission(SecurityAction.Demand, Role:="User1")> @@ -1482,7 +1482,7 @@ Module Program End Sub End Module - + Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(source) compilation.VerifyDiagnostics() @@ -1525,7 +1525,7 @@ End Module Public Sub TestSecurityPseudoCustomAttributeSameMethodSameAction() Dim source = - + Imports System.Security.Permissions public class C @@ -1540,7 +1540,7 @@ Module Program End Sub End Module - + Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(source) compilation.VerifyDiagnostics() @@ -1583,7 +1583,7 @@ End Module Public Sub TestSecurityPseudoCustomAttributeSameTypeDifferentAction() Dim source = - + Imports System.Security.Permissions <PrincipalPermission(SecurityAction.Demand, Role:="User1")> @@ -1596,7 +1596,7 @@ Module Program End Sub End Module - + Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(source) compilation.VerifyDiagnostics() @@ -1644,7 +1644,7 @@ End Module Public Sub TestSecurityPseudoCustomAttributeSameMethodDifferentAction() Dim source = - + Imports System.Security.Permissions public class C @@ -1659,7 +1659,7 @@ Module Program End Sub End Module - + Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(source) compilation.VerifyDiagnostics() @@ -1707,7 +1707,7 @@ End Module Public Sub TestSecurityPseudoCustomAttributeDifferentTypeSameAction() Dim source = - + Imports System.Security.Permissions public class C1 @@ -1728,7 +1728,7 @@ Module Program End Sub End Module - + Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(source) compilation.VerifyDiagnostics() @@ -1776,7 +1776,7 @@ End Module Public Sub TestSecurityPseudoCustomAttributeDifferentMethodSameAction() Dim source = - + Imports System.Security.Permissions <PrincipalPermission(SecurityAction.Demand, Role:="User1")> @@ -1792,7 +1792,7 @@ Module Program End Sub End Module - + Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(source) compilation.VerifyDiagnostics() @@ -1840,7 +1840,7 @@ End Module Public Sub TestSecurityPseudoCustomAttributesMultipleAssemblyTypeMethod() Dim source = - + Imports System.Security.Permissions <assembly: SecurityPermission(SecurityAction.RequestOptional, RemotingConfiguration:=true)> @@ -1858,7 +1858,7 @@ Module Program End Sub End Module - + Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(source) compilation.VerifyDiagnostics( @@ -1940,7 +1940,7 @@ End Module Public Sub TestSecurityPseudoCustomAttributesMultipleAssemblyTypeMethodSymbolApi() Dim source = - + Imports System Imports System.Security Imports System.Security.Permissions @@ -1964,7 +1964,7 @@ Module Program End Module end namespace - + Dim attributeValidator As Action(Of ModuleSymbol) = Sub([module] As ModuleSymbol) @@ -1987,7 +1987,7 @@ end namespace Dim emittedName = MetadataTypeName.FromNamespaceAndTypeName("System.Security.Permissions", "SecurityPermissionAttribute") Dim securityPermissionAttr As NamedTypeSymbol = sourceAssembly.CorLibrary.LookupTopLevelMetadataType(emittedName, True) - ' Verify + ' Verify Dim securityAttribute As Cci.SecurityAttribute = assemblySecurityAttributes.First() Assert.Equal(DeclarativeSecurityAction.RequestOptional, securityAttribute.Action) Dim typeAttribute = DirectCast(securityAttribute.Attribute, VisualBasicAttributeData) @@ -1997,7 +1997,7 @@ end namespace Assert.Equal(1, typeAttribute.CommonNamedArguments.Length) typeAttribute.VerifyNamedArgumentValue(0, "RemotingConfiguration", TypedConstantKind.Primitive, True) - ' Verify + ' Verify securityAttribute = assemblySecurityAttributes.Last() Assert.Equal(DeclarativeSecurityAction.RequestMinimum, securityAttribute.Action) typeAttribute = DirectCast(securityAttribute.Attribute, VisualBasicAttributeData) @@ -2075,11 +2075,11 @@ end namespace Dim source = > - + Class A End Class - + Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(source, TestOptions.ReleaseModule) compilation.VerifyDiagnostics() @@ -2111,11 +2111,11 @@ End Class Dim source = > - + Class A End Class - + Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(source, TestOptions.ReleaseDll) compilation.VerifyDiagnostics() @@ -2148,11 +2148,11 @@ End Class Dim source = > - + Class A End Class - + Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(source, TestOptions.ReleaseDll) compilation.VerifyDiagnostics() @@ -2185,11 +2185,11 @@ End Class Dim source = > - + Class A End Class - + Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(source, TestOptions.ReleaseDll) compilation.VerifyDiagnostics() @@ -2222,11 +2222,11 @@ End Class Dim source = > - + Class A End Class - + Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(source, TestOptions.ReleaseDll) compilation.VerifyDiagnostics() @@ -2254,11 +2254,11 @@ End Class Public Sub IllegalNameOverride() Dim source = - + Class A End Class - + Dim compilation = CreateCompilationWithMscorlibAndVBRuntime(source, TestOptions.ReleaseDll) compilation.VerifyDiagnostics() @@ -2267,7 +2267,7 @@ End Class End Sub - + Public Sub PermissionSetAttribute_Fixup() Dim tempDir = Temp.CreateDirectory() Dim tempFile = tempDir.CreateFile("pset.xml") @@ -2284,7 +2284,7 @@ End Class Dim source = - + imports System.Security.Permissions <PermissionSetAttribute(SecurityAction.Deny, File:="pset.xml")> @@ -2294,7 +2294,7 @@ public class AClass end sub End Class - + Dim syntaxTree = CreateParseTree(source) Dim resolver = New XmlFileResolver(tempDir.Path) @@ -2333,11 +2333,11 @@ End Class End Sub - + Public Sub PermissionSetAttributeInvalidFile() Dim source = - + imports System.Security.Permissions <PermissionSetAttribute(SecurityAction.Deny, File:="NonExistentFile.xml")> @@ -2345,7 +2345,7 @@ imports System.Security.Permissions public class AClass end class - + CreateCompilationWithMscorlib(source, options:=TestOptions.ReleaseDll.WithXmlReferenceResolver(XmlFileResolver.Default)).VerifyDiagnostics( Diagnostic(ERRID.WRN_UseOfObsoleteSymbol2, "SecurityAction.Deny").WithArguments("Deny", "Deny is obsolete and will be removed in a future release of the .NET Framework. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information."), @@ -2358,14 +2358,14 @@ end class Public Sub PermissionSetAttribute_NoResolver() Dim source = - + imports System.Security.Permissions <PermissionSetAttribute(SecurityAction.Deny, File:="NonExistentFile.xml")> public class AClass end class - + CreateCompilationWithMscorlib(source, options:=TestOptions.ReleaseDll.WithXmlReferenceResolver(Nothing)).VerifyDiagnostics( Diagnostic(ERRID.WRN_UseOfObsoleteSymbol2, "SecurityAction.Deny").WithArguments("Deny", "Deny is obsolete and will be removed in a future release of the .NET Framework. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.").WithLocation(3, 25), @@ -2373,11 +2373,11 @@ end class End Sub - + Public Sub ReDimPreserve() Dim source = - + Module MainModule Sub Main() Dim o As Object @@ -2385,18 +2385,18 @@ Module MainModule End Sub End Module - + Dim comp = CreateCompilationWithMscorlibAndVBRuntime(source) CompileAndVerify(comp) End Sub - + Public Sub ReDimPreserve2() Dim source = - + Module MainModule Sub Main() Dim oo(123) As Object @@ -2404,18 +2404,18 @@ Module MainModule End Sub End Module - + Dim comp = CreateCompilationWithMscorlibAndVBRuntime(source) CompileAndVerify(comp) End Sub - + Public Sub ReDimPreserve3() Dim source = - + Module MainModule Sub Main() ReDim Preserve F().M1(15) @@ -2425,21 +2425,21 @@ Module MainModule End Function End Module - + Dim comp = CreateCompilationWithMscorlibAndVBRuntime(source) CompileAndVerify(comp) End Sub - + Public Sub PermissionSetAttributeFileReadError() Dim tempDir = Temp.CreateDirectory() Dim filePath = Path.Combine(tempDir.Path, "pset_01.xml") Dim source = - + imports System.Security.Permissions <PermissionSetAttribute(SecurityAction.Deny, File:="pset_01.xml")> @@ -2449,7 +2449,7 @@ public class AClass end Sub End Class - + Dim syntaxTree = CreateParseTree(source) Dim comp As VisualBasicCompilation @@ -2485,14 +2485,14 @@ End Class End Sub - + Public Sub Bug654522() Dim refSource = - + Public Interface I(Of W As Structure) : End Interface - + Dim comp = CreateCompilationWithMscorlib(refSource).VerifyDiagnostics() @@ -2527,24 +2527,24 @@ Public Interface I(Of W As Structure) : End Interface End Sub - + Public Sub EmitNetModuleWithReferencedNetModule() Dim source1 = - + Public Class A End Class - + Dim source2 = - + Public Class B Inherits A End Class - + Dim comp = CreateCompilationWithMscorlib(source1, OutputKind.NetModule) Dim metadataRef = comp.EmitToImageReference() @@ -2555,11 +2555,11 @@ End Class Public Sub PlatformMismatch_01() Dim refSource = - + public interface ITestPlatform End interface - + Dim refCompilation = CreateCompilationWithReferences(refSource, New MetadataReference() {}, TestOptions.ReleaseDll.WithPlatform(Platform.Itanium)) @@ -2570,12 +2570,12 @@ End interface Dim useSource = - + public interface IUsePlatform Function M() As ITestPlatform End interface - + Dim useCompilation = CreateCompilationWithReferences(useSource, {compRef}, @@ -2648,11 +2648,11 @@ BC42372: Referenced assembly 'PlatformMismatch, Version=0.0.0.0, Culture=neutral Public Sub PlatformMismatch_02() Dim refSource = - + public interface ITestPlatform End interface - + Dim refCompilation = CreateCompilationWithReferences(refSource, New MetadataReference() {}, TestOptions.ReleaseModule.WithPlatform(Platform.Itanium)) @@ -2662,12 +2662,12 @@ End interface Dim useSource = - + public interface IUsePlatform Function M() As ITestPlatform End interface - + Dim useCompilation = CreateCompilationWithReferences(useSource, {imageRef}, @@ -2701,11 +2701,11 @@ BC37214: Assembly and module 'PlatformMismatch.netmodule' cannot target differen Public Sub PlatformMismatch_03() Dim refSource = - + public interface ITestPlatform End interface - + Dim refCompilation = CreateCompilationWithReferences(refSource, New MetadataReference() {}, TestOptions.ReleaseDll.WithPlatform(Platform.X86)) @@ -2716,12 +2716,12 @@ End interface Dim useSource = - + public interface IUsePlatform Function M() As ITestPlatform End interface - + Dim useCompilation = CreateCompilationWithReferences(useSource, @@ -2765,11 +2765,11 @@ BC42372: Referenced assembly 'PlatformMismatch, Version=0.0.0.0, Culture=neutral Public Sub PlatformMismatch_04() Dim refSource = - + public interface ITestPlatform End interface - + Dim refCompilation = CreateCompilationWithReferences(refSource, New MetadataReference() {}, TestOptions.ReleaseModule.WithPlatform(Platform.X86)) @@ -2779,12 +2779,12 @@ End interface Dim useSource = - + public interface IUsePlatform Function M() As ITestPlatform End interface - + Dim useCompilation = CreateCompilationWithReferences(useSource, {imageRef}, @@ -2800,11 +2800,11 @@ BC37214: Assembly and module 'PlatformMismatch.netmodule' cannot target differen Public Sub PlatformMismatch_05() Dim refSource = - + public interface ITestPlatform End interface - + Dim refCompilation = CreateCompilationWithReferences(refSource, New MetadataReference() {}, TestOptions.ReleaseDll.WithPlatform(Platform.AnyCpu)) @@ -2815,12 +2815,12 @@ End interface Dim useSource = - + public interface IUsePlatform Function M() As ITestPlatform End interface - + Dim useCompilation = CreateCompilationWithReferences(useSource, @@ -2829,7 +2829,7 @@ End interface AssertTheseDiagnostics(useCompilation.Emit(New MemoryStream()).Diagnostics, - ) +) useCompilation = CreateCompilationWithReferences(useSource, {imageRef}, @@ -2837,7 +2837,7 @@ End interface AssertTheseDiagnostics(useCompilation.Emit(New MemoryStream()).Diagnostics, - ) +) useCompilation = CreateCompilationWithReferences(useSource, {compRef}, @@ -2845,7 +2845,7 @@ End interface AssertTheseDiagnostics(useCompilation.Emit(New MemoryStream()).Diagnostics, - ) +) useCompilation = CreateCompilationWithReferences(useSource, {imageRef}, @@ -2853,18 +2853,18 @@ End interface AssertTheseDiagnostics(useCompilation.Emit(New MemoryStream()).Diagnostics, - ) +) End Sub Public Sub PlatformMismatch_06() Dim refSource = - + public interface ITestPlatform End interface - + Dim refCompilation = CreateCompilationWithReferences(refSource, New MetadataReference() {}, TestOptions.ReleaseModule.WithPlatform(Platform.AnyCpu)) @@ -2874,12 +2874,12 @@ End interface Dim useSource = - + public interface IUsePlatform Function M() As ITestPlatform End interface - + Dim useCompilation = CreateCompilationWithReferences(useSource, {imageRef}, @@ -2887,18 +2887,18 @@ End interface AssertTheseDiagnostics(useCompilation.Emit(New MemoryStream()).Diagnostics, - ) +) End Sub Public Sub PlatformMismatch_07() Dim refSource = - + public interface ITestPlatform End interface - + Dim refCompilation = CreateCompilationWithReferences(refSource, New MetadataReference() {}, TestOptions.ReleaseDll.WithPlatform(Platform.Itanium)) @@ -2909,12 +2909,12 @@ End interface Dim useSource = - + public interface IUsePlatform Function M() As ITestPlatform End interface - + Dim useCompilation = CreateCompilationWithReferences(useSource, @@ -2923,7 +2923,7 @@ End interface AssertTheseDiagnostics(useCompilation.Emit(New MemoryStream()).Diagnostics, - ) +) useCompilation = CreateCompilationWithReferences(useSource, {imageRef}, @@ -2931,7 +2931,7 @@ End interface AssertTheseDiagnostics(useCompilation.Emit(New MemoryStream()).Diagnostics, - ) +) useCompilation = CreateCompilationWithReferences(useSource, {compRef}, @@ -2939,7 +2939,7 @@ End interface AssertTheseDiagnostics(useCompilation.Emit(New MemoryStream()).Diagnostics, - ) +) useCompilation = CreateCompilationWithReferences(useSource, {imageRef}, @@ -2947,18 +2947,18 @@ End interface AssertTheseDiagnostics(useCompilation.Emit(New MemoryStream()).Diagnostics, - ) +) End Sub Public Sub PlatformMismatch_08() Dim refSource = - + public interface ITestPlatform End interface - + Dim refCompilation = CreateCompilationWithReferences(refSource, New MetadataReference() {}, TestOptions.ReleaseModule.WithPlatform(Platform.Itanium)) @@ -2968,12 +2968,12 @@ End interface Dim useSource = - + public interface IUsePlatform Function M() As ITestPlatform End interface - + Dim useCompilation = CreateCompilationWithReferences(useSource, {imageRef}, @@ -2981,16 +2981,16 @@ End interface AssertTheseDiagnostics(useCompilation.Emit(New MemoryStream()).Diagnostics, - ) +) End Sub Public Sub Bug769741() Dim source = - - - + + + Dim compilation = CreateCompilationWithReferences(source, {TestReferences.SymbolsTests.netModule.x64COFF}, TestOptions.DebugDll) @@ -3004,7 +3004,7 @@ End interface Dim useSource = - + Class Viewable Sub Maine() Dim v = New Viewable() @@ -3026,7 +3026,7 @@ End interface End Property End Class - + Dim compilation = CreateCompilationWithMscorlib(useSource, TestOptions.ReleaseDll) Dim metadataReader = ModuleMetadata.CreateFromImage(compilation.EmitToArray()).Module.GetMetadataReader() @@ -3076,7 +3076,7 @@ End interface ' examining the emitted binary. Dim source = - + Class C Function M() As ULong Return &H8675309ABCDE4225UL @@ -3088,7 +3088,7 @@ Class C End Property End Class - + Dim compilation = CreateCompilationWithMscorlib(source, TestOptions.ReleaseDll) Using stream As Stream = compilation.EmitToStream() @@ -3101,7 +3101,7 @@ End Class Dim firstMatch = IndexOfPattern(bytes, 0, pattern) Assert.True(firstMatch >= 0, "Couldn't find the expected byte pattern in the output.") Dim secondMatch = IndexOfPattern(bytes, firstMatch + 1, pattern) - Assert.True(secondMatch <0, "Expected to find just one occurrence of the pattern in the output.") + Assert.True(secondMatch < 0, "Expected to find just one occurrence of the pattern in the output.") End Using End Sub From d0b713337092103ab40c30761a6c17a844410842 Mon Sep 17 00:00:00 2001 From: Julien Couvreur Date: Thu, 16 Mar 2017 12:31:54 -0700 Subject: [PATCH 09/14] Cosmetics --- .../Test/CommandLine/CommandLineTests.cs | 6 ++- .../Test/Emit/Emit/CompilationEmitTests.cs | 21 +++++---- .../Test/CommandLine/CommandLineTests.vb | 4 +- .../Test/Emit/Emit/CompilationEmitTests.vb | 44 +++++++++---------- 4 files changed, 38 insertions(+), 37 deletions(-) diff --git a/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs b/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs index 7ba917dec345f..9c14292036b9a 100644 --- a/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs +++ b/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs @@ -8885,7 +8885,8 @@ public static void Main() }"); var outWriter = new StringWriter(CultureInfo.InvariantCulture); - var csc = new MockCSharpCompiler(null, dir.Path, new[] { "/nologo", "/out:a.exe", "/refout:ref/a.dll", "/doc:doc.xml", "/deterministic", "a.cs" }); + var csc = new MockCSharpCompiler(null, dir.Path, + new[] { "/nologo", "/out:a.exe", "/refout:ref/a.dll", "/doc:doc.xml", "/deterministic", "a.cs" }); int exitCode = csc.Run(outWriter); Assert.Equal(0, exitCode); @@ -8971,7 +8972,8 @@ public void RefOutWithError() src.WriteAllText(@"class C { public static void Main() { error(); } }"); var outWriter = new StringWriter(CultureInfo.InvariantCulture); - var csc = new MockCSharpCompiler(null, dir.Path, new[] { "/nologo", "/out:a.dll", "/refout:ref/a.dll", "/deterministic", "a.cs" }); + var csc = new MockCSharpCompiler(null, dir.Path, + new[] { "/nologo", "/out:a.dll", "/refout:ref/a.dll", "/deterministic", "a.cs" }); int exitCode = csc.Run(outWriter); Assert.Equal(1, exitCode); diff --git a/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs b/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs index c12df3de95fbb..bfe5322acbc7b 100644 --- a/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs +++ b/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs @@ -236,12 +236,12 @@ public static void Main() } } - [Theory, - InlineData("public int M() { return 1; }", "public int M() { return 2; }", true), - InlineData("public int M() { return 1; }", "public int M() { error(); }", true), - InlineData("", "private void M() { }", false), // Should be true. See follow-up issue https://github.com/dotnet/roslyn/issues/17612 - InlineData("internal void M() { }", "", false), - InlineData("public struct S { private int i; }", "public struct S { }", false)] + [Theory] + [InlineData("public int M() { return 1; }", "public int M() { return 2; }", true)] + [InlineData("public int M() { return 1; }", "public int M() { error(); }", true)] + [InlineData("", "private void M() { }", false)] // Should be true. See follow-up issue https://github.com/dotnet/roslyn/issues/17612 + [InlineData("internal void M() { }", "", false)] + [InlineData("public struct S { private int i; }", "public struct S { }", false)] public void RefAssembly_InvariantToSomeChanges(string change1, string change2, bool expectMatch) { string sourceTemplate = @" @@ -289,11 +289,10 @@ public class C } } - [Theory, - InlineData("public int M() { error(); }", true), - InlineData("public int M() { error() }", false), // Should be true. See follow-up issue https://github.com/dotnet/roslyn/issues/17612 - InlineData("public Error M() { return null; }", false), // Should be true. See follow-up issue https://github.com/dotnet/roslyn/issues/17612 - ] + [Theory] + [InlineData("public int M() { error(); }", true)] + [InlineData("public int M() { error() }", false)] // Should be true. See follow-up issue https://github.com/dotnet/roslyn/issues/17612 + [InlineData("public Error M() { return null; }", false)] // Should be true. See follow-up issue https://github.com/dotnet/roslyn/issues/17612 public void RefAssembly_IgnoresSomeDiagnostics(string change, bool expectSuccess) { string sourceTemplate = @" diff --git a/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb b/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb index 7fbd0d3569006..026a2784913ba 100644 --- a/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb +++ b/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb @@ -7996,7 +7996,7 @@ End Class End Sub - Sub RefOut() + Public Sub RefOut() Dim dir = Temp.CreateDirectory() dir.CreateDirectory("ref") @@ -8128,7 +8128,7 @@ outWriter.ToString().Trim()) End Sub - Sub RefOnly() + Public Sub RefOnly() Dim dir = Temp.CreateDirectory() Dim src = dir.CreateFile("a.vb") diff --git a/src/Compilers/VisualBasic/Test/Emit/Emit/CompilationEmitTests.vb b/src/Compilers/VisualBasic/Test/Emit/Emit/CompilationEmitTests.vb index 75c11c5af0765..2278b4112284e 100644 --- a/src/Compilers/VisualBasic/Test/Emit/Emit/CompilationEmitTests.vb +++ b/src/Compilers/VisualBasic/Test/Emit/Emit/CompilationEmitTests.vb @@ -298,7 +298,7 @@ End Class End Sub - Sub RefAssembly_InvariantToSomeChanges() + Public Sub RefAssembly_InvariantToSomeChanges() RefAssembly_InvariantToSomeChanges( "Public Function M() As Integer @@ -375,7 +375,7 @@ End Class" End Sub - Sub RefAssembly_IgnoresSomeDiagnostics() + Public Sub RefAssembly_IgnoresSomeDiagnostics() RefAssembly_IgnoresSomeDiagnostics( "Public Function M() As Integer @@ -411,7 +411,7 @@ End Class" End Sub - Sub VerifyRefAssembly() + Public Sub VerifyRefAssembly() Dim source = " Public MustInherit Class PublicClass Public Sub PublicMethod() @@ -479,7 +479,7 @@ End Class" End Sub - Sub EmitMetadataOnly_NoPdbs() + Public Sub EmitMetadataOnly_NoPdbs() Dim comp = CreateCompilation("", references:={MscorlibRef}, options:=TestOptions.DebugDll.WithDeterministic(True)) @@ -492,7 +492,7 @@ End Class" End Sub - Sub EmitMetadataOnly_NoMetadataPeStream() + Public Sub EmitMetadataOnly_NoMetadataPeStream() Dim comp = CreateCompilation("", references:={MscorlibRef}, options:=TestOptions.DebugDll.WithDeterministic(True)) @@ -505,7 +505,7 @@ End Class" End Sub - Sub EmitMetadata() + Public Sub EmitMetadata() Dim source = "Public MustInherit Class PublicClass Public Sub PublicMethod @@ -807,21 +807,21 @@ End Module Dim compilation = CreateCompilationWithMscorlib(source, options:=Nothing) - Dim peHeaders = New peHeaders(compilation.EmitToStream()) + Dim peHeaders = New PEHeaders(compilation.EmitToStream()) Assert.Equal(CorFlags.ILOnly, peHeaders.CorHeader.Flags) compilation = CreateCompilationWithMscorlib(source, options:=New VisualBasicCompilationOptions(OutputKind.ConsoleApplication).WithPlatform(Platform.X86)) - peHeaders = New peHeaders(compilation.EmitToStream()) + peHeaders = New PEHeaders(compilation.EmitToStream()) Assert.Equal(CorFlags.ILOnly Or CorFlags.Requires32Bit, peHeaders.CorHeader.Flags) compilation = CreateCompilationWithMscorlib(source, options:=New VisualBasicCompilationOptions(OutputKind.ConsoleApplication).WithPlatform(Platform.X64)) - peHeaders = New peHeaders(compilation.EmitToStream()) + peHeaders = New PEHeaders(compilation.EmitToStream()) Assert.Equal(CorFlags.ILOnly, peHeaders.CorHeader.Flags) Assert.True(peHeaders.Requires64Bits) Assert.True(peHeaders.RequiresAmdInstructionSet) compilation = CreateCompilationWithMscorlib(source, options:=New VisualBasicCompilationOptions(OutputKind.ConsoleApplication).WithPlatform(Platform.AnyCpu32BitPreferred)) - peHeaders = New peHeaders(compilation.EmitToStream()) + peHeaders = New PEHeaders(compilation.EmitToStream()) Assert.False(peHeaders.Requires64Bits) Assert.False(peHeaders.RequiresAmdInstructionSet) Assert.Equal(CorFlags.ILOnly Or CorFlags.Requires32Bit Or CorFlags.Prefers32Bit, peHeaders.CorHeader.Flags) @@ -840,7 +840,7 @@ End Module Dim compilation = CreateCompilationWithMscorlib(source, options:=New VisualBasicCompilationOptions(OutputKind.DynamicallyLinkedLibrary).WithPlatform(Platform.AnyCpu)) - Dim peHeaders = New peHeaders(compilation.EmitToStream()) + Dim peHeaders = New PEHeaders(compilation.EmitToStream()) 'interesting COFF bits Assert.False(peHeaders.Requires64Bits) @@ -865,7 +865,7 @@ End Module ' test an exe as well: compilation = CreateCompilationWithMscorlib(source, options:=New VisualBasicCompilationOptions(OutputKind.ConsoleApplication).WithPlatform(Platform.AnyCpu)) - peHeaders = New peHeaders(compilation.EmitToStream()) + peHeaders = New PEHeaders(compilation.EmitToStream()) 'interesting COFF bits Assert.False(peHeaders.Requires64Bits) @@ -901,7 +901,7 @@ End Module Dim compilation = CreateCompilationWithMscorlib(source, options:=New VisualBasicCompilationOptions(OutputKind.DynamicallyLinkedLibrary).WithPlatform(Platform.Arm)) - Dim peHeaders = New peHeaders(compilation.EmitToStream()) + Dim peHeaders = New PEHeaders(compilation.EmitToStream()) 'interesting COFF bits Assert.False(peHeaders.Requires64Bits) @@ -926,7 +926,7 @@ End Module ' test an exe as well: compilation = CreateCompilationWithMscorlib(source, options:=New VisualBasicCompilationOptions(OutputKind.ConsoleApplication).WithPlatform(Platform.AnyCpu)) - peHeaders = New peHeaders(compilation.EmitToStream()) + peHeaders = New PEHeaders(compilation.EmitToStream()) 'interesting COFF bits Assert.False(peHeaders.Requires64Bits) @@ -962,7 +962,7 @@ End Module Dim compilation = CreateCompilationWithMscorlib(source, options:=New VisualBasicCompilationOptions(OutputKind.DynamicallyLinkedLibrary).WithPlatform(Platform.X64)) - Dim peHeaders = New peHeaders(compilation.EmitToStream()) + Dim peHeaders = New PEHeaders(compilation.EmitToStream()) 'interesting COFF bits Assert.True(peHeaders.Requires64Bits) @@ -982,7 +982,7 @@ End Module ' test an exe as well: compilation = CreateCompilationWithMscorlib(source, options:=New VisualBasicCompilationOptions(OutputKind.ConsoleApplication).WithPlatform(Platform.X64)) - peHeaders = New peHeaders(compilation.EmitToStream()) + peHeaders = New PEHeaders(compilation.EmitToStream()) 'interesting COFF bits Assert.True(peHeaders.Requires64Bits) @@ -1038,7 +1038,7 @@ End Module Dim compilation = CreateCompilationWithMscorlib(source, options:=New VisualBasicCompilationOptions(OutputKind.WindowsRuntimeApplication)) - Dim peHeaders = New peHeaders(compilation.EmitToStream()) + Dim peHeaders = New PEHeaders(compilation.EmitToStream()) Assert.Equal(CType(&H9540, UShort), peHeaders.PEHeader.DllCharacteristics) 'DYNAMIC_BASE | NX_COMPAT | NO_SEH | TERMINAL_SERVER_AWARE | HIGH_ENTROPY_VA (0x20) End Sub @@ -1071,15 +1071,15 @@ End Module ' default for 32 bit compilation = CreateCompilationWithMscorlib(source, options:=TestOptions.ReleaseExe.WithPlatform(Platform.X86)) - peHeaders = New peHeaders(compilation.EmitToStream()) + peHeaders = New PEHeaders(compilation.EmitToStream()) Assert.Equal(&H400000UL, peHeaders.PEHeader.ImageBase) compilation = CreateCompilationWithMscorlib(source, options:=TestOptions.ReleaseExe.WithPlatform(Platform.X64)) - peHeaders = New peHeaders(compilation.EmitToStream()) + peHeaders = New PEHeaders(compilation.EmitToStream()) Assert.Equal(&H140000000UL, peHeaders.PEHeader.ImageBase) compilation = CreateCompilationWithMscorlib(source, options:=TestOptions.ReleaseDll.WithPlatform(Platform.X64)) - peHeaders = New peHeaders(compilation.EmitToStream()) + peHeaders = New PEHeaders(compilation.EmitToStream()) Assert.Equal(&H180000000UL, peHeaders.PEHeader.ImageBase) End Sub @@ -1101,7 +1101,7 @@ End Module Assert.Equal(1024, peHeaders.PEHeader.FileAlignment) compilation = CreateCompilationWithMscorlib(source) - peHeaders = New peHeaders(compilation.EmitToStream(options:=New EmitOptions(fileAlignment:=4096))) + peHeaders = New PEHeaders(compilation.EmitToStream(options:=New EmitOptions(fileAlignment:=4096))) Assert.Equal(4096, peHeaders.PEHeader.FileAlignment) End Sub @@ -1977,7 +1977,7 @@ end namespace Dim sourceAssembly = DirectCast(assembly, SourceAssemblySymbol) Dim compilation = sourceAssembly.DeclaringCompilation - Dim emitOptions = New emitOptions(outputNameOverride:=sourceAssembly.Name) + Dim emitOptions = New EmitOptions(outputNameOverride:=sourceAssembly.Name) Dim assemblyBuilder = New PEAssemblyBuilder(sourceAssembly, emitOptions, OutputKind.DynamicallyLinkedLibrary, GetDefaultModulePropertiesForSerialization(), SpecializedCollections.EmptyEnumerable(Of ResourceDescription), Nothing) Dim assemblySecurityAttributes As IEnumerable(Of Cci.SecurityAttribute) = assemblyBuilder.GetSourceAssemblySecurityAttributes() From e062d9692fe5e5836c06448a46eb32b6b1587881 Mon Sep 17 00:00:00 2001 From: Julien Couvreur Date: Thu, 16 Mar 2017 18:48:20 -0700 Subject: [PATCH 10/14] Addressing PR feedback from Chuck --- .../Test/CommandLine/CommandLineTests.cs | 34 +++++------ .../Test/Emit/Emit/CompilationEmitTests.cs | 15 ++--- .../Core/MSBuildTask/ManagedCompiler.cs | 2 +- .../Core/MSBuildTaskTests/CscTests.cs | 2 +- .../Core/MSBuildTaskTests/VbcTests.cs | 2 +- .../Test/CommandLine/CommandLineTests.vb | 59 +++++++++---------- .../Test/Emit/Emit/CompilationEmitTests.vb | 14 ++--- 7 files changed, 55 insertions(+), 73 deletions(-) diff --git a/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs b/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs index 9c14292036b9a..ce5f8310a98ff 100644 --- a/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs +++ b/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs @@ -8894,7 +8894,7 @@ public static void Main() var exe = Path.Combine(dir.Path, "a.exe"); Assert.True(File.Exists(exe)); - VerifyPEMetadata(File.OpenRead(exe), + VerifyPEMetadata(exe, new[] { "TypeDef:", "TypeDef:C" }, new[] { "MethodDef: Void Main()", "MethodDef: Void .ctor()" }, new[] { "CompilationRelaxationsAttribute", "RuntimeCompatibilityAttribute", "DebuggableAttribute" } @@ -8903,10 +8903,8 @@ public static void Main() var doc = Path.Combine(dir.Path, "doc.xml"); Assert.True(File.Exists(doc)); - using (var reader = new StreamReader(doc)) - { - var content = reader.ReadToEnd(); - var expectedDoc = + var content = File.ReadAllText(doc); + var expectedDoc = @" @@ -8918,16 +8916,15 @@ public static void Main() "; - Assert.Equal(expectedDoc, content.Trim()); - } + Assert.Equal(expectedDoc, content.Trim()); var output = ProcessUtilities.RunAndGetOutput(exe, startFolder: dir.ToString()); Assert.Equal("Hello", output.Trim()); - var refDll = Path.Combine(dir.Path, "ref\\a.dll"); + var refDll = Path.Combine(dir.Path, Path.Combine("ref", "a.dll")); Assert.True(File.Exists(refDll)); - VerifyPEMetadata(File.OpenRead(refDll), + VerifyPEMetadata(refDll, new[] { "TypeDef:", "TypeDef:C" }, new[] { "MethodDef: Void Main()", "MethodDef: Void .ctor()" }, new[] { "CompilationRelaxationsAttribute", "RuntimeCompatibilityAttribute", "DebuggableAttribute" } @@ -8939,8 +8936,9 @@ public static void Main() CleanupAllGeneratedFiles(dir.Path); } - private static void VerifyPEMetadata(FileStream peStream, string[] types, string[] methods, string[] attributes) + private static void VerifyPEMetadata(string pePath, string[] types, string[] methods, string[] attributes) { + using (var peStream = File.OpenRead(pePath)) using (var refPeReader = new PEReader(peStream)) { var metadataReader = refPeReader.GetMetadataReader(); @@ -8980,7 +8978,7 @@ public void RefOutWithError() var dll = Path.Combine(dir.Path, "a.dll"); Assert.False(File.Exists(dll)); - var refDll = Path.Combine(dir.Path, "ref\\a.dll"); + var refDll = Path.Combine(dir.Path, Path.Combine("ref", "a.dll")); Assert.False(File.Exists(refDll)); Assert.Equal("a.cs(1,39): error CS0103: The name 'error' does not exist in the current context", outWriter.ToString().Trim()); @@ -9006,14 +9004,15 @@ public static void Main() }"); var outWriter = new StringWriter(CultureInfo.InvariantCulture); - var csc = new MockCSharpCompiler(null, dir.Path, new[] { "/nologo", "/out:a.dll", "/refonly", "/debug", "/deterministic", "/doc:doc.xml", "a.cs" }); + var csc = new MockCSharpCompiler(null, dir.Path, + new[] { "/nologo", "/out:a.dll", "/refonly", "/debug", "/deterministic", "/doc:doc.xml", "a.cs" }); int exitCode = csc.Run(outWriter); Assert.Equal(0, exitCode); var refDll = Path.Combine(dir.Path, "a.dll"); Assert.True(File.Exists(refDll)); - VerifyPEMetadata(File.OpenRead(refDll), + VerifyPEMetadata(refDll, new[] { "TypeDef:", "TypeDef:C" }, new[] { "MethodDef: Void Main()", "MethodDef: Void .ctor()" }, new[] { "CompilationRelaxationsAttribute", "RuntimeCompatibilityAttribute", "DebuggableAttribute" } @@ -9025,10 +9024,8 @@ public static void Main() var doc = Path.Combine(dir.Path, "doc.xml"); Assert.True(File.Exists(doc)); - using (var reader = new StreamReader(doc)) - { - var content = reader.ReadToEnd(); - var expectedDoc = + var content = File.ReadAllText(doc); + var expectedDoc = @" @@ -9040,8 +9037,7 @@ public static void Main() "; - Assert.Equal(expectedDoc, content.Trim()); - } + Assert.Equal(expectedDoc, content.Trim()); // Clean up temp files CleanupAllGeneratedFiles(dir.Path); diff --git a/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs b/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs index bfe5322acbc7b..2a94fbf3fc840 100644 --- a/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs +++ b/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections.Immutable; using System.IO; using System.Linq; using System.Reflection; @@ -255,28 +256,22 @@ public class C CSharpCompilation comp1 = CreateCompilationWithMscorlib(Parse(source1), options: TestOptions.DebugDll.WithDeterministic(true), assemblyName: name); - byte[] image1; + ImmutableArray image1; using (var output = new MemoryStream()) { - var emitResult = comp1.Emit(output, options: EmitOptions.Default.WithEmitMetadataOnly(true)); - Assert.True(emitResult.Success); - emitResult.Diagnostics.Verify(); - image1 = output.ToArray(); + image1 = comp1.EmitToArray(EmitOptions.Default.WithEmitMetadataOnly(true)); } var source2 = sourceTemplate.Replace("CHANGE", change2); Compilation comp2 = CreateCompilationWithMscorlib(Parse(source2), options: TestOptions.DebugDll.WithDeterministic(true), assemblyName: name); - byte[] image2; + ImmutableArray image2; using (var output = new MemoryStream()) { - var emitResult = comp2.Emit(output, options: EmitOptions.Default.WithEmitMetadataOnly(true)); - Assert.True(emitResult.Success); - emitResult.Diagnostics.Verify(); - image2 = output.ToArray(); + image2 = comp2.EmitToArray(EmitOptions.Default.WithEmitMetadataOnly(true)); } if (expectMatch) diff --git a/src/Compilers/Core/MSBuildTask/ManagedCompiler.cs b/src/Compilers/Core/MSBuildTask/ManagedCompiler.cs index 19a35ca4cb08a..a72cdd6b1281c 100644 --- a/src/Compilers/Core/MSBuildTask/ManagedCompiler.cs +++ b/src/Compilers/Core/MSBuildTask/ManagedCompiler.cs @@ -718,7 +718,7 @@ protected internal virtual void AddResponseFileCommands(CommandLineBuilderExtens commandLine.AppendPlusOrMinusSwitch("/optimize", _store, nameof(Optimize)); commandLine.AppendSwitchIfNotNull("/pathmap:", PathMap); commandLine.AppendSwitchIfNotNull("/out:", OutputAssembly); - commandLine.AppendSwitchIfNotNull("/outref:", OutputRefAssembly); + commandLine.AppendSwitchIfNotNull("/refout:", OutputRefAssembly); commandLine.AppendWhenTrue("/refonly", _store, nameof(RefOnly)); commandLine.AppendSwitchIfNotNull("/ruleset:", CodeAnalysisRuleSet); commandLine.AppendSwitchIfNotNull("/errorlog:", ErrorLog); diff --git a/src/Compilers/Core/MSBuildTaskTests/CscTests.cs b/src/Compilers/Core/MSBuildTaskTests/CscTests.cs index d35b02527e48e..bd3e3dd55c145 100644 --- a/src/Compilers/Core/MSBuildTaskTests/CscTests.cs +++ b/src/Compilers/Core/MSBuildTaskTests/CscTests.cs @@ -293,7 +293,7 @@ public void RefOut() var csc = new Csc(); csc.Sources = MSBuildUtil.CreateTaskItems("test.cs"); csc.OutputRefAssembly = MSBuildUtil.CreateTaskItem("ref\\test.dll"); - Assert.Equal("/out:test.exe /outref:ref\\test.dll test.cs", csc.GenerateResponseFileContents()); + Assert.Equal("/out:test.exe /refout:ref\\test.dll test.cs", csc.GenerateResponseFileContents()); } [Fact] diff --git a/src/Compilers/Core/MSBuildTaskTests/VbcTests.cs b/src/Compilers/Core/MSBuildTaskTests/VbcTests.cs index 91c4333271da3..dd0b5ca23fca7 100644 --- a/src/Compilers/Core/MSBuildTaskTests/VbcTests.cs +++ b/src/Compilers/Core/MSBuildTaskTests/VbcTests.cs @@ -290,7 +290,7 @@ public void RefOut() var vbc = new Vbc(); vbc.Sources = MSBuildUtil.CreateTaskItems("test.vb"); vbc.OutputRefAssembly = MSBuildUtil.CreateTaskItem("ref\\test.dll"); - Assert.Equal("/optionstrict:custom /out:test.exe /outref:ref\\test.dll test.vb", vbc.GenerateResponseFileContents()); + Assert.Equal("/optionstrict:custom /out:test.exe /refout:ref\\test.dll test.vb", vbc.GenerateResponseFileContents()); } [Fact] diff --git a/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb b/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb index 026a2784913ba..65f763ca363be 100644 --- a/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb +++ b/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb @@ -8019,7 +8019,7 @@ End Class") Dim exe = Path.Combine(dir.Path, "a.exe") Assert.True(File.Exists(exe)) - VerifyPEMetadata(File.OpenRead(exe), + VerifyPEMetadata(exe, {"TypeDef:", "TypeDef:C"}, {"MethodDef: Void Main()", "MethodDef: Void .ctor()"}, {"CompilationRelaxationsAttribute", "RuntimeCompatibilityAttribute", "DebuggableAttribute", "STAThreadAttribute"} @@ -8029,9 +8029,8 @@ End Class") Dim doc = Path.Combine(dir.Path, "doc.xml") Assert.True(File.Exists(doc)) - Using reader As New StreamReader(doc) - Dim content = reader.ReadToEnd() - Dim expectedDoc = + Dim content = File.ReadAllText(doc) + Dim expectedDoc = " @@ -8045,17 +8044,15 @@ a " - Assert.Equal(expectedDoc, content.Trim()) - - End Using + Assert.Equal(expectedDoc, content.Trim()) Dim output = ProcessUtilities.RunAndGetOutput(exe, startFolder:=dir.ToString()) Assert.Equal("Hello", output.Trim()) - Dim refDll = Path.Combine(dir.Path, "ref\\a.dll") + Dim refDll = Path.Combine(dir.Path, Path.Combine("ref", "a.dll")) Assert.True(File.Exists(refDll)) - VerifyPEMetadata(File.OpenRead(refDll), + VerifyPEMetadata(refDll, {"TypeDef:", "TypeDef:C"}, {"MethodDef: Void Main()", "MethodDef: Void .ctor()"}, {"CompilationRelaxationsAttribute", "RuntimeCompatibilityAttribute", "DebuggableAttribute", "STAThreadAttribute"} @@ -8067,24 +8064,26 @@ a CleanupAllGeneratedFiles(dir.Path) End Sub - Private Shared Sub VerifyPEMetadata(peStream As FileStream, types As String(), methods As String(), attributes As String()) - Using refPeReader As New PEReader(peStream) - Dim metadataReader = refPeReader.GetMetadataReader() + Private Shared Sub VerifyPEMetadata(pePath As String, types As String(), methods As String(), attributes As String()) + Using peStream = File.OpenRead(pePath) + Using refPeReader = New PEReader(peStream) + Dim metadataReader = refPeReader.GetMetadataReader() - ' The types and members that are included needs further refinement. - ' See issue https://github.com/dotnet/roslyn/issues/17612 - AssertEx.SetEqual(metadataReader.TypeDefinitions.Select(Function(t) metadataReader.Dump(t)), types) + ' The types and members that are included needs further refinement. + ' See issue https://github.com/dotnet/roslyn/issues/17612 + AssertEx.SetEqual(metadataReader.TypeDefinitions.Select(Function(t) metadataReader.Dump(t)), types) - AssertEx.SetEqual(metadataReader.MethodDefinitions.Select(Function(t) metadataReader.Dump(t)), methods) + AssertEx.SetEqual(metadataReader.MethodDefinitions.Select(Function(t) metadataReader.Dump(t)), methods) - ' ReferenceAssemblyAttribute is missing. - ' See issue https://github.com/dotnet/roslyn/issues/17612 - AssertEx.SetEqual( - metadataReader.CustomAttributes.Select(Function(a) metadataReader.GetCustomAttribute(a).Constructor). - Select(Function(c) metadataReader.GetMemberReference(CType(c, MemberReferenceHandle)).Parent). - Select(Function(p) metadataReader.GetTypeReference(CType(p, TypeReferenceHandle)).Name). - Select(Function(n) metadataReader.GetString(n)), - attributes) + ' ReferenceAssemblyAttribute is missing. + ' See issue https://github.com/dotnet/roslyn/issues/17612 + AssertEx.SetEqual( + metadataReader.CustomAttributes.Select(Function(a) metadataReader.GetCustomAttribute(a).Constructor). + Select(Function(c) metadataReader.GetMemberReference(CType(c, MemberReferenceHandle)).Parent). + Select(Function(p) metadataReader.GetTypeReference(CType(p, TypeReferenceHandle)).Name). + Select(Function(n) metadataReader.GetString(n)), + attributes) + End Using End Using End Sub @@ -8113,7 +8112,7 @@ End Class") Dim dll = Path.Combine(dir.Path, "a.dll") Assert.False(File.Exists(dll)) - Dim refDll = Path.Combine(dir.Path, "ref\\a.dll") + Dim refDll = Path.Combine(dir.Path, Path.Combine("ref", "a.dll")) Assert.False(File.Exists(refDll)) Assert.Equal( @@ -8150,7 +8149,7 @@ End Class") Dim refDll = Path.Combine(dir.Path, "a.dll") Assert.True(File.Exists(refDll)) - VerifyPEMetadata(File.OpenRead(refDll), + VerifyPEMetadata(refDll, {"TypeDef:", "TypeDef:C"}, {"MethodDef: Void Main()", "MethodDef: Void .ctor()"}, {"CompilationRelaxationsAttribute", "RuntimeCompatibilityAttribute", "DebuggableAttribute", "STAThreadAttribute"} @@ -8162,9 +8161,8 @@ End Class") Dim doc = Path.Combine(dir.Path, "doc.xml") Assert.True(File.Exists(doc)) - Using reader As New StreamReader(doc) - Dim content = reader.ReadToEnd() - Dim expectedDoc = + Dim content = File.ReadAllText(doc) + Dim expectedDoc = " @@ -8178,8 +8176,7 @@ a " - Assert.Equal(expectedDoc, content.Trim()) - End Using + Assert.Equal(expectedDoc, content.Trim()) ' Clean up temp files CleanupAllGeneratedFiles(dir.Path) diff --git a/src/Compilers/VisualBasic/Test/Emit/Emit/CompilationEmitTests.vb b/src/Compilers/VisualBasic/Test/Emit/Emit/CompilationEmitTests.vb index 2278b4112284e..448414878de3b 100644 --- a/src/Compilers/VisualBasic/Test/Emit/Emit/CompilationEmitTests.vb +++ b/src/Compilers/VisualBasic/Test/Emit/Emit/CompilationEmitTests.vb @@ -345,26 +345,20 @@ End Class" Dim comp1 = CreateCompilationWithMscorlib(source1, options:=TestOptions.DebugDll.WithDeterministic(True), assemblyName:=name) - Dim image1 As Byte() + Dim image1 As ImmutableArray(Of Byte) Using output As New MemoryStream() - Dim EmitResult = comp1.Emit(output, options:=EmitOptions.Default.WithEmitMetadataOnly(True)) - Assert.True(EmitResult.Success) - EmitResult.Diagnostics.Verify() - image1 = output.ToArray() + image1 = comp1.EmitToArray(EmitOptions.Default.WithEmitMetadataOnly(True)) End Using Dim source2 = sourceTemplate.Replace("CHANGE", change2) Dim comp2 = CreateCompilationWithMscorlib(source2, options:=TestOptions.DebugDll.WithDeterministic(True), assemblyName:=name) - Dim image2 As Byte() + Dim image2 As ImmutableArray(Of Byte) Using output As New MemoryStream() - Dim EmitResult = comp2.Emit(output, options:=EmitOptions.Default.WithEmitMetadataOnly(True)) - Assert.True(EmitResult.Success) - EmitResult.Diagnostics.Verify() - image2 = output.ToArray() + image2 = comp2.EmitToArray(EmitOptions.Default.WithEmitMetadataOnly(True)) End Using If expectMatch Then From f8139ccedf5bde81ece3861c77bca252925851a1 Mon Sep 17 00:00:00 2001 From: Julien Couvreur Date: Fri, 17 Mar 2017 12:00:48 -0700 Subject: [PATCH 11/14] Additional test improvements from Chuck's feedback --- .../Test/CommandLine/CommandLineTests.cs | 8 ++++++- .../Test/Emit/Emit/CompilationEmitTests.cs | 24 ++++++------------- .../Test/CommandLine/CommandLineTests.vb | 6 ++++- .../Test/Emit/Emit/CompilationEmitTests.vb | 22 ++++++----------- 4 files changed, 26 insertions(+), 34 deletions(-) diff --git a/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs b/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs index ce5f8310a98ff..18554c0740831 100644 --- a/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs +++ b/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs @@ -2794,6 +2794,12 @@ public void ParseOut() // error CS8301: Do not use refout when using refonly. Diagnostic(ErrorCode.ERR_NoRefOutWhenRefOnly).WithLocation(1, 1)); + parsedArgs = DefaultParse(new[] { "/refonly:incorrect", "a.cs" }, baseDirectory); + parsedArgs.Errors.Verify( + // error CS2007: Unrecognized option: '/refonly:incorrect' + Diagnostic(ErrorCode.ERR_BadSwitch).WithArguments("/refonly:incorrect").WithLocation(1, 1) + ); + parsedArgs = DefaultParse(new[] { @"/refout:ref.dll", "/target:module", "a.cs" }, baseDirectory); parsedArgs.Errors.Verify( // error CS8302: Cannot compile net modules when using /refout or /refonly. @@ -8918,7 +8924,7 @@ public static void Main() "; Assert.Equal(expectedDoc, content.Trim()); - var output = ProcessUtilities.RunAndGetOutput(exe, startFolder: dir.ToString()); + var output = ProcessUtilities.RunAndGetOutput(exe, startFolder: dir.Path); Assert.Equal("Hello", output.Trim()); var refDll = Path.Combine(dir.Path, Path.Combine("ref", "a.dll")); diff --git a/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs b/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs index 2a94fbf3fc840..330f2f1ad1856 100644 --- a/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs +++ b/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs @@ -255,24 +255,12 @@ public class C string source1 = sourceTemplate.Replace("CHANGE", change1); CSharpCompilation comp1 = CreateCompilationWithMscorlib(Parse(source1), options: TestOptions.DebugDll.WithDeterministic(true), assemblyName: name); - - ImmutableArray image1; - - using (var output = new MemoryStream()) - { - image1 = comp1.EmitToArray(EmitOptions.Default.WithEmitMetadataOnly(true)); - } + ImmutableArray image1 = comp1.EmitToArray(EmitOptions.Default.WithEmitMetadataOnly(true)); var source2 = sourceTemplate.Replace("CHANGE", change2); Compilation comp2 = CreateCompilationWithMscorlib(Parse(source2), options: TestOptions.DebugDll.WithDeterministic(true), assemblyName: name); - - ImmutableArray image2; - - using (var output = new MemoryStream()) - { - image2 = comp2.EmitToArray(EmitOptions.Default.WithEmitMetadataOnly(true)); - } + ImmutableArray image2 = comp2.EmitToArray(EmitOptions.Default.WithEmitMetadataOnly(true)); if (expectMatch) { @@ -287,7 +275,7 @@ public class C [Theory] [InlineData("public int M() { error(); }", true)] [InlineData("public int M() { error() }", false)] // Should be true. See follow-up issue https://github.com/dotnet/roslyn/issues/17612 - [InlineData("public Error M() { return null; }", false)] // Should be true. See follow-up issue https://github.com/dotnet/roslyn/issues/17612 + [InlineData("public Error M() { return null; }", false)] // This may get relaxed. See follow-up issue https://github.com/dotnet/roslyn/issues/17612 public void RefAssembly_IgnoresSomeDiagnostics(string change, bool expectSuccess) { string sourceTemplate = @" @@ -381,7 +369,7 @@ private static void VerifyMethodBodies(System.Collections.Immutable.ImmutableArr } [Fact] - public void EmitMetadataOnly_NoPdbs() + public void EmitMetadataOnly_DisallowPdbs() { CSharpCompilation comp = CreateCompilation("", references: new[] { MscorlibRef }, options: TestOptions.DebugDll.WithDeterministic(true)); @@ -395,7 +383,7 @@ public void EmitMetadataOnly_NoPdbs() } [Fact] - public void EmitMetadataOnly_NoMetadataPeStream() + public void EmitMetadataOnly_DisallowMetadataPeStream() { CSharpCompilation comp = CreateCompilation("", references: new[] { MscorlibRef }, options: TestOptions.DebugDll.WithDeterministic(true)); @@ -429,6 +417,8 @@ public abstract class PublicClass Assert.NotEqual(0, output.Position); Assert.NotEqual(0, pdbOutput.Position); Assert.NotEqual(0, metadataOutput.Position); + VerifyMethodBodies(ImmutableArray.CreateRange(output.GetBuffer()), expectEmptyOrThrowNull: false); + VerifyMethodBodies(ImmutableArray.CreateRange(metadataOutput.GetBuffer()), expectEmptyOrThrowNull: true); } var peImage = comp.EmitToArray(); diff --git a/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb b/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb index 65f763ca363be..186c1ae4855b6 100644 --- a/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb +++ b/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb @@ -2773,6 +2773,10 @@ print Goodbye, World" parsedArgs.Errors.Verify( Diagnostic(ERRID.ERR_NoRefOutWhenRefOnly).WithLocation(1, 1)) + parsedArgs = DefaultParse({"/refonly:incorrect", "a.vb"}, baseDirectory) + parsedArgs.Errors.Verify( + Diagnostic(ERRID.ERR_SwitchNeedsBool).WithArguments("refonly").WithLocation(1, 1)) + parsedArgs = DefaultParse({"/refout:ref.dll", "/target:module", "a.vb"}, baseDirectory) parsedArgs.Errors.Verify( Diagnostic(ERRID.ERR_NoNetModuleOutputWhenRefOutOrRefOnly).WithLocation(1, 1)) @@ -8046,7 +8050,7 @@ a " Assert.Equal(expectedDoc, content.Trim()) - Dim output = ProcessUtilities.RunAndGetOutput(exe, startFolder:=dir.ToString()) + Dim output = ProcessUtilities.RunAndGetOutput(exe, startFolder:=dir.Path) Assert.Equal("Hello", output.Trim()) Dim refDll = Path.Combine(dir.Path, Path.Combine("ref", "a.dll")) diff --git a/src/Compilers/VisualBasic/Test/Emit/Emit/CompilationEmitTests.vb b/src/Compilers/VisualBasic/Test/Emit/Emit/CompilationEmitTests.vb index 448414878de3b..08933725997e5 100644 --- a/src/Compilers/VisualBasic/Test/Emit/Emit/CompilationEmitTests.vb +++ b/src/Compilers/VisualBasic/Test/Emit/Emit/CompilationEmitTests.vb @@ -344,22 +344,12 @@ End Class" Dim source1 As String = sourceTemplate.Replace("CHANGE", change1) Dim comp1 = CreateCompilationWithMscorlib(source1, options:=TestOptions.DebugDll.WithDeterministic(True), assemblyName:=name) - - Dim image1 As ImmutableArray(Of Byte) - - Using output As New MemoryStream() - image1 = comp1.EmitToArray(EmitOptions.Default.WithEmitMetadataOnly(True)) - End Using + Dim image1 As ImmutableArray(Of Byte) = comp1.EmitToArray(EmitOptions.Default.WithEmitMetadataOnly(True)) Dim source2 = sourceTemplate.Replace("CHANGE", change2) Dim comp2 = CreateCompilationWithMscorlib(source2, options:=TestOptions.DebugDll.WithDeterministic(True), assemblyName:=name) - - Dim image2 As ImmutableArray(Of Byte) - - Using output As New MemoryStream() - image2 = comp2.EmitToArray(EmitOptions.Default.WithEmitMetadataOnly(True)) - End Using + Dim image2 As ImmutableArray(Of Byte) = comp2.EmitToArray(EmitOptions.Default.WithEmitMetadataOnly(True)) If expectMatch Then AssertEx.Equal(image1, image2) @@ -382,7 +372,7 @@ End Function", False) ' Should be true. See follow-up issue https://github.com/d RefAssembly_IgnoresSomeDiagnostics( "Public Function M() As Error -End Function", False) ' Should be True. See follow-up issue https://github.com/dotnet/roslyn/issues/17612 +End Function", False) ' This may get relaxed. See follow-up issue https://github.com/dotnet/roslyn/issues/17612 End Sub Private Sub RefAssembly_IgnoresSomeDiagnostics(change As String, expectSuccess As Boolean) @@ -473,7 +463,7 @@ End Class" End Sub - Public Sub EmitMetadataOnly_NoPdbs() + Public Sub EmitMetadataOnly_DisallowPdbs() Dim comp = CreateCompilation("", references:={MscorlibRef}, options:=TestOptions.DebugDll.WithDeterministic(True)) @@ -486,7 +476,7 @@ End Class" End Sub - Public Sub EmitMetadataOnly_NoMetadataPeStream() + Public Sub EmitMetadataOnly_DisallowMetadataPeStream() Dim comp = CreateCompilation("", references:={MscorlibRef}, options:=TestOptions.DebugDll.WithDeterministic(True)) @@ -517,6 +507,8 @@ End Class " Assert.NotEqual(0, output.Position) Assert.NotEqual(0, pdbOutput.Position) Assert.NotEqual(0, metadataOutput.Position) + VerifyMethodBodies(ImmutableArray.CreateRange(output.GetBuffer()), expectEmptyOrThrowNull:=False) + VerifyMethodBodies(ImmutableArray.CreateRange(metadataOutput.GetBuffer()), expectEmptyOrThrowNull:=True) End Using End Using End Using From 56ba8c94097dc6348bb7d8bf0267b832e325eb7a Mon Sep 17 00:00:00 2001 From: Julien Couvreur Date: Fri, 17 Mar 2017 12:57:03 -0700 Subject: [PATCH 12/14] More PR feedback --- .../Test/CommandLine/CommandLineTests.cs | 36 ++---- .../Test/Emit/Emit/CompilationEmitTests.cs | 35 +----- .../Core/Portable/PEWriter/MetadataWriter.cs | 105 ++++++++++-------- .../Portable/PEWriter/ReferenceIndexer.cs | 2 +- .../Test/CommandLine/CommandLineTests.vb | 36 ++---- .../Test/Emit/Emit/CompilationEmitTests.vb | 30 +---- .../Portable/Metadata/MetadataReaderUtils.cs | 49 ++++++++ 7 files changed, 134 insertions(+), 159 deletions(-) diff --git a/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs b/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs index 18554c0740831..6f90b59286f47 100644 --- a/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs +++ b/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs @@ -8900,7 +8900,7 @@ public static void Main() var exe = Path.Combine(dir.Path, "a.exe"); Assert.True(File.Exists(exe)); - VerifyPEMetadata(exe, + MetadataReaderUtils.VerifyPEMetadata(exe, new[] { "TypeDef:", "TypeDef:C" }, new[] { "MethodDef: Void Main()", "MethodDef: Void .ctor()" }, new[] { "CompilationRelaxationsAttribute", "RuntimeCompatibilityAttribute", "DebuggableAttribute" } @@ -8930,7 +8930,10 @@ public static void Main() var refDll = Path.Combine(dir.Path, Path.Combine("ref", "a.dll")); Assert.True(File.Exists(refDll)); - VerifyPEMetadata(refDll, + // The types and members that are included needs further refinement. + // ReferenceAssemblyAttribute is missing. + // See issue https://github.com/dotnet/roslyn/issues/17612 + MetadataReaderUtils.VerifyPEMetadata(refDll, new[] { "TypeDef:", "TypeDef:C" }, new[] { "MethodDef: Void Main()", "MethodDef: Void .ctor()" }, new[] { "CompilationRelaxationsAttribute", "RuntimeCompatibilityAttribute", "DebuggableAttribute" } @@ -8942,30 +8945,6 @@ public static void Main() CleanupAllGeneratedFiles(dir.Path); } - private static void VerifyPEMetadata(string pePath, string[] types, string[] methods, string[] attributes) - { - using (var peStream = File.OpenRead(pePath)) - using (var refPeReader = new PEReader(peStream)) - { - var metadataReader = refPeReader.GetMetadataReader(); - - // The types and members that are included needs further refinement. - // See issue https://github.com/dotnet/roslyn/issues/17612 - AssertEx.SetEqual(metadataReader.TypeDefinitions.Select(t => metadataReader.Dump(t)), types); - - AssertEx.SetEqual(metadataReader.MethodDefinitions.Select(t => metadataReader.Dump(t)), methods); - - // ReferenceAssemblyAttribute is missing. - // See issue https://github.com/dotnet/roslyn/issues/17612 - AssertEx.SetEqual( - metadataReader.CustomAttributes.Select(a => metadataReader.GetCustomAttribute(a).Constructor) - .Select(c => metadataReader.GetMemberReference((MemberReferenceHandle)c).Parent) - .Select(p => metadataReader.GetTypeReference((TypeReferenceHandle)p).Name) - .Select(n => metadataReader.GetString(n)), - attributes); - } - } - [Fact] public void RefOutWithError() { @@ -9018,7 +8997,10 @@ public static void Main() var refDll = Path.Combine(dir.Path, "a.dll"); Assert.True(File.Exists(refDll)); - VerifyPEMetadata(refDll, + // The types and members that are included needs further refinement. + // ReferenceAssemblyAttribute is missing. + // See issue https://github.com/dotnet/roslyn/issues/17612 + MetadataReaderUtils.VerifyPEMetadata(refDll, new[] { "TypeDef:", "TypeDef:C" }, new[] { "MethodDef: Void Main()", "MethodDef: Void .ctor()" }, new[] { "CompilationRelaxationsAttribute", "RuntimeCompatibilityAttribute", "DebuggableAttribute" } diff --git a/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs b/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs index 330f2f1ad1856..e7bc7536227af 100644 --- a/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs +++ b/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs @@ -339,35 +339,8 @@ public abstract class PublicClass "System.Diagnostics.DebuggableAttribute" }); var peImage = comp.EmitToArray(emitRefOnly); - VerifyMethodBodies(peImage, expectEmptyOrThrowNull: true); + MetadataReaderUtils.VerifyMethodBodies(peImage, expectEmptyOrThrowNull: true); } - - private static void VerifyMethodBodies(System.Collections.Immutable.ImmutableArray peImage, bool expectEmptyOrThrowNull) - { - using (var peReader = new PEReader(peImage)) - { - var metadataReader = peReader.GetMetadataReader(); - foreach (var method in metadataReader.MethodDefinitions) - { - var rva = metadataReader.GetMethodDefinition(method).RelativeVirtualAddress; - if (rva != 0) - { - var il = peReader.GetMethodBody(rva).GetILBytes(); - var throwNull = new[] { (byte)ILOpCode.Ldnull, (byte)ILOpCode.Throw }; - - if (expectEmptyOrThrowNull) - { - AssertEx.Equal(throwNull, il); - } - else - { - AssertEx.NotEqual(throwNull, il); - } - } - } - } - } - [Fact] public void EmitMetadataOnly_DisallowPdbs() { @@ -417,12 +390,12 @@ public abstract class PublicClass Assert.NotEqual(0, output.Position); Assert.NotEqual(0, pdbOutput.Position); Assert.NotEqual(0, metadataOutput.Position); - VerifyMethodBodies(ImmutableArray.CreateRange(output.GetBuffer()), expectEmptyOrThrowNull: false); - VerifyMethodBodies(ImmutableArray.CreateRange(metadataOutput.GetBuffer()), expectEmptyOrThrowNull: true); + MetadataReaderUtils.VerifyMethodBodies(ImmutableArray.CreateRange(output.GetBuffer()), expectEmptyOrThrowNull: false); + MetadataReaderUtils.VerifyMethodBodies(ImmutableArray.CreateRange(metadataOutput.GetBuffer()), expectEmptyOrThrowNull: true); } var peImage = comp.EmitToArray(); - VerifyMethodBodies(peImage, expectEmptyOrThrowNull: false); + MetadataReaderUtils.VerifyMethodBodies(peImage, expectEmptyOrThrowNull: false); } /// diff --git a/src/Compilers/Core/Portable/PEWriter/MetadataWriter.cs b/src/Compilers/Core/Portable/PEWriter/MetadataWriter.cs index a8f27302e642c..614a16c7decc9 100644 --- a/src/Compilers/Core/Portable/PEWriter/MetadataWriter.cs +++ b/src/Compilers/Core/Portable/PEWriter/MetadataWriter.cs @@ -65,12 +65,12 @@ internal abstract partial class MetadataWriter private readonly int _numTypeDefsEstimate; private readonly bool _deterministic; - internal readonly bool metadataOnly; + internal readonly bool MetadataOnly; // A map of method body before token translation to RVA. Used for deduplication of small bodies. private readonly Dictionary, int> _smallMethodBodies; - private static ImmutableArray ThrowNullIL { get; } = ImmutableArray.Create((byte)ILOpCode.Ldnull, (byte)ILOpCode.Throw); + private static readonly ImmutableArray ThrowNullIL = ImmutableArray.Create((byte)ILOpCode.Ldnull, (byte)ILOpCode.Throw); private const int ThrowNullMaxStack = 1; protected MetadataWriter( @@ -85,7 +85,7 @@ protected MetadataWriter( { this.module = context.Module; _deterministic = deterministic; - this.metadataOnly = metadataOnly; + this.MetadataOnly = metadataOnly; // EDMAURER provide some reasonable size estimates for these that will avoid // much of the reallocation that would occur when growing these from empty. @@ -2833,7 +2833,7 @@ private int[] SerializeMethodBodies(BlobBuilder ilBuilder, PdbWriter nativePdbWr if (method.HasBody()) { - if (metadataOnly) + if (MetadataOnly) { bodyOffset = SerializeThrowNullMethodBody(encoder); localSignatureHandleOpt = default(StandaloneSignatureHandle); @@ -2873,7 +2873,7 @@ private int[] SerializeMethodBodies(BlobBuilder ilBuilder, PdbWriter nativePdbWr } _dynamicAnalysisDataWriterOpt?.SerializeMethodDynamicAnalysisData(body); - + bodyOffsets[methodRid - 1] = bodyOffset; methodRid++; @@ -2884,72 +2884,79 @@ private int[] SerializeMethodBodies(BlobBuilder ilBuilder, PdbWriter nativePdbWr private int SerializeThrowNullMethodBody(MethodBodyStreamEncoder encoder) { - var il = ThrowNullIL; - - // Don't do small body method caching during deterministic builds until this issue is fixed - // https://github.com/dotnet/roslyn/issues/7595 - int bodyOffset; - if (!_deterministic && _smallMethodBodies.TryGetValue(il, out bodyOffset)) - { - return bodyOffset; - } - - var encodedBody = encoder.AddMethodBody( - codeSize: il.Length, - maxStack: ThrowNullMaxStack, - exceptionRegionCount: 0, - hasSmallExceptionRegions: false); - - // Don't do small body method caching during deterministic builds until this issue is fixed - // https://github.com/dotnet/roslyn/issues/7595 - if (!_deterministic) - { - _smallMethodBodies.Add(il, encodedBody.Offset); - } - UserStringHandle mvidStringHandle = default(UserStringHandle); Blob mvidStringFixup = default(Blob); - WriteInstructions(encodedBody.Instructions, il, ref mvidStringHandle, ref mvidStringFixup); - - Debug.Assert(mvidStringHandle.Equals(default(UserStringHandle)) && mvidStringFixup.Equals(default(Blob))); - return encodedBody.Offset; - } - - private int SerializeMethodBody(MethodBodyStreamEncoder encoder, IMethodBody methodBody, StandaloneSignatureHandle localSignatureHandleOpt, ref UserStringHandle mvidStringHandle, ref Blob mvidStringFixup) - { - int ilLength = methodBody.IL.Length; - var exceptionRegions = methodBody.ExceptionRegions; - bool isSmallBody = ilLength < 64 && methodBody.MaxStack <= 8 && localSignatureHandleOpt.IsNil && exceptionRegions.Length == 0; - - // Check if an identical method body has already been serialized. + return SerializeMethodBody( + encoder, + ThrowNullIL, + ThrowNullMaxStack, + ImmutableArray.Empty, + default(StandaloneSignatureHandle), + MethodBodyAttributes.None, + ref mvidStringHandle, + ref mvidStringFixup); + } + + private int SerializeMethodBody( + MethodBodyStreamEncoder encoder, + IMethodBody methodBody, + StandaloneSignatureHandle localSignatureHandleOpt, + ref UserStringHandle mvidStringHandle, + ref Blob mvidStringFixup) + { + return SerializeMethodBody( + encoder, + methodBody.IL, + methodBody.MaxStack, + methodBody.ExceptionRegions, + localSignatureHandleOpt, + (methodBody.LocalsAreZeroed ? MethodBodyAttributes.InitLocals : MethodBodyAttributes.None), + ref mvidStringHandle, + ref mvidStringFixup); + } + + private int SerializeMethodBody( + MethodBodyStreamEncoder encoder, + ImmutableArray il, + ushort maxStack, + ImmutableArray exceptionRegions, + StandaloneSignatureHandle localSignatureHandleOpt, + MethodBodyAttributes methodBodyAttributes, + ref UserStringHandle mvidStringHandle, + ref Blob mvidStringFixup) + { + int ilLength = il.Length; + bool isSmallBody = ilLength < 64 && maxStack <= 8 && localSignatureHandleOpt.IsNil && exceptionRegions.Length == 0; + + // Check if an identical method body has already been serialized. // If so, use the RVA of the already serialized one. // Note that we don't need to rewrite the fake tokens in the body before looking it up. // Don't do small body method caching during deterministic builds until this issue is fixed // https://github.com/dotnet/roslyn/issues/7595 int bodyOffset; - if (!_deterministic && isSmallBody && _smallMethodBodies.TryGetValue(methodBody.IL, out bodyOffset)) + if (!_deterministic && isSmallBody && _smallMethodBodies.TryGetValue(il, out bodyOffset)) { return bodyOffset; } var encodedBody = encoder.AddMethodBody( - codeSize: methodBody.IL.Length, - maxStack: methodBody.MaxStack, - exceptionRegionCount: exceptionRegions.Length, + codeSize: ilLength, + maxStack: maxStack, + exceptionRegionCount: exceptionRegions.Length, hasSmallExceptionRegions: MayUseSmallExceptionHeaders(exceptionRegions), - localVariablesSignature: localSignatureHandleOpt, - attributes: (methodBody.LocalsAreZeroed ? MethodBodyAttributes.InitLocals : 0)); + localVariablesSignature: localSignatureHandleOpt, + attributes: methodBodyAttributes); // Don't do small body method caching during deterministic builds until this issue is fixed // https://github.com/dotnet/roslyn/issues/7595 if (isSmallBody && !_deterministic) { - _smallMethodBodies.Add(methodBody.IL, encodedBody.Offset); + _smallMethodBodies.Add(il, encodedBody.Offset); } - WriteInstructions(encodedBody.Instructions, methodBody.IL, ref mvidStringHandle, ref mvidStringFixup); + WriteInstructions(encodedBody.Instructions, il, ref mvidStringHandle, ref mvidStringFixup); SerializeMethodBodyExceptionHandlerTable(encodedBody.ExceptionRegions, exceptionRegions); return encodedBody.Offset; diff --git a/src/Compilers/Core/Portable/PEWriter/ReferenceIndexer.cs b/src/Compilers/Core/Portable/PEWriter/ReferenceIndexer.cs index 0b545af969782..b871a1565f161 100644 --- a/src/Compilers/Core/Portable/PEWriter/ReferenceIndexer.cs +++ b/src/Compilers/Core/Portable/PEWriter/ReferenceIndexer.cs @@ -99,7 +99,7 @@ protected override void RecordAssemblyReference(IAssemblyReference assemblyRefer protected override void ProcessMethodBody(IMethodDefinition method) { - if (method.HasBody() && !metadataWriter.metadataOnly) + if (method.HasBody() && !metadataWriter.MetadataOnly) { var body = method.GetBody(Context); diff --git a/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb b/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb index 186c1ae4855b6..f53308ffe3109 100644 --- a/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb +++ b/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb @@ -8023,13 +8023,12 @@ End Class") Dim exe = Path.Combine(dir.Path, "a.exe") Assert.True(File.Exists(exe)) - VerifyPEMetadata(exe, + MetadataReaderUtils.VerifyPEMetadata(exe, {"TypeDef:", "TypeDef:C"}, {"MethodDef: Void Main()", "MethodDef: Void .ctor()"}, {"CompilationRelaxationsAttribute", "RuntimeCompatibilityAttribute", "DebuggableAttribute", "STAThreadAttribute"} ) - Dim doc = Path.Combine(dir.Path, "doc.xml") Assert.True(File.Exists(doc)) @@ -8056,7 +8055,10 @@ a Dim refDll = Path.Combine(dir.Path, Path.Combine("ref", "a.dll")) Assert.True(File.Exists(refDll)) - VerifyPEMetadata(refDll, + ' The types and members that are included needs further refinement. + ' ReferenceAssemblyAttribute is missing. + ' See issue https://github.com/dotnet/roslyn/issues/17612 + MetadataReaderUtils.VerifyPEMetadata(refDll, {"TypeDef:", "TypeDef:C"}, {"MethodDef: Void Main()", "MethodDef: Void .ctor()"}, {"CompilationRelaxationsAttribute", "RuntimeCompatibilityAttribute", "DebuggableAttribute", "STAThreadAttribute"} @@ -8068,29 +8070,6 @@ a CleanupAllGeneratedFiles(dir.Path) End Sub - Private Shared Sub VerifyPEMetadata(pePath As String, types As String(), methods As String(), attributes As String()) - Using peStream = File.OpenRead(pePath) - Using refPeReader = New PEReader(peStream) - Dim metadataReader = refPeReader.GetMetadataReader() - - ' The types and members that are included needs further refinement. - ' See issue https://github.com/dotnet/roslyn/issues/17612 - AssertEx.SetEqual(metadataReader.TypeDefinitions.Select(Function(t) metadataReader.Dump(t)), types) - - AssertEx.SetEqual(metadataReader.MethodDefinitions.Select(Function(t) metadataReader.Dump(t)), methods) - - ' ReferenceAssemblyAttribute is missing. - ' See issue https://github.com/dotnet/roslyn/issues/17612 - AssertEx.SetEqual( - metadataReader.CustomAttributes.Select(Function(a) metadataReader.GetCustomAttribute(a).Constructor). - Select(Function(c) metadataReader.GetMemberReference(CType(c, MemberReferenceHandle)).Parent). - Select(Function(p) metadataReader.GetTypeReference(CType(p, TypeReferenceHandle)).Name). - Select(Function(n) metadataReader.GetString(n)), - attributes) - End Using - End Using - End Sub - Public Sub RefOutWithError() Dim dir = Temp.CreateDirectory() @@ -8153,7 +8132,10 @@ End Class") Dim refDll = Path.Combine(dir.Path, "a.dll") Assert.True(File.Exists(refDll)) - VerifyPEMetadata(refDll, + ' The types and members that are included needs further refinement. + ' ReferenceAssemblyAttribute is missing. + ' See issue https://github.com/dotnet/roslyn/issues/17612 + MetadataReaderUtils.VerifyPEMetadata(refDll, {"TypeDef:", "TypeDef:C"}, {"MethodDef: Void Main()", "MethodDef: Void .ctor()"}, {"CompilationRelaxationsAttribute", "RuntimeCompatibilityAttribute", "DebuggableAttribute", "STAThreadAttribute"} diff --git a/src/Compilers/VisualBasic/Test/Emit/Emit/CompilationEmitTests.vb b/src/Compilers/VisualBasic/Test/Emit/Emit/CompilationEmitTests.vb index 08933725997e5..775744fdbbce5 100644 --- a/src/Compilers/VisualBasic/Test/Emit/Emit/CompilationEmitTests.vb +++ b/src/Compilers/VisualBasic/Test/Emit/Emit/CompilationEmitTests.vb @@ -437,29 +437,11 @@ End Class" AssertEx.SetEqual(assembly.GetAttributes().Select(Function(a) a.AttributeClass.ToTestDisplayString()), {"System.Runtime.CompilerServices.CompilationRelaxationsAttribute", - "System.Runtime.CompilerServices.RuntimeCompatibilityAttribute", - "System.Diagnostics.DebuggableAttribute"}) + "System.Runtime.CompilerServices.RuntimeCompatibilityAttribute", + "System.Diagnostics.DebuggableAttribute"}) Dim peImage = comp.EmitToArray(emitRefOnly) - VerifyMethodBodies(peImage, expectEmptyOrThrowNull:=True) - End Sub - - Private Shared Sub VerifyMethodBodies(peImage As ImmutableArray(Of Byte), expectEmptyOrThrowNull As Boolean) - Using peReader As New PEReader(peImage) - Dim metadataReader = peReader.GetMetadataReader() - For Each method In metadataReader.MethodDefinitions - Dim rva = metadataReader.GetMethodDefinition(method).RelativeVirtualAddress - If rva <> 0 Then - Dim il = peReader.GetMethodBody(rva).GetILBytes() - Dim throwNull = {CType(ILOpCode.Ldnull, Byte), CType(ILOpCode.Throw, Byte)} - If expectEmptyOrThrowNull Then - AssertEx.Equal(throwNull, il) - Else - AssertEx.NotEqual(throwNull, il) - End If - End If - Next - End Using + MetadataReaderUtils.VerifyMethodBodies(peImage, expectEmptyOrThrowNull:=True) End Sub @@ -507,14 +489,14 @@ End Class " Assert.NotEqual(0, output.Position) Assert.NotEqual(0, pdbOutput.Position) Assert.NotEqual(0, metadataOutput.Position) - VerifyMethodBodies(ImmutableArray.CreateRange(output.GetBuffer()), expectEmptyOrThrowNull:=False) - VerifyMethodBodies(ImmutableArray.CreateRange(metadataOutput.GetBuffer()), expectEmptyOrThrowNull:=True) + MetadataReaderUtils.VerifyMethodBodies(ImmutableArray.CreateRange(output.GetBuffer()), expectEmptyOrThrowNull:=False) + MetadataReaderUtils.VerifyMethodBodies(ImmutableArray.CreateRange(metadataOutput.GetBuffer()), expectEmptyOrThrowNull:=True) End Using End Using End Using Dim peImage = comp.EmitToArray() - VerifyMethodBodies(peImage, expectEmptyOrThrowNull:=False) + MetadataReaderUtils.VerifyMethodBodies(peImage, expectEmptyOrThrowNull:=False) End Sub diff --git a/src/Test/Utilities/Portable/Metadata/MetadataReaderUtils.cs b/src/Test/Utilities/Portable/Metadata/MetadataReaderUtils.cs index e12525d9face3..5e1f8db49ddf5 100644 --- a/src/Test/Utilities/Portable/Metadata/MetadataReaderUtils.cs +++ b/src/Test/Utilities/Portable/Metadata/MetadataReaderUtils.cs @@ -358,5 +358,54 @@ public string GetTypeFromSpecification(MetadataReader reader, object genericCont return new SignatureDecoder(Instance, reader, genericContext).DecodeType(ref sigReader); } } + + internal static void VerifyPEMetadata(string pePath, string[] types, string[] methods, string[] attributes) + { + using (var peStream = File.OpenRead(pePath)) + using (var refPeReader = new PEReader(peStream)) + { + var metadataReader = refPeReader.GetMetadataReader(); + + AssertEx.SetEqual(metadataReader.TypeDefinitions.Select(t => metadataReader.Dump(t)), types); + AssertEx.SetEqual(metadataReader.MethodDefinitions.Select(t => metadataReader.Dump(t)), methods); + + AssertEx.SetEqual( + metadataReader.CustomAttributes.Select(a => metadataReader.GetCustomAttribute(a).Constructor) + .Select(c => metadataReader.GetMemberReference((MemberReferenceHandle)c).Parent) + .Select(p => metadataReader.GetTypeReference((TypeReferenceHandle)p).Name) + .Select(n => metadataReader.GetString(n)), + attributes); + } + } + + /// + /// Asserts that all the method bodies in the PE are empty or `throw null`, if expectEmptyOrThrowNull is true. + /// Asserts that none of the methods bodies are empty or `throw null`, if expectEmptyOrThrowNull is false. + /// + internal static void VerifyMethodBodies(ImmutableArray peImage, bool expectEmptyOrThrowNull) + { + using (var peReader = new PEReader(peImage)) + { + var metadataReader = peReader.GetMetadataReader(); + foreach (var method in metadataReader.MethodDefinitions) + { + var rva = metadataReader.GetMethodDefinition(method).RelativeVirtualAddress; + if (rva != 0) + { + var il = peReader.GetMethodBody(rva).GetILBytes(); + var throwNull = new[] { (byte)ILOpCode.Ldnull, (byte)ILOpCode.Throw }; + + if (expectEmptyOrThrowNull) + { + AssertEx.Equal(throwNull, il); + } + else + { + AssertEx.NotEqual(throwNull, il); + } + } + } + } + } } } From 7258b4bbbe75778253265387a700a340fdefd2f5 Mon Sep 17 00:00:00 2001 From: Julien Couvreur Date: Mon, 20 Mar 2017 12:24:50 -0700 Subject: [PATCH 13/14] Address Aleksey's PR feedback --- .../Test/Emit/Emit/CompilationEmitTests.cs | 27 +++++++++++++++++++ .../CodeAnalysisResources.Designer.cs | 9 +++++++ .../Core/Portable/CodeAnalysisResources.resx | 3 +++ .../Core/Portable/Compilation/Compilation.cs | 12 +++++++++ .../Core/Portable/PEWriter/MetadataWriter.cs | 5 +++- 5 files changed, 55 insertions(+), 1 deletion(-) diff --git a/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs b/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs index e7bc7536227af..bd115c7776b04 100644 --- a/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs +++ b/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs @@ -369,6 +369,33 @@ public void EmitMetadataOnly_DisallowMetadataPeStream() } } + [Fact] + public void EmitMetadata_DisallowOutputtingNetModule() + { + CSharpCompilation comp = CreateCompilation("", references: new[] { MscorlibRef }, + options: TestOptions.DebugDll.WithDeterministic(true).WithOutputKind(OutputKind.NetModule)); + + using (var output = new MemoryStream()) + using (var metadataPeOutput = new MemoryStream()) + { + Assert.Throws(() => comp.Emit(output, metadataPeStream: metadataPeOutput, + options: EmitOptions.Default)); + } + } + + [Fact] + public void EmitMetadataOnly_DisallowOutputtingNetModule() + { + CSharpCompilation comp = CreateCompilation("", references: new[] { MscorlibRef }, + options: TestOptions.DebugDll.WithDeterministic(true).WithOutputKind(OutputKind.NetModule)); + + using (var output = new MemoryStream()) + { + Assert.Throws(() => comp.Emit(output, + options: EmitOptions.Default.WithEmitMetadataOnly(true))); + } + } + [Fact] public void EmitMetadata() { diff --git a/src/Compilers/Core/Portable/CodeAnalysisResources.Designer.cs b/src/Compilers/Core/Portable/CodeAnalysisResources.Designer.cs index e89dfe380ab29..7dd8597b0b3b5 100644 --- a/src/Compilers/Core/Portable/CodeAnalysisResources.Designer.cs +++ b/src/Compilers/Core/Portable/CodeAnalysisResources.Designer.cs @@ -269,6 +269,15 @@ internal static string CannotEmbedInteropTypesFromModule { } } + /// + /// Looks up a localized string similar to Cannot target net module when emitting ref assembly.. + /// + internal static string CannotTargetNetModuleWhenEmittingRefAssembly { + get { + return ResourceManager.GetString("CannotTargetNetModuleWhenEmittingRefAssembly", resourceCulture); + } + } + /// /// Looks up a localized string similar to Can't create a module reference to an assembly.. /// diff --git a/src/Compilers/Core/Portable/CodeAnalysisResources.resx b/src/Compilers/Core/Portable/CodeAnalysisResources.resx index 198b316cb4b53..928a36ef445d3 100644 --- a/src/Compilers/Core/Portable/CodeAnalysisResources.resx +++ b/src/Compilers/Core/Portable/CodeAnalysisResources.resx @@ -336,6 +336,9 @@ Metadata PE stream should not be given when emitting metadata only. + + Cannot target net module when emitting ref assembly. + Invalid hash. diff --git a/src/Compilers/Core/Portable/Compilation/Compilation.cs b/src/Compilers/Core/Portable/Compilation/Compilation.cs index 0a9d62660e8ab..a9ffb9d65fe35 100644 --- a/src/Compilers/Core/Portable/Compilation/Compilation.cs +++ b/src/Compilers/Core/Portable/Compilation/Compilation.cs @@ -2072,6 +2072,18 @@ public EmitResult Emit( throw new ArgumentException(CodeAnalysisResources.MetadataPeStreamUnexpectedWhenEmittingMetadataOnly, nameof(metadataPeStream)); } + if (this.Options.OutputKind == OutputKind.NetModule) + { + if (metadataPeStream != null) + { + throw new ArgumentException(CodeAnalysisResources.CannotTargetNetModuleWhenEmittingRefAssembly, nameof(metadataPeStream)); + } + else if (options?.EmitMetadataOnly == true) + { + throw new ArgumentException(CodeAnalysisResources.CannotTargetNetModuleWhenEmittingRefAssembly, nameof(options.EmitMetadataOnly)); + } + } + if (win32Resources != null) { if (!win32Resources.CanRead || !win32Resources.CanSeek) diff --git a/src/Compilers/Core/Portable/PEWriter/MetadataWriter.cs b/src/Compilers/Core/Portable/PEWriter/MetadataWriter.cs index 614a16c7decc9..d54aee2c74a85 100644 --- a/src/Compilers/Core/Portable/PEWriter/MetadataWriter.cs +++ b/src/Compilers/Core/Portable/PEWriter/MetadataWriter.cs @@ -2887,7 +2887,7 @@ private int SerializeThrowNullMethodBody(MethodBodyStreamEncoder encoder) UserStringHandle mvidStringHandle = default(UserStringHandle); Blob mvidStringFixup = default(Blob); - return SerializeMethodBody( + int offset = SerializeMethodBody( encoder, ThrowNullIL, ThrowNullMaxStack, @@ -2896,6 +2896,9 @@ private int SerializeThrowNullMethodBody(MethodBodyStreamEncoder encoder) MethodBodyAttributes.None, ref mvidStringHandle, ref mvidStringFixup); + + Debug.Assert(mvidStringHandle.Equals(default(UserStringHandle)) && mvidStringFixup.Equals(default(Blob))); + return offset; } private int SerializeMethodBody( From ef4ee02f13320ef3de90e7efe3b8fc8e16f35b5c Mon Sep 17 00:00:00 2001 From: Julien Couvreur Date: Tue, 21 Mar 2017 10:27:06 -0700 Subject: [PATCH 14/14] Can no longer produce netmodule with metadata only --- .../CSharp/Test/Emit/Emit/ResourceTests.cs | 506 +++++++++--------- 1 file changed, 252 insertions(+), 254 deletions(-) diff --git a/src/Compilers/CSharp/Test/Emit/Emit/ResourceTests.cs b/src/Compilers/CSharp/Test/Emit/Emit/ResourceTests.cs index dc95a75b61541..a416a2b5979c8 100644 --- a/src/Compilers/CSharp/Test/Emit/Emit/ResourceTests.cs +++ b/src/Compilers/CSharp/Test/Emit/Emit/ResourceTests.cs @@ -432,323 +432,321 @@ public void AddManagedResource() c1 = null; } + [Fact] public void AddResourceToModule() { - for (int metadataOnlyIfNonzero = 0; metadataOnlyIfNonzero < 2; metadataOnlyIfNonzero++) - { - var metadataOnly = metadataOnlyIfNonzero != 0; - Func emit; - emit = (c, s, r) => c.Emit(s, manifestResources: r, options: new EmitOptions(metadataOnly: metadataOnly)); + bool metadataOnly = false; + Func emit; + emit = (c, s, r) => c.Emit(s, manifestResources: r, options: new EmitOptions(metadataOnly: metadataOnly)); - var sourceTree = SyntaxFactory.ParseSyntaxTree(""); + var sourceTree = SyntaxFactory.ParseSyntaxTree(""); - // Do not name the compilation, a unique guid is used as a name by default. It prevents conflicts with other assemblies loaded via Assembly.ReflectionOnlyLoad. - var c1 = CSharpCompilation.Create( - Guid.NewGuid().ToString(), - new[] { sourceTree }, - new[] { MscorlibRef }, - TestOptions.ReleaseModule); + // Do not name the compilation, a unique guid is used as a name by default. It prevents conflicts with other assemblies loaded via Assembly.ReflectionOnlyLoad. + var c1 = CSharpCompilation.Create( + Guid.NewGuid().ToString(), + new[] { sourceTree }, + new[] { MscorlibRef }, + TestOptions.ReleaseModule); - var resourceFileName = "RoslynResourceFile.foo"; - var output = new MemoryStream(); + var resourceFileName = "RoslynResourceFile.foo"; + var output = new MemoryStream(); - const string r1Name = "some.dotted.NAME"; - const string r2Name = "another.DoTtEd.NAME"; + const string r1Name = "some.dotted.NAME"; + const string r2Name = "another.DoTtEd.NAME"; - var arrayOfEmbeddedData = new byte[] { 1, 2, 3, 4, 5 }; - var resourceFileData = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + var arrayOfEmbeddedData = new byte[] { 1, 2, 3, 4, 5 }; + var resourceFileData = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; - var result = emit(c1, output, - new ResourceDescription[] - { - new ResourceDescription(r1Name, () => new MemoryStream(arrayOfEmbeddedData), true), - new ResourceDescription(r2Name, resourceFileName, () => new MemoryStream(resourceFileData), false) - }); + var result = emit(c1, output, + new ResourceDescription[] + { + new ResourceDescription(r1Name, () => new MemoryStream(arrayOfEmbeddedData), true), + new ResourceDescription(r2Name, resourceFileName, () => new MemoryStream(resourceFileData), false) + }); - Assert.False(result.Success); - Assert.NotEmpty(result.Diagnostics.Where(x => x.Code == (int)ErrorCode.ERR_CantRefResource)); + Assert.False(result.Success); + Assert.NotEmpty(result.Diagnostics.Where(x => x.Code == (int)ErrorCode.ERR_CantRefResource)); - result = emit(c1, output, - new ResourceDescription[] - { - new ResourceDescription(r2Name, resourceFileName, () => new MemoryStream(resourceFileData), false), - new ResourceDescription(r1Name, () => new MemoryStream(arrayOfEmbeddedData), true) - }); + result = emit(c1, output, + new ResourceDescription[] + { + new ResourceDescription(r2Name, resourceFileName, () => new MemoryStream(resourceFileData), false), + new ResourceDescription(r1Name, () => new MemoryStream(arrayOfEmbeddedData), true) + }); - Assert.False(result.Success); - Assert.NotEmpty(result.Diagnostics.Where(x => x.Code == (int)ErrorCode.ERR_CantRefResource)); + Assert.False(result.Success); + Assert.NotEmpty(result.Diagnostics.Where(x => x.Code == (int)ErrorCode.ERR_CantRefResource)); - result = emit(c1, output, - new ResourceDescription[] - { - new ResourceDescription(r2Name, resourceFileName, () => new MemoryStream(resourceFileData), false) - }); + result = emit(c1, output, + new ResourceDescription[] + { + new ResourceDescription(r2Name, resourceFileName, () => new MemoryStream(resourceFileData), false) + }); - Assert.False(result.Success); - Assert.NotEmpty(result.Diagnostics.Where(x => x.Code == (int)ErrorCode.ERR_CantRefResource)); + Assert.False(result.Success); + Assert.NotEmpty(result.Diagnostics.Where(x => x.Code == (int)ErrorCode.ERR_CantRefResource)); - var c_mod1 = CSharpCompilation.Create( - Guid.NewGuid().ToString(), - new[] { sourceTree }, - new[] { MscorlibRef }, - TestOptions.ReleaseModule); + var c_mod1 = CSharpCompilation.Create( + Guid.NewGuid().ToString(), + new[] { sourceTree }, + new[] { MscorlibRef }, + TestOptions.ReleaseModule); - var output_mod1 = new MemoryStream(); - result = emit(c_mod1, output_mod1, - new ResourceDescription[] - { - new ResourceDescription(r1Name, () => new MemoryStream(arrayOfEmbeddedData), true) - }); + var output_mod1 = new MemoryStream(); + result = emit(c_mod1, output_mod1, + new ResourceDescription[] + { + new ResourceDescription(r1Name, () => new MemoryStream(arrayOfEmbeddedData), true) + }); - Assert.True(result.Success); - var mod1 = ModuleMetadata.CreateFromImage(output_mod1.ToImmutable()); - var ref_mod1 = mod1.GetReference(); - Assert.Equal(ManifestResourceAttributes.Public, mod1.Module.GetEmbeddedResourcesOrThrow()[0].Attributes); + Assert.True(result.Success); + var mod1 = ModuleMetadata.CreateFromImage(output_mod1.ToImmutable()); + var ref_mod1 = mod1.GetReference(); + Assert.Equal(ManifestResourceAttributes.Public, mod1.Module.GetEmbeddedResourcesOrThrow()[0].Attributes); - { - var c2 = CreateCompilationWithMscorlib(sourceTree, new[] { ref_mod1 }, TestOptions.ReleaseDll); - var output2 = new MemoryStream(); - var result2 = c2.Emit(output2); + { + var c2 = CreateCompilationWithMscorlib(sourceTree, new[] { ref_mod1 }, TestOptions.ReleaseDll); + var output2 = new MemoryStream(); + var result2 = c2.Emit(output2); - Assert.True(result2.Success); - var assembly = System.Reflection.Assembly.ReflectionOnlyLoad(output2.ToArray()); + Assert.True(result2.Success); + var assembly = System.Reflection.Assembly.ReflectionOnlyLoad(output2.ToArray()); - assembly.ModuleResolve += (object sender, ResolveEventArgs e) => + assembly.ModuleResolve += (object sender, ResolveEventArgs e) => + { + if (e.Name.Equals(c_mod1.SourceModule.Name)) { - if (e.Name.Equals(c_mod1.SourceModule.Name)) - { - return assembly.LoadModule(e.Name, output_mod1.ToArray()); - } + return assembly.LoadModule(e.Name, output_mod1.ToArray()); + } - return null; - }; + return null; + }; - string[] resourceNames = assembly.GetManifestResourceNames(); - Assert.Equal(1, resourceNames.Length); + string[] resourceNames = assembly.GetManifestResourceNames(); + Assert.Equal(1, resourceNames.Length); - var rInfo = assembly.GetManifestResourceInfo(r1Name); - Assert.Equal(System.Reflection.ResourceLocation.Embedded, rInfo.ResourceLocation); - Assert.Equal(c_mod1.SourceModule.Name, rInfo.FileName); + var rInfo = assembly.GetManifestResourceInfo(r1Name); + Assert.Equal(System.Reflection.ResourceLocation.Embedded, rInfo.ResourceLocation); + Assert.Equal(c_mod1.SourceModule.Name, rInfo.FileName); - var rData = assembly.GetManifestResourceStream(r1Name); - var rBytes = new byte[rData.Length]; - rData.Read(rBytes, 0, (int)rData.Length); - Assert.Equal(arrayOfEmbeddedData, rBytes); - } + var rData = assembly.GetManifestResourceStream(r1Name); + var rBytes = new byte[rData.Length]; + rData.Read(rBytes, 0, (int)rData.Length); + Assert.Equal(arrayOfEmbeddedData, rBytes); + } - var c_mod2 = CSharpCompilation.Create( - Guid.NewGuid().ToString(), - new[] { sourceTree }, - new[] { MscorlibRef }, - TestOptions.ReleaseModule); + var c_mod2 = CSharpCompilation.Create( + Guid.NewGuid().ToString(), + new[] { sourceTree }, + new[] { MscorlibRef }, + TestOptions.ReleaseModule); - var output_mod2 = new MemoryStream(); - result = emit(c_mod2, output_mod2, - new ResourceDescription[] - { - new ResourceDescription(r1Name, () => new MemoryStream(arrayOfEmbeddedData), true), - new ResourceDescription(r2Name, () => new MemoryStream(resourceFileData), true) - }); + var output_mod2 = new MemoryStream(); + result = emit(c_mod2, output_mod2, + new ResourceDescription[] + { + new ResourceDescription(r1Name, () => new MemoryStream(arrayOfEmbeddedData), true), + new ResourceDescription(r2Name, () => new MemoryStream(resourceFileData), true) + }); - Assert.True(result.Success); - var ref_mod2 = ModuleMetadata.CreateFromImage(output_mod2.ToImmutable()).GetReference(); + Assert.True(result.Success); + var ref_mod2 = ModuleMetadata.CreateFromImage(output_mod2.ToImmutable()).GetReference(); - { - var c3 = CreateCompilationWithMscorlib(sourceTree, new[] { ref_mod2 }, TestOptions.ReleaseDll); - var output3 = new MemoryStream(); - var result3 = c3.Emit(output3); + { + var c3 = CreateCompilationWithMscorlib(sourceTree, new[] { ref_mod2 }, TestOptions.ReleaseDll); + var output3 = new MemoryStream(); + var result3 = c3.Emit(output3); - Assert.True(result3.Success); - var assembly = Assembly.ReflectionOnlyLoad(output3.ToArray()); + Assert.True(result3.Success); + var assembly = Assembly.ReflectionOnlyLoad(output3.ToArray()); - assembly.ModuleResolve += (object sender, ResolveEventArgs e) => + assembly.ModuleResolve += (object sender, ResolveEventArgs e) => + { + if (e.Name.Equals(c_mod2.SourceModule.Name)) { - if (e.Name.Equals(c_mod2.SourceModule.Name)) - { - return assembly.LoadModule(e.Name, output_mod2.ToArray()); - } - - return null; - }; - - string[] resourceNames = assembly.GetManifestResourceNames(); - Assert.Equal(2, resourceNames.Length); - - var rInfo = assembly.GetManifestResourceInfo(r1Name); - Assert.Equal(ResourceLocation.Embedded, rInfo.ResourceLocation); - Assert.Equal(c_mod2.SourceModule.Name, rInfo.FileName); - - var rData = assembly.GetManifestResourceStream(r1Name); - var rBytes = new byte[rData.Length]; - rData.Read(rBytes, 0, (int)rData.Length); - Assert.Equal(arrayOfEmbeddedData, rBytes); - - rInfo = assembly.GetManifestResourceInfo(r2Name); - Assert.Equal(ResourceLocation.Embedded, rInfo.ResourceLocation); - Assert.Equal(c_mod2.SourceModule.Name, rInfo.FileName); - - rData = assembly.GetManifestResourceStream(r2Name); - rBytes = new byte[rData.Length]; - rData.Read(rBytes, 0, (int)rData.Length); - Assert.Equal(resourceFileData, rBytes); - } + return assembly.LoadModule(e.Name, output_mod2.ToArray()); + } - var c_mod3 = CSharpCompilation.Create( - Guid.NewGuid().ToString(), - new[] { sourceTree }, - new[] { MscorlibRef }, - TestOptions.ReleaseModule); + return null; + }; - var output_mod3 = new MemoryStream(); - result = emit(c_mod3, output_mod3, - new ResourceDescription[] - { - new ResourceDescription(r2Name, () => new MemoryStream(resourceFileData), false) - }); + string[] resourceNames = assembly.GetManifestResourceNames(); + Assert.Equal(2, resourceNames.Length); + + var rInfo = assembly.GetManifestResourceInfo(r1Name); + Assert.Equal(ResourceLocation.Embedded, rInfo.ResourceLocation); + Assert.Equal(c_mod2.SourceModule.Name, rInfo.FileName); - Assert.True(result.Success); - var mod3 = ModuleMetadata.CreateFromImage(output_mod3.ToImmutable()); - var ref_mod3 = mod3.GetReference(); - Assert.Equal(ManifestResourceAttributes.Private, mod3.Module.GetEmbeddedResourcesOrThrow()[0].Attributes); + var rData = assembly.GetManifestResourceStream(r1Name); + var rBytes = new byte[rData.Length]; + rData.Read(rBytes, 0, (int)rData.Length); + Assert.Equal(arrayOfEmbeddedData, rBytes); + rInfo = assembly.GetManifestResourceInfo(r2Name); + Assert.Equal(ResourceLocation.Embedded, rInfo.ResourceLocation); + Assert.Equal(c_mod2.SourceModule.Name, rInfo.FileName); + + rData = assembly.GetManifestResourceStream(r2Name); + rBytes = new byte[rData.Length]; + rData.Read(rBytes, 0, (int)rData.Length); + Assert.Equal(resourceFileData, rBytes); + } + + var c_mod3 = CSharpCompilation.Create( + Guid.NewGuid().ToString(), + new[] { sourceTree }, + new[] { MscorlibRef }, + TestOptions.ReleaseModule); + + var output_mod3 = new MemoryStream(); + result = emit(c_mod3, output_mod3, + new ResourceDescription[] { - var c4 = CreateCompilationWithMscorlib(sourceTree, new[] { ref_mod3 }, TestOptions.ReleaseDll); - var output4 = new MemoryStream(); - var result4 = c4.Emit(output4, manifestResources: - new ResourceDescription[] - { - new ResourceDescription(r1Name, () => new MemoryStream(arrayOfEmbeddedData), false) - }); + new ResourceDescription(r2Name, () => new MemoryStream(resourceFileData), false) + }); - Assert.True(result4.Success); - var assembly = System.Reflection.Assembly.ReflectionOnlyLoad(output4.ToArray()); + Assert.True(result.Success); + var mod3 = ModuleMetadata.CreateFromImage(output_mod3.ToImmutable()); + var ref_mod3 = mod3.GetReference(); + Assert.Equal(ManifestResourceAttributes.Private, mod3.Module.GetEmbeddedResourcesOrThrow()[0].Attributes); - assembly.ModuleResolve += (object sender, ResolveEventArgs e) => + { + var c4 = CreateCompilationWithMscorlib(sourceTree, new[] { ref_mod3 }, TestOptions.ReleaseDll); + var output4 = new MemoryStream(); + var result4 = c4.Emit(output4, manifestResources: + new ResourceDescription[] { - if (e.Name.Equals(c_mod3.SourceModule.Name)) - { - return assembly.LoadModule(e.Name, output_mod3.ToArray()); - } + new ResourceDescription(r1Name, () => new MemoryStream(arrayOfEmbeddedData), false) + }); - return null; - }; + Assert.True(result4.Success); + var assembly = System.Reflection.Assembly.ReflectionOnlyLoad(output4.ToArray()); - string[] resourceNames = assembly.GetManifestResourceNames(); - Assert.Equal(2, resourceNames.Length); + assembly.ModuleResolve += (object sender, ResolveEventArgs e) => + { + if (e.Name.Equals(c_mod3.SourceModule.Name)) + { + return assembly.LoadModule(e.Name, output_mod3.ToArray()); + } - var rInfo = assembly.GetManifestResourceInfo(r1Name); - Assert.Equal(ResourceLocation.Embedded | ResourceLocation.ContainedInManifestFile, rInfo.ResourceLocation); + return null; + }; - var rData = assembly.GetManifestResourceStream(r1Name); - var rBytes = new byte[rData.Length]; - rData.Read(rBytes, 0, (int)rData.Length); - Assert.Equal(arrayOfEmbeddedData, rBytes); + string[] resourceNames = assembly.GetManifestResourceNames(); + Assert.Equal(2, resourceNames.Length); - rInfo = assembly.GetManifestResourceInfo(r2Name); - Assert.Equal(ResourceLocation.Embedded, rInfo.ResourceLocation); - Assert.Equal(c_mod3.SourceModule.Name, rInfo.FileName); + var rInfo = assembly.GetManifestResourceInfo(r1Name); + Assert.Equal(ResourceLocation.Embedded | ResourceLocation.ContainedInManifestFile, rInfo.ResourceLocation); - rData = assembly.GetManifestResourceStream(r2Name); - rBytes = new byte[rData.Length]; - rData.Read(rBytes, 0, (int)rData.Length); - Assert.Equal(resourceFileData, rBytes); - } + var rData = assembly.GetManifestResourceStream(r1Name); + var rBytes = new byte[rData.Length]; + rData.Read(rBytes, 0, (int)rData.Length); + Assert.Equal(arrayOfEmbeddedData, rBytes); - { - var c5 = CreateCompilationWithMscorlib(sourceTree, new[] { ref_mod1, ref_mod3 }, TestOptions.ReleaseDll); - var output5 = new MemoryStream(); - var result5 = emit(c5, output5, null); + rInfo = assembly.GetManifestResourceInfo(r2Name); + Assert.Equal(ResourceLocation.Embedded, rInfo.ResourceLocation); + Assert.Equal(c_mod3.SourceModule.Name, rInfo.FileName); + + rData = assembly.GetManifestResourceStream(r2Name); + rBytes = new byte[rData.Length]; + rData.Read(rBytes, 0, (int)rData.Length); + Assert.Equal(resourceFileData, rBytes); + } - Assert.True(result5.Success); - var assembly = Assembly.ReflectionOnlyLoad(output5.ToArray()); + { + var c5 = CreateCompilationWithMscorlib(sourceTree, new[] { ref_mod1, ref_mod3 }, TestOptions.ReleaseDll); + var output5 = new MemoryStream(); + var result5 = emit(c5, output5, null); - assembly.ModuleResolve += (object sender, ResolveEventArgs e) => - { - if (e.Name.Equals(c_mod1.SourceModule.Name)) - { - return assembly.LoadModule(e.Name, output_mod1.ToArray()); - } - else if (e.Name.Equals(c_mod3.SourceModule.Name)) - { - return assembly.LoadModule(e.Name, output_mod3.ToArray()); - } - - return null; - }; - - string[] resourceNames = assembly.GetManifestResourceNames(); - Assert.Equal(2, resourceNames.Length); - - var rInfo = assembly.GetManifestResourceInfo(r1Name); - Assert.Equal(ResourceLocation.Embedded, rInfo.ResourceLocation); - Assert.Equal(c_mod1.SourceModule.Name, rInfo.FileName); - - var rData = assembly.GetManifestResourceStream(r1Name); - var rBytes = new byte[rData.Length]; - rData.Read(rBytes, 0, (int)rData.Length); - Assert.Equal(arrayOfEmbeddedData, rBytes); - - rInfo = assembly.GetManifestResourceInfo(r2Name); - Assert.Equal(ResourceLocation.Embedded, rInfo.ResourceLocation); - Assert.Equal(c_mod3.SourceModule.Name, rInfo.FileName); - - rData = assembly.GetManifestResourceStream(r2Name); - rBytes = new byte[rData.Length]; - rData.Read(rBytes, 0, (int)rData.Length); - Assert.Equal(resourceFileData, rBytes); - } + Assert.True(result5.Success); + var assembly = Assembly.ReflectionOnlyLoad(output5.ToArray()); + assembly.ModuleResolve += (object sender, ResolveEventArgs e) => { - var c6 = CreateCompilationWithMscorlib(sourceTree, new[] { ref_mod1, ref_mod2 }, TestOptions.ReleaseDll); - var output6 = new MemoryStream(); - var result6 = emit(c6, output6, null); - - if (metadataOnly) + if (e.Name.Equals(c_mod1.SourceModule.Name)) { - Assert.True(result6.Success); + return assembly.LoadModule(e.Name, output_mod1.ToArray()); } - else + else if (e.Name.Equals(c_mod3.SourceModule.Name)) { - Assert.False(result6.Success); - result6.Diagnostics.Verify( - // error CS1508: Resource identifier 'some.dotted.NAME' has already been used in this assembly - Diagnostic(ErrorCode.ERR_ResourceNotUnique).WithArguments("some.dotted.NAME") - ); + return assembly.LoadModule(e.Name, output_mod3.ToArray()); } - result6 = emit(c6, output6, - new ResourceDescription[] - { - new ResourceDescription(r2Name, () => new MemoryStream(resourceFileData), false) - }); + return null; + }; - if (metadataOnly) - { - Assert.True(result6.Success); - } - else - { - Assert.False(result6.Success); - result6.Diagnostics.Verify( - // error CS1508: Resource identifier 'some.dotted.NAME' has already been used in this assembly - Diagnostic(ErrorCode.ERR_ResourceNotUnique).WithArguments("some.dotted.NAME"), - // error CS1508: Resource identifier 'another.DoTtEd.NAME' has already been used in this assembly - Diagnostic(ErrorCode.ERR_ResourceNotUnique).WithArguments("another.DoTtEd.NAME") - ); - } + string[] resourceNames = assembly.GetManifestResourceNames(); + Assert.Equal(2, resourceNames.Length); + + var rInfo = assembly.GetManifestResourceInfo(r1Name); + Assert.Equal(ResourceLocation.Embedded, rInfo.ResourceLocation); + Assert.Equal(c_mod1.SourceModule.Name, rInfo.FileName); + + var rData = assembly.GetManifestResourceStream(r1Name); + var rBytes = new byte[rData.Length]; + rData.Read(rBytes, 0, (int)rData.Length); + Assert.Equal(arrayOfEmbeddedData, rBytes); + + rInfo = assembly.GetManifestResourceInfo(r2Name); + Assert.Equal(ResourceLocation.Embedded, rInfo.ResourceLocation); + Assert.Equal(c_mod3.SourceModule.Name, rInfo.FileName); + + rData = assembly.GetManifestResourceStream(r2Name); + rBytes = new byte[rData.Length]; + rData.Read(rBytes, 0, (int)rData.Length); + Assert.Equal(resourceFileData, rBytes); + } - c6 = CreateCompilationWithMscorlib(sourceTree, new[] { ref_mod1, ref_mod2 }, TestOptions.ReleaseModule); + { + var c6 = CreateCompilationWithMscorlib(sourceTree, new[] { ref_mod1, ref_mod2 }, TestOptions.ReleaseDll); + var output6 = new MemoryStream(); + var result6 = emit(c6, output6, null); + + if (metadataOnly) + { + Assert.True(result6.Success); + } + else + { + Assert.False(result6.Success); + result6.Diagnostics.Verify( + // error CS1508: Resource identifier 'some.dotted.NAME' has already been used in this assembly + Diagnostic(ErrorCode.ERR_ResourceNotUnique).WithArguments("some.dotted.NAME") + ); + } - result6 = emit(c6, output6, - new ResourceDescription[] - { - new ResourceDescription(r2Name, () => new MemoryStream(resourceFileData), false) - }); + result6 = emit(c6, output6, + new ResourceDescription[] + { + new ResourceDescription(r2Name, () => new MemoryStream(resourceFileData), false) + }); + if (metadataOnly) + { Assert.True(result6.Success); } + else + { + Assert.False(result6.Success); + result6.Diagnostics.Verify( + // error CS1508: Resource identifier 'some.dotted.NAME' has already been used in this assembly + Diagnostic(ErrorCode.ERR_ResourceNotUnique).WithArguments("some.dotted.NAME"), + // error CS1508: Resource identifier 'another.DoTtEd.NAME' has already been used in this assembly + Diagnostic(ErrorCode.ERR_ResourceNotUnique).WithArguments("another.DoTtEd.NAME") + ); + } + + c6 = CreateCompilationWithMscorlib(sourceTree, new[] { ref_mod1, ref_mod2 }, TestOptions.ReleaseModule); + + result6 = emit(c6, output6, + new ResourceDescription[] + { + new ResourceDescription(r2Name, () => new MemoryStream(resourceFileData), false) + }); + + Assert.True(result6.Success); } }