File: src\RoslynAnalyzers\Utilities\Compiler\Lightup\IFunctionPointerInvocationOperationWrapper.cs
Web Access
Project: src\src\RoslynAnalyzers\Microsoft.CodeAnalysis.ResxSourceGenerator\Microsoft.CodeAnalysis.ResxSourceGenerator\Microsoft.CodeAnalysis.ResxSourceGenerator.csproj (Microsoft.CodeAnalysis.ResxSourceGenerator)
// 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.
 
#if HAS_IOPERATION
 
namespace Analyzer.Utilities.Lightup
{
    using System;
    using System.Collections.Immutable;
    using System.Diagnostics.CodeAnalysis;
    using System.Linq.Expressions;
    using System.Reflection;
    using Microsoft.CodeAnalysis;
    using Microsoft.CodeAnalysis.Operations;
 
    [SuppressMessage("Performance", "CA1815:Override equals and operator equals on value types", Justification = "Not a comparable instance.")]
    internal readonly struct IFunctionPointerInvocationOperationWrapper : IOperationWrapper
    {
        internal const string WrappedTypeName = "Microsoft.CodeAnalysis.Operations.IFunctionPointerInvocationOperation";
        private static readonly Type? WrappedType = OperationWrapperHelper.GetWrappedType(typeof(IFunctionPointerInvocationOperationWrapper));
 
        private static readonly Func<IOperation, ImmutableArray<IArgumentOperation>> ArgumentsAccessor = LightupHelpers.CreateOperationPropertyAccessor<IOperation, ImmutableArray<IArgumentOperation>>(WrappedType, nameof(Arguments), fallbackResult: ImmutableArray<IArgumentOperation>.Empty);
        private static readonly Func<IOperation, IOperation> TargetAccessor = LightupHelpers.CreateOperationPropertyAccessor<IOperation, IOperation>(WrappedType, nameof(Target), fallbackResult: null!);
 
        private static readonly Func<IOperation, IMethodSymbol> GetFunctionPointerSignatureAccessor = CreateFunctionPointerSignatureAccessor(WrappedType);
 
        private static Func<IOperation, IMethodSymbol> CreateFunctionPointerSignatureAccessor(Type? wrappedType)
        {
            if (wrappedType == null)
            {
                return op => null!;
            }
 
            var targetMethod = typeof(OperationExtensions).GetTypeInfo().GetDeclaredMethod("GetFunctionPointerSignature");
 
            if (targetMethod is null)
            {
                return op => null!;
            }
 
            var operation = Expression.Variable(typeof(IOperation));
 
            return Expression.Lambda<Func<IOperation, IMethodSymbol>>(Expression.Call(targetMethod, Expression.Convert(operation, wrappedType)), operation).Compile();
        }
 
        private IFunctionPointerInvocationOperationWrapper(IOperation operation)
        {
            WrappedOperation = operation;
        }
 
        public IOperation WrappedOperation { get; }
        public ITypeSymbol? Type => WrappedOperation.Type;
        public ImmutableArray<IArgumentOperation> Arguments => ArgumentsAccessor(WrappedOperation);
        public IOperation Target => TargetAccessor(WrappedOperation);
 
        public IMethodSymbol GetFunctionPointerSignature() => GetFunctionPointerSignatureAccessor(WrappedOperation);
 
        public static IFunctionPointerInvocationOperationWrapper FromOperation(IOperation operation)
        {
            if (operation == null)
            {
                return default;
            }
 
            if (!IsInstance(operation))
            {
                throw new InvalidCastException($"Cannot cast '{operation.GetType().FullName}' to '{WrappedTypeName}'");
            }
 
            return new IFunctionPointerInvocationOperationWrapper(operation);
        }
 
        public static bool IsInstance(IOperation operation)
        {
            return operation != null && LightupHelpers.CanWrapOperation(operation, WrappedType);
        }
    }
}
 
#endif