File: Marshalling\ByValueContentsMarshalKindValidator.cs
Web Access
Project: src\src\libraries\System.Runtime.InteropServices\gen\Microsoft.Interop.SourceGeneration\Microsoft.Interop.SourceGeneration.csproj (Microsoft.Interop.SourceGeneration)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Diagnostics;
 
namespace Microsoft.Interop
{
    /// <summary>
    /// An <see cref="IMarshallingGeneratorResolver"/> implementation that wraps an inner <see cref="IMarshallingGeneratorResolver"/> instance and validates that the <see cref="TypePositionInfo.ByValueContentsMarshalKind"/> on the provided <see cref="TypePositionInfo"/> is valid in the current marshalling scenario.
    /// </summary>
    public sealed class ByValueContentsMarshalKindValidator : IMarshallingGeneratorResolver
    {
        private static readonly Forwarder s_forwarder = new();
 
        private readonly IMarshallingGeneratorResolver _inner;
 
        public ByValueContentsMarshalKindValidator(IMarshallingGeneratorResolver inner)
        {
            _inner = inner;
        }
 
        public ResolvedGenerator Create(TypePositionInfo info, StubCodeContext context)
        {
            ResolvedGenerator generator = _inner.Create(info, context);
            return generator.IsResolvedWithoutErrors ? ValidateByValueMarshalKind(generator, context) : generator;
        }
 
        private static ResolvedGenerator ValidateByValueMarshalKind(ResolvedGenerator generator, StubCodeContext context)
        {
            if (generator.Generator.IsForwarder())
            {
                // Forwarder allows everything since it just forwards to a P/Invoke.
                // The Default marshal kind is always valid.
                return generator;
            }
 
            var support = generator.Generator.SupportsByValueMarshalKind(generator.Generator.TypeInfo.ByValueContentsMarshalKind, out GeneratorDiagnostic? diagnostic);
            Debug.Assert(support == ByValueMarshalKindSupport.Supported || diagnostic is not null);
            return support switch
            {
                ByValueMarshalKindSupport.Supported => generator,
                ByValueMarshalKindSupport.NotSupported => ResolvedGenerator.ResolvedWithDiagnostics(s_forwarder.Bind(generator.Generator.TypeInfo, context), generator.Diagnostics.Add(diagnostic!)),
                ByValueMarshalKindSupport.Unnecessary => generator with { Diagnostics = generator.Diagnostics.Add(diagnostic!) },
                ByValueMarshalKindSupport.NotRecommended => generator with { Diagnostics = generator.Diagnostics.Add(diagnostic!) },
                _ => throw new UnreachableException()
            };
        }
    }
}