/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/CSharp/Test/Symbol/Symbols/ModuleInitializers/ModuleInitializersTests.cs
1 161 строка
32 KB
AlekseyTs
Implement INamespaceTypeReference.GetUnit for RootModuleType (#56450)
17 сен 2021, 21:21
Не верифицирован
17 сен 2021, 21:21
d695369
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #nullable disable using System.Collections.Immutable; using System.Reflection; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.Emit; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using Roslyn.Utilities; using Xunit; namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Symbols.ModuleInitializers { [CompilerTrait(CompilerFeature.ModuleInitializers)] public sealed class ModuleInitializersTests : CSharpTestBase { private static readonly CSharpParseOptions s_parseOptions = TestOptions.Regular9; [Fact] public static void LastLanguageVersionNotSupportingModuleInitializersIs8() { var source = @"using System.Runtime.CompilerServices; class C { [ModuleInitializer] internal static void M() { } } namespace System.Runtime.CompilerServices { class ModuleInitializerAttribute : System.Attribute { } } "; var compilation = CreateCompilation(source, parseOptions: TestOptions.Regular8); compilation.VerifyDiagnostics( // (5,6): error CS8400: Feature 'module initializers' is not available in C# 8.0. Please use language version 9.0 or greater. // [ModuleInitializer] Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion8, "ModuleInitializer").WithArguments("module initializers", "9.0").WithLocation(5, 6) ); } [Fact] public static void FirstLanguageVersionSupportingModuleInitializersIs9() { var source = @"using System.Runtime.CompilerServices; class C { [ModuleInitializer] internal static void M() { } } namespace System.Runtime.CompilerServices { class ModuleInitializerAttribute : System.Attribute { } } "; var compilation = CreateCompilation(source, parseOptions: TestOptions.Regular9); compilation.VerifyDiagnostics(); } [Fact] public void ModuleTypeStaticConstructorIsNotEmittedWhenNoMethodIsMarkedWithModuleInitializerAttribute() { string source = @" using System; using System.Runtime.CompilerServices; class C { internal static void M() => Console.WriteLine(""C.M""); } class Program { static void Main() => Console.WriteLine(""Program.Main""); } namespace System.Runtime.CompilerServices { class ModuleInitializerAttribute : System.Attribute { } } "; CompileAndVerify( source, parseOptions: s_parseOptions, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), symbolValidator: module => { Assert.Equal(MetadataImportOptions.All, ((PEModuleSymbol)module).ImportOptions); var rootModuleType = (TypeSymbol)module.GlobalNamespace.GetMember("<Module>"); Assert.Null(rootModuleType.GetMember(".cctor")); }, expectedOutput: @" Program.Main"); } [Fact] public void ModuleTypeStaticConstructorCallsMethodMarkedWithModuleInitializerAttribute() { string source = @" using System; using System.Runtime.CompilerServices; class C { [ModuleInitializer] internal static void M() => Console.WriteLine(""C.M""); } class Program { static void Main() => Console.WriteLine(""Program.Main""); } namespace System.Runtime.CompilerServices { class ModuleInitializerAttribute : System.Attribute { } } "; CompileAndVerify( source, parseOptions: s_parseOptions, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), symbolValidator: module => { Assert.Equal(MetadataImportOptions.All, ((PEModuleSymbol)module).ImportOptions); var rootModuleType = (TypeSymbol)module.GlobalNamespace.GetMember("<Module>"); var staticConstructor = (PEMethodSymbol)rootModuleType.GetMember(".cctor"); Assert.NotNull(staticConstructor); Assert.Equal(MethodKind.StaticConstructor, staticConstructor.MethodKind); var expectedFlags = MethodAttributes.Private | MethodAttributes.Static | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName | MethodAttributes.HideBySig; Assert.Equal(expectedFlags, staticConstructor.Flags); }, expectedOutput: @" C.M Program.Main"); } [Fact] public void SingleCallIsGeneratedWhenMethodIsMarkedTwice() { string source = @" using System; using System.Runtime.CompilerServices; class C { [ModuleInitializer, ModuleInitializer] internal static void M() => Console.WriteLine(""C.M""); } class Program { static void Main() { } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] class ModuleInitializerAttribute : System.Attribute { } } "; CompileAndVerify(source, parseOptions: s_parseOptions, expectedOutput: "C.M"); } [Fact] public void AttributeCanBeAppliedWithinItsOwnDefinition() { string source = @" using System; class Program { static void Main() => Console.WriteLine(""Program.Main""); } namespace System.Runtime.CompilerServices { class ModuleInitializerAttribute : System.Attribute { [ModuleInitializer] internal static void M() => Console.WriteLine(""ModuleInitializerAttribute.M""); } } "; CompileAndVerify(source, parseOptions: s_parseOptions, expectedOutput: @" ModuleInitializerAttribute.M Program.Main"); } [Fact] public void ExternMethodCanBeModuleInitializer() { string source = @" using System.Runtime.CompilerServices; using System.Runtime.InteropServices; class C { [ModuleInitializer, DllImport(""dllName"")] internal static extern void M(); } namespace System.Runtime.CompilerServices { class ModuleInitializerAttribute : System.Attribute { } } "; CompileAndVerify( source, parseOptions: s_parseOptions, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), symbolValidator: module => { Assert.Equal(MetadataImportOptions.All, ((PEModuleSymbol)module).ImportOptions); var rootModuleType = module.ContainingAssembly.GetTypeByMetadataName("<Module>"); Assert.NotNull(rootModuleType.GetMember(".cctor")); }); } [Fact] public void MayBeDeclaredByStruct() { string source = @" using System; using System.Runtime.CompilerServices; struct S { [ModuleInitializer] internal static void M() => Console.WriteLine(""S.M""); } class Program { static void Main() => Console.WriteLine(""Program.Main""); } namespace System.Runtime.CompilerServices { class ModuleInitializerAttribute : System.Attribute { } } "; CompileAndVerify(source, parseOptions: s_parseOptions, expectedOutput: @" S.M Program.Main"); } [Fact] public void MayBeDeclaredByInterface() { string source = @" using System; using System.Runtime.CompilerServices; interface I { [ModuleInitializer] internal static void M() => Console.WriteLine(""I.M""); } class Program { static void Main() => Console.WriteLine(""Program.Main""); } namespace System.Runtime.CompilerServices { class ModuleInitializerAttribute : System.Attribute { } } "; CompileAndVerify( source, parseOptions: s_parseOptions, targetFramework: TargetFramework.NetCoreApp, expectedOutput: ExecutionConditionUtil.IsMonoOrCoreClr ? @" I.M Program.Main" : null, verify: ExecutionConditionUtil.IsMonoOrCoreClr ? Verification.Passes : Verification.Skipped); } [Fact] public void MultipleInitializers_SingleFile() { string source = @" using System; using System.Runtime.CompilerServices; class C1 { [ModuleInitializer] internal static void M1() => Console.Write(1); internal class C2 { [ModuleInitializer] internal static void M2() => Console.Write(2); } [ModuleInitializer] internal static void M3() => Console.Write(3); } class Program { static void Main() => Console.Write(4); } namespace System.Runtime.CompilerServices { class ModuleInitializerAttribute : System.Attribute { } } "; CompileAndVerify( source, parseOptions: s_parseOptions, expectedOutput: "1234"); } [Fact] public void MultipleInitializers_DifferentContainingTypeKinds() { string source = @" using System; using System.Runtime.CompilerServices; class C1 { [ModuleInitializer] internal static void M1() => Console.Write(1); } struct S1 { [ModuleInitializer] internal static void M2() => Console.Write(2); } interface I1 { [ModuleInitializer] internal static void M3() => Console.Write(3); } class Program { static void Main() => Console.Write(4); } namespace System.Runtime.CompilerServices { class ModuleInitializerAttribute : System.Attribute { } } "; CompileAndVerify( source, parseOptions: s_parseOptions, targetFramework: TargetFramework.NetCoreApp, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : "1234", verify: !ExecutionConditionUtil.IsMonoOrCoreClr ? Verification.Skipped : Verification.Passes); } [Fact] public void MultipleInitializers_MultipleFiles() { string source1 = @" using System; using System.Runtime.CompilerServices; class C1 { [ModuleInitializer] internal static void M1() => Console.Write(1); [ModuleInitializer] internal static void M2() => Console.Write(2); } namespace System.Runtime.CompilerServices { class ModuleInitializerAttribute : System.Attribute { } } "; string source2 = @" using System; using System.Runtime.CompilerServices; class C2 { internal class C3 { [ModuleInitializer] internal static void M3() => Console.Write(3); } [ModuleInitializer] internal static void M4() => Console.Write(4); } class Program { static void Main() => Console.Write(6); } "; string source3 = @" using System; using System.Runtime.CompilerServices; class C4 { // shouldn't be called internal static void M() => Console.Write(0); [ModuleInitializer] internal static void M5() => Console.Write(5); } "; CompileAndVerify( new[] { source1, source2, source3 }, parseOptions: s_parseOptions, expectedOutput: "123456"); } [Fact] public void StaticConstructor_Ordering() { const string text = @" using System; using System.Runtime.CompilerServices; class C1 { [ModuleInitializer] internal static void Init() => Console.Write(1); } class C2 { static C2() => Console.Write(2); static void Main() { Console.Write(3); } } namespace System.Runtime.CompilerServices { class ModuleInitializerAttribute : System.Attribute { } } "; var verifier = CompileAndVerify(text, parseOptions: s_parseOptions, expectedOutput: "123"); verifier.VerifyDiagnostics(); } [Fact] public void StaticConstructor_Ordering_SameType() { const string text = @" using System; using System.Runtime.CompilerServices; class C { static C() => Console.Write(1); [ModuleInitializer] internal static void Init() => Console.Write(2); static void Main() { Console.Write(3); } } namespace System.Runtime.CompilerServices { class ModuleInitializerAttribute : System.Attribute { } } "; var verifier = CompileAndVerify(text, parseOptions: s_parseOptions, expectedOutput: "123"); verifier.VerifyDiagnostics(); } [Fact] public void StaticConstructor_DefaultInitializer_SameType() { const string text = @" using System; using System.Runtime.CompilerServices; class C { internal static string s1 = null; [ModuleInitializer] internal static void Init() { s1 = ""hello""; } static void Main() { Console.Write(s1); } } namespace System.Runtime.CompilerServices { class ModuleInitializerAttribute : System.Attribute { } } "; var verifier = CompileAndVerify( text, parseOptions: s_parseOptions, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), expectedOutput: "hello", symbolValidator: validator); verifier.VerifyDiagnostics(); void validator(ModuleSymbol module) { var cType = module.ContainingAssembly.GetTypeByMetadataName("C"); // static constructor should be optimized out Assert.Null(cType.GetMember<MethodSymbol>(".cctor")); var moduleType = module.ContainingAssembly.GetTypeByMetadataName("<Module>"); Assert.NotNull(moduleType.GetMember<MethodSymbol>(".cctor")); } } [Fact] public void StaticConstructor_EffectingInitializer_SameType() { const string text = @" using System; using System.Runtime.CompilerServices; class C { internal static int i = InitField(); internal static int InitField() { Console.Write(1); return -1; } [ModuleInitializer] internal static void Init() { i = 2; } static void Main() { Console.Write(i); } } namespace System.Runtime.CompilerServices { class ModuleInitializerAttribute : System.Attribute { } } "; var verifier = CompileAndVerify( text, parseOptions: s_parseOptions, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), expectedOutput: "12", symbolValidator: validator); verifier.VerifyDiagnostics(); void validator(ModuleSymbol module) { var cType = module.ContainingAssembly.GetTypeByMetadataName("C"); Assert.NotNull(cType.GetMember<MethodSymbol>(".cctor")); var moduleType = module.ContainingAssembly.GetTypeByMetadataName("<Module>"); Assert.NotNull(moduleType.GetMember<MethodSymbol>(".cctor")); } } [Fact] public void StaticConstructor_DefaultInitializer_OtherType() { const string text = @" using System; using System.Runtime.CompilerServices; class C1 { [ModuleInitializer] internal static void Init() { C2.s1 = ""hello""; } } class C2 { internal static string s1 = null; static void Main() { Console.Write(s1); } } namespace System.Runtime.CompilerServices { class ModuleInitializerAttribute : System.Attribute { } } "; var verifier = CompileAndVerify( text, parseOptions: s_parseOptions, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), expectedOutput: "hello", symbolValidator: validator); verifier.VerifyDiagnostics(); void validator(ModuleSymbol module) { var c2Type = module.ContainingAssembly.GetTypeByMetadataName("C2"); // static constructor should be optimized out Assert.Null(c2Type.GetMember<MethodSymbol>(".cctor")); var moduleType = module.ContainingAssembly.GetTypeByMetadataName("<Module>"); Assert.NotNull(moduleType.GetMember<MethodSymbol>(".cctor")); } } [Fact] public void StaticConstructor_EffectingInitializer_OtherType() { const string text = @" using System; using System.Runtime.CompilerServices; class C1 { [ModuleInitializer] internal static void Init() { C2.i = 2; } } class C2 { internal static int i = InitField(); static int InitField() { Console.Write(1); return -1; } static void Main() { Console.Write(i); } } namespace System.Runtime.CompilerServices { class ModuleInitializerAttribute : System.Attribute { } } "; var verifier = CompileAndVerify( text, parseOptions: s_parseOptions, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), expectedOutput: "12", symbolValidator: validator); verifier.VerifyDiagnostics(); void validator(ModuleSymbol module) { var c2Type = module.ContainingAssembly.GetTypeByMetadataName("C2"); Assert.NotNull(c2Type.GetMember<MethodSymbol>(".cctor")); var moduleType = module.ContainingAssembly.GetTypeByMetadataName("<Module>"); Assert.NotNull(moduleType.GetMember<MethodSymbol>(".cctor")); } } [Fact] public void ModuleInitializerAttributeIncludedByConditionalAttribute() { string source = @" #define INCLUDE using System; using System.Runtime.CompilerServices; class C { [ModuleInitializer] internal static void M() => Console.WriteLine(""C.M""); } class Program { static void Main() => Console.WriteLine(""Program.Main""); } namespace System.Runtime.CompilerServices { [System.Diagnostics.Conditional(""INCLUDE"")] class ModuleInitializerAttribute : System.Attribute { } } "; CompileAndVerify(source, parseOptions: s_parseOptions, expectedOutput: @" C.M Program.Main"); } [Fact] public void ModuleInitializerAttributeExcludedByConditionalAttribute() { string source = @" using System; using System.Runtime.CompilerServices; class C { [ModuleInitializer] internal static void M() => Console.WriteLine(""C.M""); } class Program { static void Main() => Console.WriteLine(""Program.Main""); } namespace System.Runtime.CompilerServices { [System.Diagnostics.Conditional(""EXCLUDE"")] class ModuleInitializerAttribute : System.Attribute { } } "; CompileAndVerify(source, parseOptions: s_parseOptions, expectedOutput: @" C.M Program.Main"); } [Fact] public void ModuleInitializerMethodIncludedByConditionalAttribute() { string source = @" #define INCLUDE using System; using System.Runtime.CompilerServices; class C { [System.Diagnostics.Conditional(""INCLUDE""), ModuleInitializer] internal static void Preceding() => Console.WriteLine(""C.Preceding""); [ModuleInitializer, System.Diagnostics.Conditional(""INCLUDE"")] internal static void Following() => Console.WriteLine(""C.Following""); } class Program { static void Main() => Console.WriteLine(""Program.Main""); } namespace System.Runtime.CompilerServices { class ModuleInitializerAttribute : System.Attribute { } } "; CompileAndVerify(source, parseOptions: s_parseOptions, expectedOutput: @" C.Preceding C.Following Program.Main"); } [Fact] public void ModuleInitializerMethodExcludedByConditionalAttribute() { string source = @" using System; using System.Runtime.CompilerServices; class C { [System.Diagnostics.Conditional(""EXCLUDE""), ModuleInitializer] internal static void Preceding() { } [ModuleInitializer, System.Diagnostics.Conditional(""EXCLUDE"")] internal static void Following() { } } namespace System.Runtime.CompilerServices { class ModuleInitializerAttribute : System.Attribute { } } "; CompileAndVerify( source, parseOptions: s_parseOptions, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), symbolValidator: module => { Assert.Equal(MetadataImportOptions.All, ((PEModuleSymbol)module).ImportOptions); var rootModuleType = module.ContainingAssembly.GetTypeByMetadataName("<Module>"); Assert.Null(rootModuleType.GetMember(".cctor")); }); } [Fact] public void ModuleInitializerMethodIsObsolete() { string source = @" using System; using System.Runtime.CompilerServices; class C { [Obsolete, ModuleInitializer] internal static void Init() => Console.WriteLine(""C.Init""); } class Program { static void Main() => Console.WriteLine(""Program.Main""); } namespace System.Runtime.CompilerServices { class ModuleInitializerAttribute : System.Attribute { } } "; CompileAndVerify(source, parseOptions: s_parseOptions, expectedOutput: @" C.Init Program.Main"); } [ConditionalFact(typeof(WindowsDesktopOnly), Reason = ConditionalSkipReason.NetModulesNeedDesktop)] public void MultipleNetmodules() { var moduleOptions = TestOptions.ReleaseModule.WithMetadataImportOptions(MetadataImportOptions.All); var s1 = @" using System; using System.Runtime.CompilerServices; public class A { [ModuleInitializer] public static void M1() { Console.Write(1); } } namespace System.Runtime.CompilerServices { public class ModuleInitializerAttribute : System.Attribute { } }"; var comp1 = CreateCompilation(s1, options: moduleOptions.WithModuleName("A"), parseOptions: s_parseOptions); comp1.VerifyDiagnostics(); var ref1 = comp1.EmitToImageReference(); CompileAndVerify(comp1, symbolValidator: validateModuleInitializer, verify: Verification.Skipped); var s2 = @" using System; using System.Runtime.CompilerServices; public class B { [ModuleInitializer] public static void M2() { Console.Write(2); } }"; var comp2 = CreateCompilation(s2, options: moduleOptions.WithModuleName("B"), parseOptions: s_parseOptions, references: new[] { ref1 }); comp2.VerifyDiagnostics(); var ref2 = comp2.EmitToImageReference(); CompileAndVerify(comp2, symbolValidator: validateModuleInitializer, verify: Verification.Skipped); var exeOptions = TestOptions.ReleaseExe .WithMetadataImportOptions(MetadataImportOptions.All) .WithModuleName("C"); var s3 = @" using System; public class Program { public static void Main(string[] args) { Console.Write(3); } }"; var comp3 = CreateCompilation(s3, options: exeOptions, parseOptions: s_parseOptions, references: new[] { ref1, ref2 }); comp3.VerifyDiagnostics(); CompileAndVerify(comp3, symbolValidator: validateNoModuleInitializer, expectedOutput: "3"); var s4 = @" using System; public class Program { public static void Main(string[] args) { new A(); new B(); Console.Write(3); } }"; var comp4 = CreateCompilation(s4, options: exeOptions, parseOptions: s_parseOptions, references: new[] { ref1, ref2 }); comp4.VerifyDiagnostics(); CompileAndVerify(comp4, symbolValidator: validateNoModuleInitializer, expectedOutput: "123"); var s5 = @" using System; public class Program { public static void Main(string[] args) { new B(); Console.Write(3); new A(); } }"; var comp5 = CreateCompilation(s5, options: exeOptions, parseOptions: s_parseOptions, references: new[] { ref1, ref2 }); comp5.VerifyDiagnostics(); // This order seems surprising, but is likely related to the order in which types are loaded when a method is called. CompileAndVerify(comp5, symbolValidator: validateNoModuleInitializer, expectedOutput: "213"); var s6 = @" using System; public class Program { public static void Main(string[] args) { new A(); Console.Write(3); } }"; var comp6 = CreateCompilation(s6, options: exeOptions, parseOptions: s_parseOptions, references: new[] { ref1, ref2 }); comp6.VerifyDiagnostics(); CompileAndVerify(comp6, symbolValidator: validateNoModuleInitializer, expectedOutput: "13"); var s7 = @" using System; using System.Runtime.CompilerServices; public class Program { [ModuleInitializer] public static void Init() { Console.Write(0); } public static void Main(string[] args) { new B(); Console.Write(3); } }"; var comp7 = CreateCompilation(s7, options: exeOptions, parseOptions: s_parseOptions, references: new[] { ref1, ref2 }); comp7.VerifyDiagnostics(); CompileAndVerify(comp7, symbolValidator: validateModuleInitializer, expectedOutput: "023"); var s8 = @" using System; using System.Runtime.CompilerServices; public class Program { [ModuleInitializer] public static void Init() { Console.Write(0); new A(); } public static void Main(string[] args) { new A(); new B(); Console.Write(3); } }"; var comp8 = CreateCompilation(s8, options: exeOptions, parseOptions: s_parseOptions, references: new[] { ref1, ref2 }); comp8.VerifyDiagnostics(); CompileAndVerify(comp8, symbolValidator: validateModuleInitializer, expectedOutput: "1023"); void validateModuleInitializer(ModuleSymbol module) { Assert.Equal(MetadataImportOptions.All, ((PEModuleSymbol)module).ImportOptions); var moduleType = module.ContainingAssembly.GetTypeByMetadataName("<Module>"); Assert.NotNull(moduleType.GetMember<MethodSymbol>(".cctor")); } void validateNoModuleInitializer(ModuleSymbol module) { Assert.Equal(MetadataImportOptions.All, ((PEModuleSymbol)module).ImportOptions); var moduleType = module.ContainingAssembly.GetTypeByMetadataName("<Module>"); Assert.Null(moduleType.GetMember<MethodSymbol>(".cctor")); } } [ConditionalFact(typeof(WindowsDesktopOnly), Reason = ConditionalSkipReason.NetModulesNeedDesktop)] public void NetmoduleFromIL_InitializerNotCalled() { var il = @" .class public auto ansi beforefieldinit A extends [mscorlib]System.Object { .method public hidebysig static void M1() cil managed { .custom instance void System.Runtime.CompilerServices.ModuleInitializerAttribute::.ctor() = ( 01 00 00 00 ) // Code size 9 (0x9) .maxstack 8 IL_0000: nop IL_0001: ldc.i4.0 IL_0002: call void [mscorlib]System.Console::Write(int32) IL_0007: nop IL_0008: ret } // end of method A::M1 .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { // Code size 8 (0x8) .maxstack 8 IL_0000: ldarg.0 IL_0001: call instance void [mscorlib]System.Object::.ctor() IL_0006: nop IL_0007: ret } // end of method A::.ctor } // end of class A .class public auto ansi beforefieldinit System.Runtime.CompilerServices.ModuleInitializerAttribute extends [mscorlib]System.Attribute { .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { // Code size 8 (0x8) .maxstack 8 IL_0000: ldarg.0 IL_0001: call instance void [mscorlib]System.Attribute::.ctor() IL_0006: nop IL_0007: ret } // end of method ModuleInitializerAttribute::.ctor } // end of class System.Runtime.CompilerServices.ModuleInitializerAttribute"; var source1 = @" using System; using System.Runtime.CompilerServices; public class A { [ModuleInitializer] public static void M1() { Console.Write(1); } public static void Main() { Console.Write(2); } } namespace System.Runtime.CompilerServices { public class ModuleInitializerAttribute : System.Attribute { } } "; var source2 = @" using System; using System.Runtime.CompilerServices; public class A { public static void M1() { Console.Write(0); } public static void Main() { Console.Write(1); } } namespace System.Runtime.CompilerServices { public class ModuleInitializerAttribute : System.Attribute { } } "; var exeOptions = TestOptions.ReleaseExe .WithMetadataImportOptions(MetadataImportOptions.All) .WithModuleName("C"); var comp = CreateCompilationWithIL(source1, il, parseOptions: s_parseOptions, options: exeOptions); CompileAndVerify(comp, symbolValidator: validateModuleInitializer, verify: Verification.Skipped, expectedOutput: "12"); comp = CreateCompilationWithIL(source2, il, parseOptions: s_parseOptions, options: exeOptions); CompileAndVerify(comp, symbolValidator: validateNoModuleInitializer, verify: Verification.Skipped, expectedOutput: "1"); void validateModuleInitializer(ModuleSymbol module) { Assert.Equal(MetadataImportOptions.All, ((PEModuleSymbol)module).ImportOptions); var moduleType = module.ContainingAssembly.GetTypeByMetadataName("<Module>"); Assert.NotNull(moduleType.GetMember<MethodSymbol>(".cctor")); } void validateNoModuleInitializer(ModuleSymbol module) { Assert.Equal(MetadataImportOptions.All, ((PEModuleSymbol)module).ImportOptions); var moduleType = module.ContainingAssembly.GetTypeByMetadataName("<Module>"); Assert.Null(moduleType.GetMember<MethodSymbol>(".cctor")); } } [Fact] public void MultipleAttributesViaExternAlias() { var source1 = @" namespace System.Runtime.CompilerServices { public class ModuleInitializerAttribute : System.Attribute { } } "; var ref1 = CreateCompilation(source1).ToMetadataReference(aliases: ImmutableArray.Create("Alias1")); var ref2 = CreateCompilation(source1).ToMetadataReference(aliases: ImmutableArray.Create("Alias2")); var source = @" extern alias Alias1; extern alias Alias2; using System; class Program { [Alias1::System.Runtime.CompilerServices.ModuleInitializer] internal static void Init1() { Console.Write(1); } [Alias2::System.Runtime.CompilerServices.ModuleInitializer] internal static void Init2() { Console.Write(2); } static void Main() { Console.Write(3); } } "; CompileAndVerify(source, parseOptions: s_parseOptions, references: new[] { ref1, ref2 }, expectedOutput: "123"); } [Fact] [WorkItem(56412, "https://github.com/dotnet/roslyn/issues/56412")] public void Issue56412() { string source = @" using System; using System.Runtime.CompilerServices; class C { [ModuleInitializer] internal static void M() => Console.WriteLine(""C.M""); } class Program { static void Main() => Console.WriteLine(""Program.Main""); } namespace System.Runtime.CompilerServices { class ModuleInitializerAttribute : System.Attribute { } } "; CompileAndVerify( source, options: TestOptions.ReleaseExe, emitOptions: EmitOptions.Default.WithDebugInformationFormat(PathUtilities.IsUnixLikePlatform ? DebugInformationFormat.PortablePdb : DebugInformationFormat.Pdb), expectedOutput: @" C.M Program.Main"); } } }