File: Marshalling\BreakingChangeDetector.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;
using System.Collections.Generic;
using System.Text;
using Microsoft.CodeAnalysis;
 
namespace Microsoft.Interop
{
    /// <summary>
    /// An <see cref="IMarshallingGeneratorResolver"/> that adds diagnostics to warn users about breaking changes in the interop generators,
    /// whether from built-in to source-generated interop or between versions of interop source-generation.
    /// </summary>
    public sealed class BreakingChangeDetector(IMarshallingGeneratorResolver inner) : IMarshallingGeneratorResolver
    {
        public ResolvedGenerator Create(TypePositionInfo info, StubCodeContext context)
        {
            ResolvedGenerator gen = inner.Create(info, context);
            if (!gen.IsResolvedWithoutErrors)
            {
                return gen;
            }
 
            // Breaking change: [MarshalAs(UnmanagedType.Struct)] in object in unmanaged-to-managed scenarios will not respect VT_BYREF.
            if (info is { RefKind: RefKind.In or RefKind.RefReadOnlyParameter, MarshallingAttributeInfo: NativeMarshallingAttributeInfo(ManagedTypeInfo { DiagnosticFormattedName: TypeNames.ComVariantMarshaller }, _) }
                && context.Direction == MarshalDirection.UnmanagedToManaged)
            {
                gen = ResolvedGenerator.ResolvedWithDiagnostics(
                    gen.Generator,
                    gen.Diagnostics.Add(
                        new GeneratorDiagnostic.NotRecommended(info)
                        {
                            Details = SR.InVariantShouldBeRef
                        }));
            }
 
            return gen;
        }
    }
}