From 0c67caf54b16e5a9ebfac6dda3f60369190d2671 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Wed, 30 Oct 2024 19:13:41 -0700 Subject: [PATCH] Add ref/out keywords on arguments for shadow methods in GeneratedComInterface (#109382) --- .../ComInterfaceGenerator/ComMethodContext.cs | 7 ++++- .../Marshalling/MarshallerHelpers.cs | 2 +- .../CodeSnippets.cs | 30 +++++++++++++++++++ .../Compiles.cs | 4 +++ 4 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComMethodContext.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComMethodContext.cs index e85905a0ee7f7..42d0bb3691ead 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComMethodContext.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComMethodContext.cs @@ -141,8 +141,13 @@ private MethodDeclarationSyntax GenerateShadow() CastExpression(OriginalDeclaringInterface.Info.Type.Syntax, IdentifierName("this"))), IdentifierName(MethodInfo.MethodName)), ArgumentList( - SeparatedList(GenerationContext.SignatureContext.ManagedParameters.Select(p => Argument(IdentifierName(p.InstanceIdentifier)))))))) + SeparatedList(GenerationContext.SignatureContext.ManagedParameters.Select(GenerateArgument)))))) .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)); + + static ArgumentSyntax GenerateArgument(TypePositionInfo info) + => info.IsByRef + ? Argument(IdentifierName(info.InstanceIdentifier)).WithRefKindKeyword(MarshallerHelpers.GetManagedArgumentRefKindKeyword(info)) + : Argument(IdentifierName(info.InstanceIdentifier)); } /// diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallerHelpers.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallerHelpers.cs index 7c7e4b5c609dd..d37849547d1a2 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallerHelpers.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallerHelpers.cs @@ -458,7 +458,7 @@ public static SyntaxToken GetManagedArgumentRefKindKeyword(TypePositionInfo type RefKind.In => Token(SyntaxKind.InKeyword), RefKind.Ref => Token(SyntaxKind.RefKeyword), RefKind.Out => Token(SyntaxKind.OutKeyword), - RefKind.RefReadOnlyParameter => Token(SyntaxKind.RefKeyword), + RefKind.RefReadOnlyParameter => Token(SyntaxKind.InKeyword), _ => throw new NotImplementedException($"Support for some RefKind: {typeInfo.RefKind}") }; } diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CodeSnippets.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CodeSnippets.cs index 933de5f86f6b1..e349b85798572 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CodeSnippets.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CodeSnippets.cs @@ -671,6 +671,36 @@ interface IOtherInterface } """; + public string ForwarderWithPreserveSigAndRefKind(string refKind) => $$""" + using System; + using System.Runtime.CompilerServices; + using System.Runtime.InteropServices; + using System.Runtime.InteropServices.Marshalling; + + #nullable enable + + [assembly:DisableRuntimeMarshalling] + + {{GeneratedComInterface()}} + partial interface IValue + { + } + + {{GeneratedComInterface()}} + partial interface INativeAPIBase + { + [PreserveSig] + int FindValue(int key, {{refKind}} IValue? value); + } + + {{GeneratedComInterface()}} + unsafe partial interface INativeDerived : INativeAPIBase + { + [PreserveSig] + int GetName(out char* name); + } + """; + public class ManagedToUnmanaged : IVirtualMethodIndexSignatureProvider { public MarshalDirection Direction => MarshalDirection.ManagedToUnmanaged; diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/Compiles.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/Compiles.cs index 1522ab3478ac6..3f5a90d3c1a2c 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/Compiles.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/Compiles.cs @@ -341,6 +341,10 @@ public static IEnumerable ComInterfaceSnippetsToCompile() yield return new object[] { ID(), codeSnippets.DerivedComInterfaceTypeTwoLevelShadows}; yield return new object[] { ID(), codeSnippets.DerivedWithParametersDeclaredInOtherNamespace }; yield return new object[] { ID(), codeSnippets.ComInterfaceParameters }; + yield return new object[] { ID(), codeSnippets.ForwarderWithPreserveSigAndRefKind("ref") }; + yield return new object[] { ID(), codeSnippets.ForwarderWithPreserveSigAndRefKind("ref readonly") }; + yield return new object[] { ID(), codeSnippets.ForwarderWithPreserveSigAndRefKind("in") }; + yield return new object[] { ID(), codeSnippets.ForwarderWithPreserveSigAndRefKind("out") }; } public static IEnumerable ManagedToUnmanagedComInterfaceSnippetsToCompile()