Repository: dotnet/runtime
File: src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/TypeMap.cs (C#)

Code before:
[assembly: TypeMapAssociation<UsedProxyTypeMap>(typeof(UsedProxySource2), typeof(UsedProxyTarget2))] // Kept

[assembly: TypeMapAssociation<UsedTypeMap>(typeof(SourceClass), typeof(ProxyType))]
[assembly: TypeMapAssociation<UsedTypeMap>(typeof(TypeCheckOnlyClass), typeof(TypeCheckOnlyProxy))]
[assembly: TypeMapAssociation<UsedTypeMap>(typeof(AllocatedNoBoxStructType), typeof(AllocatedNoBoxProxy))]
[assembly: TypeMapAssociation<UsedTypeMap>(typeof(I), typeof(IImpl))]
[assembly: TypeMapAssociation<UsedTypeMap>(typeof(IInterfaceWithDynamicImpl), typeof(IDynamicImpl))]
[assembly: TypeMapAssociation<UsedTypeMap>(typeof(ArrayElement), typeof(ArrayElementProxy))]

[assembly: TypeMap<UnusedTypeMap>("UnusedName", typeof(UnusedTargetType), typeof(TrimTarget))]
[assembly: TypeMapAssociation<UsedTypeMap>(typeof(UnusedSourceClass), typeof(UnusedProxyType))]
[assembly: TypeMap<UsedTypeMap>("ClassWithStaticMethod", typeof(TargetType4), typeof(ClassWithStaticMethod))]
[assembly: TypeMap<UsedTypeMap>("ClassWithStaticMethodAndField", typeof(TargetType5), typeof(ClassWithStaticMethodAndField))]

[assembly: KeptAttributeAttribute(typeof(TypeMapAssemblyTargetAttribute<UsedTypeMap>))]
[assembly: TypeMapAssemblyTarget<UsedTypeMap>("library")]
// TypeMapAssemblyTarget is kept regardless of which type map the program needs (External or Proxy)
[assembly: KeptAttributeAttribute(typeof(TypeMapAssemblyTargetAttribute<UsedProxyTypeMap>))]
[assembly: KeptAttributeAttribute(typeof(TypeMapAssemblyTargetAttribute<UsedExternalTypeMap>))]
[assembly: KeptAttributeAttribute(typeof(TypeMapAssemblyTargetAttribute<UsedTypeMapUniverse>))]
[assembly: TypeMapAssemblyTarget<UsedProxyTypeMap>("library")]
[assembly: TypeMapAssemblyTarget<UsedExternalTypeMap>("library")]
[assembly: TypeMapAssemblyTarget<UsedTypeMapUniverse>("library")]
[assembly: TypeMapAssemblyTarget<UnusedTypeMap2>("library")] // Should be removed

namespace Mono.Linker.Tests.Cases.Reflection
{
    [SetupLinkerAction("link", "System.Private.CoreLib")] // Needed to get the RemoveAttributeInstances in embedded xml
    [SetupLinkerArgument("--ignore-link-attributes", "false")]
    [SetupCompileArgument("/unsafe")]
    [SetupCompileBefore("library.dll", new[] { "Dependencies/TypeMapReferencedAssembly.cs" })]
    [SetupCompileBefore("library2.dll", new[] { "Dependencies/TypeMapSecondOrderReference.cs" })]
    [Kept]
    [KeptAssembly("library.dll")]
    [KeptAssembly("library2.dll")]
    [KeptTypeInAssembly("library.dll", typeof(TypeMapReferencedAssembly))]
    [KeptMemberInAssembly("library.dll", typeof(TypeMapReferencedAssembly), "Run()")]
    [KeptTypeInAssembly("library.dll", typeof(TargetTypeUnconditional1), Tool = Tool.Trimmer)]
    [KeptTypeInAssembly("library.dll", typeof(TrimTarget1))]
    [KeptMemberInAssembly("library.dll", typeof(TrimTarget1), ".ctor()")]
    [KeptTypeInAssembly("library.dll", typeof(TrimTarget2))]
    [KeptMemberInAssembly("library.dll", typeof(TrimTarget2), ".ctor()")]
    [KeptTypeInAssembly("library.dll", typeof(TargetTypeConditional1), Tool = Tool.Trimmer)]
    [KeptTypeInAssembly("library.dll", typeof(ProxySource1))]
    [KeptMemberInAssembly("library.dll", typeof(ProxySource1), ".ctor()")]
    [KeptTypeInAssembly("library.dll", typeof(ProxyTarget1))]

    [KeptAttributeInAssembly("library.dll", typeof(TypeMapAttribute<UsedTypeMapUniverse>))]
    [KeptAttributeInAssembly("library.dll", typeof(TypeMapAssociationAttribute<UsedTypeMapUniverse>))]
    [KeptAttributeInAssembly("library.dll", typeof(TypeMapAssemblyTargetAttribute<UsedTypeMapUniverse>))]
    [RemovedAttributeInAssembly("library.dll", typeof(TypeMapAttribute<UnusedTypeMapUniverse>))]

Review comment (suggestion):
Is anything here exercising the negative case (where we validate that TypeMap<T> attributes in "library" which aren't targeted by TypeMapAssemblyTarget<T>("library") are removed?)

Code after:
[assembly: TypeMap<UsedProxyTypeMap>("UsedOnlyForExternalTypeMap", typeof(UsedExternalTarget2), typeof(UsedTrimTarget2))] // Removed
[assembly: TypeMapAssociation<UsedProxyTypeMap>(typeof(UsedProxySource2), typeof(UsedProxyTarget2))] // Kept

[assembly: TypeMapAssociation<UsedTypeMap>(typeof(SourceClass), typeof(ProxyType))]
[assembly: TypeMapAssociation<UsedTypeMap>(typeof(TypeCheckOnlyClass), typeof(TypeCheckOnlyProxy))]
[assembly: TypeMapAssociation<UsedTypeMap>(typeof(AllocatedNoBoxStructType), typeof(AllocatedNoBoxProxy))]
[assembly: TypeMapAssociation<UsedTypeMap>(typeof(I), typeof(IImpl))]
[assembly: TypeMapAssociation<UsedTypeMap>(typeof(IInterfaceWithDynamicImpl), typeof(IDynamicImpl))]
[assembly: TypeMapAssociation<UsedTypeMap>(typeof(ArrayElement), typeof(ArrayElementProxy))]

[assembly: TypeMap<UnusedTypeMap>("UnusedName", typeof(UnusedTargetType), typeof(TrimTarget))]
[assembly: TypeMapAssociation<UsedTypeMap>(typeof(UnusedSourceClass), typeof(UnusedProxyType))]
[assembly: TypeMap<UsedTypeMap>("ClassWithStaticMethod", typeof(TargetType4), typeof(ClassWithStaticMethod))]
[assembly: TypeMap<UsedTypeMap>("ClassWithStaticMethodAndField", typeof(TargetType5), typeof(ClassWithStaticMethodAndField))]

[assembly: TypeMap<UsedWithoutAssemblyTargetUniverse>("UnimportantString", typeof(PreservedTargetType))]

[assembly: KeptAttributeAttribute(typeof(TypeMapAssemblyTargetAttribute<UsedTypeMap>))]
[assembly: TypeMapAssemblyTarget<UsedTypeMap>("library")]
// TypeMapAssemblyTarget is kept regardless of which type map the program needs (External or Proxy)
[assembly: KeptAttributeAttribute(typeof(TypeMapAssemblyTargetAttribute<UsedProxyTypeMap>))]
[assembly: KeptAttributeAttribute(typeof(TypeMapAssemblyTargetAttribute<UsedExternalTypeMap>))]
[assembly: KeptAttributeAttribute(typeof(TypeMapAssemblyTargetAttribute<UsedTypeMapUniverse>))]
[assembly: TypeMapAssemblyTarget<UsedProxyTypeMap>("library")]
[assembly: TypeMapAssemblyTarget<UsedExternalTypeMap>("library")]
[assembly: TypeMapAssemblyTarget<UsedTypeMapUniverse>("library")]
[assembly: TypeMapAssemblyTarget<UnusedTypeMap2>("library")] // Should be removed

namespace Mono.Linker.Tests.Cases.Reflection
{
    [SetupLinkerAction("link", "System.Private.CoreLib")] // Needed to get the RemoveAttributeInstances in embedded xml
    [SetupLinkerArgument("--ignore-link-attributes", "false")]
    [SetupCompileArgument("/unsafe")]
    [SetupCompileBefore("library.dll", new[] { "Dependencies/TypeMapReferencedAssembly.cs" })]
    [SetupCompileBefore("library2.dll", new[] { "Dependencies/TypeMapSecondOrderReference.cs" })]
    [Kept]
    [KeptAssembly("library.dll")]
    [KeptAssembly("library2.dll")]
    [KeptTypeInAssembly("library.dll", typeof(TypeMapReferencedAssembly))]
    [KeptMemberInAssembly("library.dll", typeof(TypeMapReferencedAssembly), "Run()")]
    [KeptTypeInAssembly("library.dll", typeof(TargetTypeUnconditional1), Tool = Tool.Trimmer)]
    [KeptTypeInAssembly("library.dll", typeof(TrimTarget1))]
    [KeptMemberInAssembly("library.dll", typeof(TrimTarget1), ".ctor()")]
    [KeptTypeInAssembly("library.dll", typeof(TrimTarget2))]
    [KeptMemberInAssembly("library.dll", typeof(TrimTarget2), ".ctor()")]
    [KeptTypeInAssembly("library.dll", typeof(TargetTypeConditional1), Tool = Tool.Trimmer)]
    [KeptTypeInAssembly("library.dll", typeof(ProxySource1))]
    [KeptMemberInAssembly("library.dll", typeof(ProxySource1), ".ctor()")]
    [KeptTypeInAssembly("library.dll", typeof(ProxyTarget1))]

    // For correctness, NativeAOT only preserves type map entries in a given assembly when the type map is referenced