// 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.Collections.Immutable; using System.Reflection.Metadata; namespace Microsoft.CodeAnalysis; internal partial struct SymbolKey { private sealed class FunctionPointerTypeSymbolKey : AbstractSymbolKey<IFunctionPointerTypeSymbol> { public static readonly FunctionPointerTypeSymbolKey Instance = new(); public sealed override void Create(IFunctionPointerTypeSymbol symbol, SymbolKeyWriter visitor) { var callingConvention = symbol.Signature.CallingConvention; visitor.WriteInteger((int)callingConvention); if (callingConvention == SignatureCallingConvention.Unmanaged) { visitor.WriteSymbolKeyArray(symbol.Signature.UnmanagedCallingConventionTypes); } visitor.WriteRefKind(symbol.Signature.RefKind); visitor.WriteSymbolKey(symbol.Signature.ReturnType); visitor.WriteRefKindArray(symbol.Signature.Parameters); visitor.WriteParameterTypesArray(symbol.Signature.Parameters); } protected sealed override SymbolKeyResolution Resolve( SymbolKeyReader reader, IFunctionPointerTypeSymbol? contextualSymbol, out string? failureReason) { var callingConvention = (SignatureCallingConvention)reader.ReadInteger(); var callingConventionModifiers = ImmutableArray<INamedTypeSymbol>.Empty; if (callingConvention == SignatureCallingConvention.Unmanaged) { using var modifiersBuilder = reader.ReadSymbolKeyArray<IFunctionPointerTypeSymbol, INamedTypeSymbol>( contextualSymbol, static (contextualSymbol, i) => SafeGet(contextualSymbol.Signature.UnmanagedCallingConventionTypes, i), out var conventionTypesFailureReason); if (conventionTypesFailureReason != null) { failureReason = $"({nameof(FunctionPointerTypeSymbolKey)} {nameof(callingConventionModifiers)} failed -> {conventionTypesFailureReason})"; return default; } callingConventionModifiers = modifiersBuilder.ToImmutable(); } var returnRefKind = reader.ReadRefKind(); var returnType = reader.ReadSymbolKey(contextualSymbol?.Signature.ReturnType, out var returnTypeFailureReason); using var paramRefKinds = reader.ReadRefKindArray(); using var parameterTypes = reader.ReadSymbolKeyArray<IFunctionPointerTypeSymbol, ITypeSymbol>( contextualSymbol, static (contextualSymbol, i) => SafeGet(contextualSymbol.Signature.Parameters, i)?.Type, out var parameterTypesFailureReason); if (returnTypeFailureReason != null) { failureReason = $"({nameof(FunctionPointerTypeSymbolKey)} {nameof(returnType)} failed -> {returnTypeFailureReason})"; return default; } if (parameterTypesFailureReason != null) { Contract.ThrowIfFalse(parameterTypes.IsDefault); failureReason = $"({nameof(FunctionPointerTypeSymbolKey)} {nameof(parameterTypes)} failed -> {parameterTypesFailureReason})"; return default; } Contract.ThrowIfTrue(parameterTypes.IsDefault); if (returnType.GetAnySymbol() is not ITypeSymbol returnTypeSymbol) { failureReason = $"({nameof(FunctionPointerTypeSymbolKey)} no return type)"; return default; } if (reader.Compilation.Language == LanguageNames.VisualBasic) { failureReason = $"({nameof(FunctionPointerTypeSymbolKey)} is not supported in {LanguageNames.VisualBasic})"; return default; } failureReason = null; return new SymbolKeyResolution(reader.Compilation.CreateFunctionPointerTypeSymbol( returnTypeSymbol, returnRefKind, parameterTypes.ToImmutable(), paramRefKinds.ToImmutable(), callingConvention, callingConventionModifiers)); } } } |