File: RequiresUnreferencedCodeUtils.cs
Web Access
Project: src\src\tools\illink\src\ILLink.RoslynAnalyzer\ILLink.RoslynAnalyzer.csproj (ILLink.RoslynAnalyzer)
// 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.Diagnostics.CodeAnalysis;
using ILLink.Shared;
using Microsoft.CodeAnalysis;
 
namespace ILLink.RoslynAnalyzer
{
    public static class RequiresUnreferencedCodeUtils
    {
        private const string RequiresUnreferencedCodeAttribute = nameof(RequiresUnreferencedCodeAttribute);
 
        public static bool TryGetRequiresUnreferencedCodeAttribute(this ISymbol member, [NotNullWhen(returnValue: true)] out AttributeData? requiresAttributeData) =>
            member.DoesMemberRequireUnreferencedCodeAttribute(out requiresAttributeData) && VerifyRequiresUnreferencedCodeAttributeArguments(requiresAttributeData);
 
        // TODO: Consider sharing with ILLink DoesMethodRequireUnreferencedCode method
        /// <summary>
        /// True if the target of a call is considered to be annotated with the RequiresUnreferencedCode attribute
        /// </summary>
        public static bool DoesMemberRequireUnreferencedCodeAttribute(this ISymbol member, [NotNullWhen(returnValue: true)] out AttributeData? requiresAttributeData)
            => member.DoesMemberRequire(RequiresUnreferencedCodeAttribute, out requiresAttributeData);
 
        // TODO: Consider sharing with ILLink IsMethodInRequiresUnreferencedCodeScope method
        /// <summary>
        /// True if the source of a call is considered to be annotated with the RequiresUnreferencedCode attribute
        /// </summary>
        public static bool IsInRequiresUnreferencedCodeAttributeScope(this ISymbol member, [NotNullWhen(true)] out AttributeData? requiresAttribute)
            => member.IsInRequiresScope(RequiresUnreferencedCodeAttribute, out requiresAttribute);
 
        /// <summary>
        /// This method verifies that the arguments in an attribute have certain structure.
        /// </summary>
        /// <param name="attribute">Attribute data to compare.</param>
        /// <returns>True if the validation was successfull; otherwise, returns false.</returns>
        public static bool VerifyRequiresUnreferencedCodeAttributeArguments(AttributeData attribute)
            => attribute.ConstructorArguments.Length >= 1 && attribute.ConstructorArguments is [{ Type.SpecialType: SpecialType.System_String }, ..];
 
        public static string GetMessageFromAttribute(AttributeData? requiresAttribute)
        {
            var message = (string)requiresAttribute!.ConstructorArguments[0].Value!;
            return MessageFormat.FormatRequiresAttributeMessageArg(message);
        }
    }
}