From 5daad64bf58b6209c1f8854f6b63ebc49d4598fb Mon Sep 17 00:00:00 2001 From: CyrusNajmabadi Date: Thu, 20 Jan 2022 14:20:50 -1000 Subject: [PATCH] Allow xml docs to still be created when 'emit metadata only' is on. (#57667) * Allow xml docs to still be created when 'emit metadata only' is on. * Add VB tests * Simplify * Simplify * Update src/Compilers/Core/Portable/Compilation/Compilation.cs * Fix * Remove parameter * Pass in doc mode explicitly * Actually show the full xml docs we get * Update src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs * Update src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs * Update src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs --- .../Portable/Compilation/CSharpCompilation.cs | 18 +- .../Test/Emit/Emit/CompilationEmitTests.cs | 305 +++++++++++++++++- .../Portable/CommandLine/CommonCompiler.cs | 11 +- .../Core/Portable/Compilation/Compilation.cs | 34 +- .../Compilation/VisualBasicCompilation.vb | 17 +- .../Test/Emit/Emit/CompilationEmitTests.vb | 290 ++++++++++++++++- 6 files changed, 639 insertions(+), 36 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs b/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs index 875093a533ff0..fbb9a58e46de2 100644 --- a/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs +++ b/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs @@ -3274,15 +3274,15 @@ private void GenerateModuleInitializer(PEModuleBuilder moduleBeingBuilt, Diagnos } } - internal override bool GenerateResourcesAndDocumentationComments( + internal override bool GenerateResources( CommonPEModuleBuilder moduleBuilder, - Stream? xmlDocStream, Stream? win32Resources, bool useRawWin32Resources, - string? outputNameOverride, DiagnosticBag diagnostics, CancellationToken cancellationToken) { + cancellationToken.ThrowIfCancellationRequested(); + // Use a temporary bag so we don't have to refilter pre-existing diagnostics. DiagnosticBag? resourceDiagnostics = DiagnosticBag.GetInstance(); @@ -3294,11 +3294,15 @@ internal override bool GenerateResourcesAndDocumentationComments( AddedModulesResourceNames(resourceDiagnostics), resourceDiagnostics); - if (!FilterAndAppendAndFreeDiagnostics(diagnostics, ref resourceDiagnostics, cancellationToken)) - { - return false; - } + return FilterAndAppendAndFreeDiagnostics(diagnostics, ref resourceDiagnostics, cancellationToken); + } + internal override bool GenerateDocumentationComments( + Stream? xmlDocStream, + string? outputNameOverride, + DiagnosticBag diagnostics, + CancellationToken cancellationToken) + { cancellationToken.ThrowIfCancellationRequested(); // Use a temporary bag so we don't have to refilter pre-existing diagnostics. diff --git a/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs b/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs index 0683a48eedec3..58eda81e723ad 100644 --- a/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs +++ b/src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs @@ -13,6 +13,7 @@ using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Reflection.PortableExecutable; +using System.Text; using System.Threading; using Microsoft.CodeAnalysis.CSharp.Emit; using Microsoft.CodeAnalysis.CSharp.Symbols; @@ -178,7 +179,6 @@ namespace N.; Diagnostic(ErrorCode.WRN_UnassignedInternalField, "field").WithArguments("N.X.field", "null").WithLocation(4, 21)); } - // Check that EmitMetadataOnly works [Fact] public void EmitMetadataOnly() { @@ -246,6 +246,309 @@ public static void Main() } } + [Fact] + public void EmitMetadataOnly_XmlDocs_NoDocMode_Success() + { + CSharpCompilation comp = CreateCompilation(@" +namespace Goo.Bar +{ + /// This should be emitted + public class Test1 + { + public static void SayHello() + { + Console.WriteLine(""hello""); + } + } +} +", assemblyName: "test", parseOptions: CSharpParseOptions.Default.WithDocumentationMode(DocumentationMode.None)); + + EmitResult emitResult; + byte[] mdOnlyImage; + byte[] xmlDocBytes; + + using (var peStream = new MemoryStream()) + using (var xmlStream = new MemoryStream()) + { + emitResult = comp.Emit(peStream, xmlDocumentationStream: xmlStream, options: new EmitOptions(metadataOnly: true)); + mdOnlyImage = peStream.ToArray(); + xmlDocBytes = xmlStream.ToArray(); + } + + Assert.True(emitResult.Success); + emitResult.Diagnostics.Verify(); + Assert.True(mdOnlyImage.Length > 0, "no metadata emitted"); + Assert.Equal( +@" + + + test + + + + +", + Encoding.UTF8.GetString(xmlDocBytes)); + } + + [Fact] + public void EmitMetadataOnly_XmlDocs_NoDocMode_SyntaxWarning() + { + CSharpCompilation comp = CreateCompilation(@" +namespace Goo.Bar +{ + /// This should still emit + public class Test1 + { + public static void SayHello() + { + Console.WriteLine(""hello""); + } + } +} +", assemblyName: "test", parseOptions: CSharpParseOptions.Default.WithDocumentationMode(DocumentationMode.None)); + + EmitResult emitResult; + byte[] mdOnlyImage; + byte[] xmlDocBytes; + + using (var peStream = new MemoryStream()) + using (var xmlStream = new MemoryStream()) + { + emitResult = comp.Emit(peStream, xmlDocumentationStream: xmlStream, options: new EmitOptions(metadataOnly: true)); + mdOnlyImage = peStream.ToArray(); + xmlDocBytes = xmlStream.ToArray(); + } + + Assert.True(emitResult.Success); + emitResult.Diagnostics.Verify(); + + Assert.True(mdOnlyImage.Length > 0, "no metadata emitted"); + Assert.Equal( + @" + + + test + + + + +", + Encoding.UTF8.GetString(xmlDocBytes)); + } + + [Fact] + public void EmitMetadataOnly_XmlDocs_DiagnoseDocMode_SyntaxWarning() + { + CSharpCompilation comp = CreateCompilation(@" +namespace Goo.Bar +{ + /// This should still emit + public class Test1 + { + public static void SayHello() + { + Console.WriteLine(""hello""); + } + } +} +", assemblyName: "test", parseOptions: CSharpParseOptions.Default.WithDocumentationMode(DocumentationMode.Diagnose)); + + EmitResult emitResult; + byte[] mdOnlyImage; + byte[] xmlDocBytes; + + using (var peStream = new MemoryStream()) + using (var xmlStream = new MemoryStream()) + { + emitResult = comp.Emit(peStream, xmlDocumentationStream: xmlStream, options: new EmitOptions(metadataOnly: true)); + mdOnlyImage = peStream.ToArray(); + xmlDocBytes = xmlStream.ToArray(); + } + + // This should not fail the emit (as it's a warning). + Assert.True(emitResult.Success); + emitResult.Diagnostics.Verify( + // (5,1): warning CS1570: XML comment has badly formed XML -- 'Expected an end tag for element 'summary'.' + // public class Test1 + Diagnostic(ErrorCode.WRN_XMLParseError, "").WithArguments("summary").WithLocation(5, 1), + // (7,28): warning CS1591: Missing XML comment for publicly visible type or member 'Test1.SayHello()' + // public static void SayHello() + Diagnostic(ErrorCode.WRN_MissingXMLComment, "SayHello").WithArguments("Goo.Bar.Test1.SayHello()").WithLocation(7, 28)); + + Assert.True(mdOnlyImage.Length > 0, "no metadata emitted"); + Assert.Equal( +@" + + + test + + + + + +", + Encoding.UTF8.GetString(xmlDocBytes)); + } + + [Fact] + public void EmitMetadataOnly_XmlDocs_DiagnoseDocMode_SemanticWarning() + { + CSharpCompilation comp = CreateCompilation(@" +namespace Goo.Bar +{ + /// + public class Test1 + { + public static void SayHello() + { + Console.WriteLine(""hello""); + } + } +} +", assemblyName: "test", parseOptions: CSharpParseOptions.Default.WithDocumentationMode(DocumentationMode.Diagnose)); + + EmitResult emitResult; + byte[] mdOnlyImage; + byte[] xmlDocBytes; + + using (var peStream = new MemoryStream()) + using (var xmlStream = new MemoryStream()) + { + emitResult = comp.Emit(peStream, xmlDocumentationStream: xmlStream, options: new EmitOptions(metadataOnly: true)); + mdOnlyImage = peStream.ToArray(); + xmlDocBytes = xmlStream.ToArray(); + } + + // This should not fail the emit (as it's a warning). + Assert.True(emitResult.Success); + emitResult.Diagnostics.Verify( + // (4,29): warning CS1574: XML comment has cref attribute 'T' that could not be resolved + // /// + Diagnostic(ErrorCode.WRN_BadXMLRef, "T").WithArguments("T").WithLocation(4, 29), + // (7,28): warning CS1591: Missing XML comment for publicly visible type or member 'Test1.SayHello()' + // public static void SayHello() + Diagnostic(ErrorCode.WRN_MissingXMLComment, "SayHello").WithArguments("Goo.Bar.Test1.SayHello()").WithLocation(7, 28)); + + Assert.True(mdOnlyImage.Length > 0, "no metadata emitted"); + Assert.Equal( +@" + + + test + + + + + + + +", + Encoding.UTF8.GetString(xmlDocBytes)); + } + + [Fact] + public void EmitMetadataOnly_XmlDocs_DiagnoseDocMode_Success() + { + CSharpCompilation comp = CreateCompilation(@" +namespace Goo.Bar +{ + /// This should emit + public class Test1 + { + public static void SayHello() + { + Console.WriteLine(""hello""); + } + } +} +", assemblyName: "test", parseOptions: CSharpParseOptions.Default.WithDocumentationMode(DocumentationMode.Diagnose)); + + EmitResult emitResult; + byte[] mdOnlyImage; + byte[] xmlDocBytes; + + using (var peStream = new MemoryStream()) + using (var xmlStream = new MemoryStream()) + { + emitResult = comp.Emit(peStream, xmlDocumentationStream: xmlStream, options: new EmitOptions(metadataOnly: true)); + mdOnlyImage = peStream.ToArray(); + xmlDocBytes = xmlStream.ToArray(); + } + + // This should not fail the emit (as it's a warning). + Assert.True(emitResult.Success); + emitResult.Diagnostics.Verify( + // (7,28): warning CS1591: Missing XML comment for publicly visible type or member 'Test1.SayHello()' + // public static void SayHello() + Diagnostic(ErrorCode.WRN_MissingXMLComment, "SayHello").WithArguments("Goo.Bar.Test1.SayHello()").WithLocation(7, 28)); + + Assert.True(mdOnlyImage.Length > 0, "no metadata emitted"); + Assert.Equal( +@" + + + test + + + + This should emit + + + +", + Encoding.UTF8.GetString(xmlDocBytes)); + } + + [Fact] + public void EmitMetadataOnly_XmlDocs_ParseDocMode_Success() + { + CSharpCompilation comp = CreateCompilation(@" +namespace Goo.Bar +{ + /// This should emit + public class Test1 + { + public static void SayHello() + { + Console.WriteLine(""hello""); + } + } +} +", assemblyName: "test", parseOptions: CSharpParseOptions.Default.WithDocumentationMode(DocumentationMode.Parse)); + + EmitResult emitResult; + byte[] mdOnlyImage; + byte[] xmlDocBytes; + + using (var peStream = new MemoryStream()) + using (var xmlStream = new MemoryStream()) + { + emitResult = comp.Emit(peStream, xmlDocumentationStream: xmlStream, options: new EmitOptions(metadataOnly: true)); + mdOnlyImage = peStream.ToArray(); + xmlDocBytes = xmlStream.ToArray(); + } + + Assert.True(emitResult.Success); + emitResult.Diagnostics.Verify(); + + Assert.True(mdOnlyImage.Length > 0, "no metadata emitted"); + Assert.Equal( + @" + + + test + + + + This should emit + + + +", + Encoding.UTF8.GetString(xmlDocBytes)); + } + [Fact] public void EmitRefAssembly_PrivateMain() { diff --git a/src/Compilers/Core/Portable/CommandLine/CommonCompiler.cs b/src/Compilers/Core/Portable/CommandLine/CommonCompiler.cs index 2245042f57874..b579dc1f0c8ff 100644 --- a/src/Compilers/Core/Portable/CommandLine/CommonCompiler.cs +++ b/src/Compilers/Core/Portable/CommandLine/CommonCompiler.cs @@ -1259,14 +1259,9 @@ private void CompileAndEmit( return; } - success = compilation.GenerateResourcesAndDocumentationComments( - moduleBeingBuilt, - xmlStreamDisposerOpt?.Stream, - win32ResourceStreamOpt, - useRawWin32Resources: false, - emitOptions.OutputNameOverride, - diagnostics, - cancellationToken); + success = + compilation.GenerateResources(moduleBeingBuilt, win32ResourceStreamOpt, useRawWin32Resources: false, diagnostics, cancellationToken) && + compilation.GenerateDocumentationComments(xmlStreamDisposerOpt?.Stream, emitOptions.OutputNameOverride, diagnostics, cancellationToken); } } diff --git a/src/Compilers/Core/Portable/Compilation/Compilation.cs b/src/Compilers/Core/Portable/Compilation/Compilation.cs index 48ea4ae8f0a0d..4d40459777aea 100644 --- a/src/Compilers/Core/Portable/Compilation/Compilation.cs +++ b/src/Compilers/Core/Portable/Compilation/Compilation.cs @@ -2334,14 +2334,22 @@ internal bool CreateDebugDocuments(DebugDocumentsBuilder documentsBuilder, IEnum internal abstract void AddDebugSourceDocumentsForChecksumDirectives(DebugDocumentsBuilder documentsBuilder, SyntaxTree tree, DiagnosticBag diagnostics); /// - /// Update resources and generate XML documentation comments. + /// Update resources. /// /// True if successful. - internal abstract bool GenerateResourcesAndDocumentationComments( - CommonPEModuleBuilder moduleBeingBuilt, - Stream? xmlDocumentationStream, - Stream? win32ResourcesStream, + internal abstract bool GenerateResources( + CommonPEModuleBuilder moduleBuilder, + Stream? win32Resources, bool useRawWin32Resources, + DiagnosticBag diagnostics, + CancellationToken cancellationToken); + + /// + /// Generate XML documentation comments. + /// + /// True if successful. + internal abstract bool GenerateDocumentationComments( + Stream? xmlDocStream, string? outputNameOverride, DiagnosticBag diagnostics, CancellationToken cancellationToken); @@ -2742,14 +2750,8 @@ internal EmitResult Emit( { // NOTE: We generate documentation even in presence of compile errors. // https://github.com/dotnet/roslyn/issues/37996 tracks revisiting this behavior. - if (!GenerateResourcesAndDocumentationComments( - moduleBeingBuilt, - xmlDocumentationStream, - win32Resources, - useRawWin32Resources: rebuildData is object, - options.OutputNameOverride, - diagnostics, - cancellationToken)) + if (!GenerateResources(moduleBeingBuilt, win32Resources, useRawWin32Resources: rebuildData is object, diagnostics, cancellationToken) || + !GenerateDocumentationComments(xmlDocumentationStream, options.OutputNameOverride, diagnostics, cancellationToken)) { success = false; } @@ -2759,6 +2761,12 @@ internal EmitResult Emit( ReportUnusedImports(diagnostics, cancellationToken); } } + else if (xmlDocumentationStream != null) + { + // If we're in metadata only, and the caller asks for xml docs, then still proceed and generate those. + success = GenerateDocumentationComments( + xmlDocumentationStream, options.OutputNameOverride, diagnostics, cancellationToken); + } } finally { diff --git a/src/Compilers/VisualBasic/Portable/Compilation/VisualBasicCompilation.vb b/src/Compilers/VisualBasic/Portable/Compilation/VisualBasicCompilation.vb index f600e10b64cd3..2f8a3cd02943f 100644 --- a/src/Compilers/VisualBasic/Portable/Compilation/VisualBasicCompilation.vb +++ b/src/Compilers/VisualBasic/Portable/Compilation/VisualBasicCompilation.vb @@ -2503,15 +2503,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Return True End Function - Friend Overrides Function GenerateResourcesAndDocumentationComments( + Friend Overrides Function GenerateResources( moduleBuilder As CommonPEModuleBuilder, - xmlDocStream As Stream, win32Resources As Stream, useRawWin32Resources As Boolean, - outputNameOverride As String, diagnostics As DiagnosticBag, cancellationToken As CancellationToken) As Boolean + cancellationToken.ThrowIfCancellationRequested() + ' Use a temporary bag so we don't have to refilter pre-existing diagnostics. Dim resourceDiagnostics = DiagnosticBag.GetInstance() @@ -2524,9 +2524,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic AddedModulesResourceNames(resourceDiagnostics), resourceDiagnostics) - If Not FilterAndAppendAndFreeDiagnostics(diagnostics, resourceDiagnostics, cancellationToken) Then - Return False - End If + Return FilterAndAppendAndFreeDiagnostics(diagnostics, resourceDiagnostics, cancellationToken) + End Function + + Friend Overrides Function GenerateDocumentationComments( + xmlDocStream As Stream, + outputNameOverride As String, + diagnostics As DiagnosticBag, + cancellationToken As CancellationToken) As Boolean cancellationToken.ThrowIfCancellationRequested() diff --git a/src/Compilers/VisualBasic/Test/Emit/Emit/CompilationEmitTests.vb b/src/Compilers/VisualBasic/Test/Emit/Emit/CompilationEmitTests.vb index bf050def0c3cf..8d857b7525507 100644 --- a/src/Compilers/VisualBasic/Test/Emit/Emit/CompilationEmitTests.vb +++ b/src/Compilers/VisualBasic/Test/Emit/Emit/CompilationEmitTests.vb @@ -238,7 +238,6 @@ BC30451: 'NoSuchMethod' is not declared. It may be inaccessible due to its prote Public Sub EmitMetadataOnly() - ' Check that Compilation.EmitMetadataOnly works. Dim compilation = CompilationUtils.CreateCompilationWithMscorlib40( @@ -299,6 +298,295 @@ End Class End Using End Sub + + Public Sub EmitMetadataOnly_XmlDocs_NoDocMode_Success() + Dim compilation = CreateCompilationWithMscorlib40( + + +Imports System + +Namespace Goo.Bar + ''' <summary>This should be emitted</summary> + Public Class X + End Class +End Namespace + +, assemblyName:="test", parseOptions:=VisualBasicParseOptions.Default.WithDocumentationMode(DocumentationMode.None)) + + Dim emitResult As EmitResult + Dim mdOnlyImage As Byte() + Dim xmlDocBytes As Byte() + + Using output = New MemoryStream() + Using xmlStream = New MemoryStream() + emitResult = compilation.Emit(output, xmlDocumentationStream:=xmlStream, options:=New EmitOptions(metadataOnly:=True)) + mdOnlyImage = output.ToArray() + xmlDocBytes = xmlStream.ToArray() + End Using + End Using + + Assert.True(emitResult.Success) + emitResult.Diagnostics.Verify() + + Assert.True(mdOnlyImage.Length > 0, "no metadata emitted") + Assert.Equal( +" + + + +test + + + + + +", + Encoding.UTF8.GetString(xmlDocBytes)) + End Sub + + + Public Sub EmitMetadataOnly_XmlDocs_NoDocMode_SyntaxWarning() + Dim compilation = CreateCompilationWithMscorlib40( + + +Imports System + +Namespace Goo.Bar + ''' <summary>This should still emit + Public Class X + End Class +End Namespace + +, assemblyName:="test", parseOptions:=VisualBasicParseOptions.Default.WithDocumentationMode(DocumentationMode.None)) + + Dim emitResult As EmitResult + Dim mdOnlyImage As Byte() + Dim xmlDocBytes As Byte() + + Using output = New MemoryStream() + Using xmlStream = New MemoryStream() + emitResult = compilation.Emit(output, xmlDocumentationStream:=xmlStream, options:=New EmitOptions(metadataOnly:=True)) + mdOnlyImage = output.ToArray() + xmlDocBytes = xmlStream.ToArray() + End Using + End Using + + Assert.True(emitResult.Success) + emitResult.Diagnostics.Verify() + + Assert.True(mdOnlyImage.Length > 0, "no metadata emitted") + Assert.Equal( + " + + + +test + + + + + +", + Encoding.UTF8.GetString(xmlDocBytes)) + End Sub + + + Public Sub EmitMetadataOnly_XmlDocs_DiagnoseDocMode_SyntaxWarning() + Dim compilation = CreateCompilationWithMscorlib40( + + +Imports System + +Namespace Goo.Bar + ''' <summary>This should still emit + Public Class X + End Class +End Namespace + +, assemblyName:="test", parseOptions:=VisualBasicParseOptions.Default.WithDocumentationMode(DocumentationMode.Diagnose)) + + Dim emitResult As EmitResult + Dim mdOnlyImage As Byte() + Dim xmlDocBytes As Byte() + + Using output = New MemoryStream() + Using xmlStream = New MemoryStream() + emitResult = compilation.Emit(output, xmlDocumentationStream:=xmlStream, options:=New EmitOptions(metadataOnly:=True)) + mdOnlyImage = output.ToArray() + xmlDocBytes = xmlStream.ToArray() + End Using + End Using + + Assert.True(emitResult.Success) + emitResult.Diagnostics.Verify( + Diagnostic(ERRID.WRN_XMLDocParseError1, "").WithArguments("Element is missing an end tag.").WithLocation(4, 9), + Diagnostic(ERRID.WRN_XMLDocParseError1, "").WithArguments("Expected beginning '<' for an XML tag.").WithLocation(4, 40), + Diagnostic(ERRID.WRN_XMLDocParseError1, "").WithArguments("'>' expected.").WithLocation(4, 40)) + + Assert.True(mdOnlyImage.Length > 0, "no metadata emitted") + Assert.Equal( + " + + + +test + + + + + +", + Encoding.UTF8.GetString(xmlDocBytes)) + End Sub + + + Public Sub EmitMetadataOnly_XmlDocs_DiagnoseDocMode_SemanticWarning() + Dim compilation = CreateCompilationWithMscorlib40( + + +Imports System + +Namespace Goo.Bar + ''' <summary><see cref="T"/></summary> + Public Class X + End Class +End Namespace + +, assemblyName:="test", parseOptions:=VisualBasicParseOptions.Default.WithDocumentationMode(DocumentationMode.Diagnose)) + + Dim emitResult As EmitResult + Dim mdOnlyImage As Byte() + Dim xmlDocBytes As Byte() + + Using output = New MemoryStream() + Using xmlStream = New MemoryStream() + emitResult = compilation.Emit(output, xmlDocumentationStream:=xmlStream, options:=New EmitOptions(metadataOnly:=True)) + mdOnlyImage = output.ToArray() + xmlDocBytes = xmlStream.ToArray() + End Using + End Using + + Assert.True(emitResult.Success) + emitResult.Diagnostics.Verify( + Diagnostic(ERRID.WRN_XMLDocCrefAttributeNotFound1, "cref=""T""").WithArguments("T").WithLocation(4, 23)) + + Assert.True(mdOnlyImage.Length > 0, "no metadata emitted") + Assert.Equal( + " + + + +test + + + + + + + + +", + Encoding.UTF8.GetString(xmlDocBytes)) + End Sub + + + Public Sub EmitMetadataOnly_XmlDocs_DiagnoseDocMode_Success() + Dim compilation = CreateCompilationWithMscorlib40( + + +Imports System + +Namespace Goo.Bar + ''' <summary>This should emit</summary> + Public Class X + End Class +End Namespace + +, assemblyName:="test", parseOptions:=VisualBasicParseOptions.Default.WithDocumentationMode(DocumentationMode.Diagnose)) + + Dim emitResult As EmitResult + Dim mdOnlyImage As Byte() + Dim xmlDocBytes As Byte() + + Using output = New MemoryStream() + Using xmlStream = New MemoryStream() + emitResult = compilation.Emit(output, xmlDocumentationStream:=xmlStream, options:=New EmitOptions(metadataOnly:=True)) + mdOnlyImage = output.ToArray() + xmlDocBytes = xmlStream.ToArray() + End Using + End Using + + Assert.True(emitResult.Success) + emitResult.Diagnostics.Verify() + + Assert.True(mdOnlyImage.Length > 0, "no metadata emitted") + Assert.Equal( + " + + + +test + + + + + This should emit + + + +", + Encoding.UTF8.GetString(xmlDocBytes)) + End Sub + + + Public Sub EmitMetadataOnly_XmlDocs_ParseDocMode_Success() + Dim compilation = CreateCompilationWithMscorlib40( + + +Imports System + +Namespace Goo.Bar + ''' <summary>This should emit</summary> + Public Class X + End Class +End Namespace + +, assemblyName:="test", parseOptions:=VisualBasicParseOptions.Default.WithDocumentationMode(DocumentationMode.Parse)) + + Dim emitResult As EmitResult + Dim mdOnlyImage As Byte() + Dim xmlDocBytes As Byte() + + Using output = New MemoryStream() + Using xmlStream = New MemoryStream() + emitResult = compilation.Emit(output, xmlDocumentationStream:=xmlStream, options:=New EmitOptions(metadataOnly:=True)) + mdOnlyImage = output.ToArray() + xmlDocBytes = xmlStream.ToArray() + End Using + End Using + + Assert.True(emitResult.Success) + emitResult.Diagnostics.Verify() + + Assert.True(mdOnlyImage.Length > 0, "no metadata emitted") + Assert.Equal( + " + + + +test + + + + + This should emit + + + +", + Encoding.UTF8.GetString(xmlDocBytes)) + End Sub + Private Sub EmitRefAssembly_PrivatePropertyGetter() Dim source As String = "