| File: Linker\DynamicDependency.cs | Web Access |
| Project: src\runtime\src\tools\illink\src\linker\Mono.Linker.csproj (illink) |
// Copyright (c) .NET Foundation and contributors. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; using System.Diagnostics.CodeAnalysis; using ILLink.Shared; using Mono.Cecil; namespace Mono.Linker { /// Tracks dependencies created via DynamicDependencyAttribute in trimming. /// This is almost identical to DynamicDependencyAttribute, but it holds a /// TypeReference instead of a Type, and it has a reference to the original /// CustomAttribute for dependency tracing. It is also a place for helper /// methods related to the attribute. [System.AttributeUsage(System.AttributeTargets.Constructor | System.AttributeTargets.Field | System.AttributeTargets.Method, AllowMultiple = true, Inherited = false)] internal sealed class DynamicDependency : Attribute { public CustomAttribute? OriginalAttribute { get; private set; } public DynamicDependency(string memberSignature) { MemberSignature = memberSignature; } public DynamicDependency(string memberSignature, TypeReference type) { MemberSignature = memberSignature; Type = type; } public DynamicDependency(string memberSignature, string typeName, string assemblyName) { MemberSignature = memberSignature; TypeName = typeName; AssemblyName = assemblyName; } public DynamicDependency(DynamicallyAccessedMemberTypes memberTypes, TypeReference type) { MemberTypes = memberTypes; Type = type; } public DynamicDependency(DynamicallyAccessedMemberTypes memberTypes, string typeName, string assemblyName) { MemberTypes = memberTypes; TypeName = typeName; AssemblyName = assemblyName; } public string? MemberSignature { get; } public DynamicallyAccessedMemberTypes MemberTypes { get; } public TypeReference? Type { get; } public string? TypeName { get; } public string? AssemblyName { get; } public string? Condition { get; set; } public static DynamicDependency? ProcessAttribute(LinkContext context, ICustomAttributeProvider provider, CustomAttribute customAttribute) { if (!(provider is IMemberDefinition member)) return null; if (!(member is MethodDefinition || member is FieldDefinition)) return null; // Don't honor the Condition until we have figured out the behavior for DynamicDependencyAttribute: // https://github.com/dotnet/linker/issues/1231 // if (!ShouldProcess(context, customAttribute)) // return null; var dynamicDependency = GetDynamicDependency(customAttribute); if (dynamicDependency != null) return dynamicDependency; context.LogWarning(member, DiagnosticId.DynamicDependencyAttributeCouldNotBeAnalyzed); return null; } static DynamicDependency? GetDynamicDependency(CustomAttribute ca) { var args = ca.ConstructorArguments; if (args.Count < 1 || args.Count > 3) return null; DynamicDependency? result = args[0].Value switch { string stringMemberSignature => args.Count switch { 1 => new DynamicDependency(stringMemberSignature), 2 when args[1].Value is TypeReference type => new DynamicDependency(stringMemberSignature, type), 3 when args[1].Value is string typeName && args[2].Value is string assemblyName => new DynamicDependency(stringMemberSignature, typeName, assemblyName), _ => null, }, int memberTypes => args.Count switch { 2 when args[1].Value is TypeReference type => new DynamicDependency((DynamicallyAccessedMemberTypes)memberTypes, type), 3 when args[1].Value is string typeName && args[2].Value is string assemblyName => new DynamicDependency((DynamicallyAccessedMemberTypes)memberTypes, typeName, assemblyName), _ => null, }, _ => null, }; result?.OriginalAttribute = ca; return result; } public static bool ShouldProcess(LinkContext context, CustomAttribute ca) { if (ca.HasProperties && ca.Properties[0].Name == "Condition") { var condition = ca.Properties[0].Argument.Value as string; switch (condition) { case "": case null: return true; case "DEBUG": if (!context.KeepMembersForDebugger) return false; break; default: // Don't have yet a way to match the general condition so everything is excluded return false; } } return true; } } }