File: src\Workspaces\SharedUtilitiesAndExtensions\Compiler\Core\SymbolKey\SymbolKey.BuiltinOperatorSymbolKey.cs
Web Access
Project: src\src\Workspaces\Core\Portable\Microsoft.CodeAnalysis.Workspaces.csproj (Microsoft.CodeAnalysis.Workspaces)
// 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.
 
using System;
using System.Diagnostics;
using Roslyn.Utilities;
 
namespace Microsoft.CodeAnalysis;
 
internal partial struct SymbolKey
{
    private sealed class BuiltinOperatorSymbolKey : AbstractSymbolKey<IMethodSymbol>
    {
        public static readonly BuiltinOperatorSymbolKey Instance = new();
 
        public sealed override void Create(IMethodSymbol symbol, SymbolKeyWriter visitor)
        {
            visitor.WriteString(symbol.Name);
            visitor.WriteSymbolKey(symbol.ReturnType);
            visitor.WriteParameterTypesArray(symbol.Parameters);
        }
 
        protected sealed override SymbolKeyResolution Resolve(
            SymbolKeyReader reader, IMethodSymbol? contextualSymbol, out string? failureReason)
        {
            var name = reader.ReadRequiredString();
 
            var returnType = reader.ReadSymbolKey(contextualSymbol?.ReturnType, out var returnTypeFailureReason);
            using var parameterTypes = reader.ReadSymbolKeyArray<IMethodSymbol, ITypeSymbol>(
                contextualSymbol,
                static (contextualSymbol, i) => SafeGet(contextualSymbol.Parameters, i)?.Type,
                out var parameterTypesFailureReason);
 
            if (returnTypeFailureReason != null)
            {
                failureReason = $"({nameof(BuiltinOperatorSymbolKey)} {nameof(returnType)} failed -> {returnTypeFailureReason})";
                return default;
            }
 
            if (parameterTypesFailureReason != null)
            {
                failureReason = $"({nameof(BuiltinOperatorSymbolKey)} {nameof(parameterTypes)} failed -> {parameterTypesFailureReason})";
                return default;
            }
 
            var returnTypeSymbol = (ITypeSymbol?)returnType.GetAnySymbol();
            Contract.ThrowIfNull(returnTypeSymbol);
 
            try
            {
                switch (parameterTypes.Count)
                {
                    case 1:
                        failureReason = null;
                        var unaryOperator = reader.Compilation.CreateBuiltinOperator(name, returnTypeSymbol, parameterTypes[0]);
                        return new SymbolKeyResolution(unaryOperator);
                    case 2:
                        failureReason = null;
                        var binaryOperator = reader.Compilation.CreateBuiltinOperator(name, returnTypeSymbol, parameterTypes[0], parameterTypes[1]);
                        return new SymbolKeyResolution(binaryOperator);
 
                    default:
                        failureReason = $"({nameof(BuiltinOperatorSymbolKey)} {nameof(parameterTypes)} failed -> count was {parameterTypes.Count})";
                        return default;
                }
            }
            catch (ArgumentException ex)
            {
                failureReason = $"({nameof(BuiltinOperatorSymbolKey)} failed -> {ex.Message})";
                return default;
            }
        }
    }
}