Skip to content

Commit

Permalink
Silently treat IncludePrivateMembers as true when emitting regular as…
Browse files Browse the repository at this point in the history
…semblies (#21359)
  • Loading branch information
jcouv authored Sep 1, 2017
1 parent 468d3c9 commit eb3f5ba
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 5 deletions.
37 changes: 34 additions & 3 deletions src/Compilers/CSharp/Test/Emit/Emit/CompilationEmitTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1576,6 +1576,36 @@ public class PublicClass
"System.Diagnostics.DebuggableAttribute" },
compWithReal.SourceModule.GetReferencedAssemblySymbols().Last().GetAttributes().Select(a => a.AttributeClass.ToTestDisplayString()));

// Verify metadata (types, members, attributes) of the regular assembly with IncludePrivateMembers accidentally set to false.
// Note this can happen because of binary clients compiled against old EmitOptions ctor which had IncludePrivateMembers=false by default.
// In this case, IncludePrivateMembers is silently set to true when emitting
// See https://github.com/dotnet/roslyn/issues/20873
var emitRegularWithoutPrivateMembers = EmitOptions.Default.WithIncludePrivateMembers(false);
CompileAndVerify(comp, emitOptions: emitRegularWithoutPrivateMembers, verify: true);

var realImage2 = comp.EmitToImageReference(emitRegularWithoutPrivateMembers);
var compWithReal2 = CreateCompilation("", references: new[] { MscorlibRef, realImage2 },
options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All));
AssertEx.Equal(
new[] { "<Module>", "<>f__AnonymousType0<<anonymous>j__TPar>", "PublicClass" },
compWithReal2.SourceModule.GetReferencedAssemblySymbols().Last().GlobalNamespace.GetMembers().Select(m => m.ToDisplayString()));

AssertEx.Equal(
new[] { "void PublicClass.PublicMethod()", "void PublicClass.PrivateMethod()",
"void PublicClass.ProtectedMethod()", "void PublicClass.InternalMethod()",
"void PublicClass.PublicEvent.add", "void PublicClass.PublicEvent.remove",
"void PublicClass.InternalEvent.add", "void PublicClass.InternalEvent.remove",
"PublicClass..ctor()",
"event System.Action PublicClass.PublicEvent", "event System.Action PublicClass.InternalEvent" },
compWithReal2.GetMember<NamedTypeSymbol>("PublicClass").GetMembers()
.Select(m => m.ToTestDisplayString()));

AssertEx.Equal(
new[] { "System.Runtime.CompilerServices.CompilationRelaxationsAttribute",
"System.Runtime.CompilerServices.RuntimeCompatibilityAttribute",
"System.Diagnostics.DebuggableAttribute" },
compWithReal2.SourceModule.GetReferencedAssemblySymbols().Last().GetAttributes().Select(a => a.AttributeClass.ToTestDisplayString()));

// verify metadata (types, members, attributes) of the metadata-only assembly
var emitMetadataOnly = EmitOptions.Default.WithEmitMetadataOnly(true);
CompileAndVerify(comp, emitOptions: emitMetadataOnly, verify: true);
Expand Down Expand Up @@ -1732,15 +1762,16 @@ public void IncludePrivateMembers_DisallowMetadataPeStream()
}

[Fact]
public void MustIncludePrivateMembersUnlessRefAssembly()
[WorkItem(20873, "https://github.com/dotnet/roslyn/issues/20873")]
public void IncludePrivateMembersSilentlyAssumedTrueWhenEmittingRegular()
{
CSharpCompilation comp = CreateCompilation("", references: new[] { MscorlibRef },
options: TestOptions.DebugDll.WithDeterministic(true));

using (var output = new MemoryStream())
{
Assert.Throws<ArgumentException>(() => comp.Emit(output,
options: EmitOptions.Default.WithIncludePrivateMembers(false)));
// no exception
_ = comp.Emit(output, options: EmitOptions.Default.WithIncludePrivateMembers(false));
}
}

Expand Down
5 changes: 3 additions & 2 deletions src/Compilers/Core/Portable/Compilation/Compilation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2086,9 +2086,10 @@ public EmitResult Emit(
throw new ArgumentException(CodeAnalysisResources.IncludingPrivateMembersUnexpectedWhenEmittingToMetadataPeStream, nameof(metadataPEStream));
}

if (metadataPEStream == null && options?.EmitMetadataOnly == false && options?.IncludePrivateMembers == false)
if (metadataPEStream == null && options?.EmitMetadataOnly == false)
{
throw new ArgumentException(CodeAnalysisResources.MustIncludePrivateMembersUnlessRefAssembly, nameof(options.IncludePrivateMembers));
// EmitOptions used to default to IncludePrivateMembers=false, so to preserve binary compatibility we silently correct that unless emitting regular assemblies
options = options.WithIncludePrivateMembers(true);
}

if (options?.DebugInformationFormat == DebugInformationFormat.Embedded &&
Expand Down

0 comments on commit eb3f5ba

Please sign in to comment.