| File: VariableDeclarations.cs | Web Access |
| Project: 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 Microsoft.CodeAnalysis; namespace Microsoft.Interop { public readonly record struct VariableDeclarations(string Initializations, string Variables) { public static VariableDeclarations GenerateDeclarationsForManagedToUnmanaged(BoundGenerators marshallers, StubIdentifierContext context, bool initializeDeclarations) { var initializations = new IndentedTextWriter(); var variables = new IndentedTextWriter(); foreach (IBoundMarshallingGenerator marshaller in marshallers.NativeParameterMarshallers) { TypePositionInfo info = marshaller.TypeInfo; if (info.IsManagedReturnPosition) continue; if (info.RefKind == RefKind.Out && !info.IsErrorHandlingPosition) { initializations.WriteLine(MarshallerHelpers.DefaultInit(info, context)); } AppendVariableDeclarations(marshaller); } if (!marshallers.IsManagedVoidReturn) { AppendVariableDeclarations(marshallers.ManagedReturnMarshaller); } if (!marshallers.IsUnmanagedVoidReturn && !marshallers.ManagedNativeSameReturn) { AppendVariableDeclarations(marshallers.NativeReturnMarshaller); } foreach (IBoundMarshallingGenerator errorMarshaller in marshallers.SignatureMarshallers) { TypePositionInfo errorInfo = errorMarshaller.TypeInfo; if (errorInfo is { IsErrorHandlingPosition: true, ManagedIndex: TypePositionInfo.ErrorIndex } && !ReferenceEquals(errorMarshaller, marshallers.NativeReturnMarshaller)) { Declare(variables, errorInfo.ManagedType.FullTypeName, context.GetIdentifiers(errorInfo).managed, initializeDeclarations); } } return new VariableDeclarations(initializations.ToString(), variables.ToString()); void AppendVariableDeclarations(IBoundMarshallingGenerator marshaller) { (string managed, string native) = context.GetIdentifiers(marshaller.TypeInfo); if (marshaller.TypeInfo.IsManagedReturnPosition || marshaller.TypeInfo.IsNativeReturnPosition) { Declare(variables, marshaller.TypeInfo.ManagedType.FullTypeName, managed, initializeDeclarations); } if (marshaller.UsesNativeIdentifier) { Declare(variables, marshaller.NativeType.FullTypeName, native, initializeDeclarations); } } } public static VariableDeclarations GenerateDeclarationsForUnmanagedToManaged(BoundGenerators marshallers, StubIdentifierContext context, bool initializeDeclarations) { var variables = new IndentedTextWriter(); foreach (IBoundMarshallingGenerator marshaller in marshallers.NativeParameterMarshallers) { TypePositionInfo info = marshaller.TypeInfo; if (info.IsNativeReturnPosition || info.IsManagedReturnPosition) continue; AppendVariableDeclarations(marshaller); } if (!marshallers.IsManagedVoidReturn) { AppendVariableDeclarations(marshallers.ManagedReturnMarshaller); } if (!marshallers.IsUnmanagedVoidReturn && !marshallers.ManagedNativeSameReturn) { AppendVariableDeclarations(marshallers.NativeReturnMarshaller); } return new VariableDeclarations("", variables.ToString()); void AppendVariableDeclarations(IBoundMarshallingGenerator marshaller) { (string managed, string native) = context.GetIdentifiers(marshaller.TypeInfo); if (marshaller.TypeInfo.IsNativeReturnPosition) { bool nativeReturnUsesNativeIdentifier = marshaller.UsesNativeIdentifier; Declare(variables, marshaller.TypeInfo.ManagedType.FullTypeName, managed, initializeDeclarations || !nativeReturnUsesNativeIdentifier); if (nativeReturnUsesNativeIdentifier) { Declare(variables, marshaller.NativeType.FullTypeName, native, initializeToDefault: true); } } else { ValueBoundaryBehavior boundaryBehavior = marshaller.ValueBoundaryBehavior; if (marshaller.UsesNativeIdentifier && boundaryBehavior is not (ValueBoundaryBehavior.NativeIdentifier or ValueBoundaryBehavior.CastNativeIdentifier)) { string localType = marshaller.NativeType.FullTypeName; if (boundaryBehavior != ValueBoundaryBehavior.AddressOfNativeIdentifier) { Declare(variables, localType, native, initializeToDefault: false); } else { // Alias the native parameter so unmarshalling also updates the caller's value. variables.WriteLine($"ref {localType} {native} = {marshaller.GenerateNativeByRefInitialization(context)};"); } } // The exception's managed identifier is declared by the catch clause. if (boundaryBehavior != ValueBoundaryBehavior.ManagedIdentifier && !marshaller.TypeInfo.IsErrorHandlingPosition) { Declare(variables, marshaller.TypeInfo.ManagedType.FullTypeName, managed, initializeDeclarations); } } } } private static void Declare(IndentedTextWriter writer, string type, string identifier, bool initializeToDefault) { writer.WriteLine($"{type} {identifier}{(initializeToDefault ? " = default" : "")};"); } } }