| File: Linker\CustomAttributeSource.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.Collections.Generic; using System.Diagnostics.CodeAnalysis; using Mono.Cecil; namespace Mono.Linker { public class CustomAttributeSource { public AttributeInfo PrimaryAttributeInfo { get; } private readonly Dictionary<AssemblyDefinition, AttributeInfo?> _embeddedXmlInfos; readonly LinkContext _context; public CustomAttributeSource(LinkContext context) { PrimaryAttributeInfo = new AttributeInfo(); _embeddedXmlInfos = new Dictionary<AssemblyDefinition, AttributeInfo?>(); _context = context; } public static AssemblyDefinition GetAssemblyFromCustomAttributeProvider(ICustomAttributeProvider provider) { return provider switch { MemberReference mr => mr.Module.Assembly, AssemblyDefinition ad => ad, ModuleDefinition md => md.Assembly, InterfaceImplementation ii => ii.InterfaceType.Module.Assembly, GenericParameterConstraint gpc => gpc.ConstraintType.Module.Assembly, ParameterDefinition pd => pd.ParameterType.Module.Assembly, MethodReturnType mrt => mrt.ReturnType.Module.Assembly, _ => throw new NotImplementedException(provider.GetType().ToString()), }; } public bool TryGetEmbeddedXmlInfo(ICustomAttributeProvider provider, [NotNullWhen(true)] out AttributeInfo? xmlInfo) { AssemblyDefinition assembly = GetAssemblyFromCustomAttributeProvider(provider); if (!_embeddedXmlInfos.TryGetValue(assembly, out xmlInfo)) { // Add an empty record - this prevents reentrancy // If the embedded XML itself generates warnings, trying to log such warning // may ask for attributes (suppressions) and thus we could end up in this very place again // So first add a dummy record and once processed we will replace it with the real data _embeddedXmlInfos.Add(assembly, new AttributeInfo()); xmlInfo = _context.EmbeddedXmlInfo.ProcessAttributes(assembly, _context); _embeddedXmlInfos[assembly] = xmlInfo; } return xmlInfo != null; } public IEnumerable<CustomAttribute> GetCustomAttributes(ICustomAttributeProvider provider, string attributeNamespace, string attributeName) { foreach (var attr in GetCustomAttributes(provider)) { if (attr.AttributeType.Namespace == attributeNamespace && attr.AttributeType.Name == attributeName) yield return attr; } } public IEnumerable<CustomAttribute> GetCustomAttributes(ICustomAttributeProvider provider) { if (provider.HasCustomAttributes) { foreach (var customAttribute in provider.CustomAttributes) yield return customAttribute; } if (PrimaryAttributeInfo.CustomAttributes.TryGetValue(provider, out var annotations)) { foreach (var customAttribute in annotations) yield return customAttribute; } if (!TryGetEmbeddedXmlInfo(provider, out var embeddedXml)) yield break; if (embeddedXml.CustomAttributes.TryGetValue(provider, out annotations)) { foreach (var customAttribute in annotations) yield return customAttribute; } } public bool TryGetCustomAttributeOrigin(ICustomAttributeProvider provider, CustomAttribute customAttribute, out MessageOrigin origin) { if (PrimaryAttributeInfo.CustomAttributesOrigins.TryGetValue(customAttribute, out origin)) return true; if (!TryGetEmbeddedXmlInfo(provider, out var embeddedXml)) return false; return embeddedXml.CustomAttributesOrigins.TryGetValue(customAttribute, out origin); } public bool HasAny(ICustomAttributeProvider provider) { if (provider.HasCustomAttributes) return true; if (PrimaryAttributeInfo.CustomAttributes.ContainsKey(provider)) return true; if (!TryGetEmbeddedXmlInfo(provider, out var embeddedXml)) return false; return embeddedXml.CustomAttributes.ContainsKey(provider); } } }