From de8d8134f2a0d80e807a266d5316a34b18148c52 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Wed, 13 Apr 2022 16:12:38 -0700 Subject: [PATCH 01/30] WIP for generating stubs for manual vtable entrypoints. --- .../System.Runtime.InteropServices.sln | 20 + .../ComInterfaceGenerator.csproj | 40 ++ .../gen/ComInterfaceGenerator/Comparers.cs | 75 ++++ .../GeneratorDiagnostics.cs | 304 +++++++++++++ .../ComInterfaceGenerator/LanguageSupport.cs | 11 + .../ManagedToNativeVTableMethodGenerator.cs | 263 +++++++++++ ...rosoft.Interop.ComInterfaceGenerator.props | 9 + .../Resources/Strings.resx | 188 ++++++++ .../Resources/xlf/Strings.cs.xlf | 114 +++++ .../Resources/xlf/Strings.de.xlf | 114 +++++ .../Resources/xlf/Strings.es.xlf | 114 +++++ .../Resources/xlf/Strings.fr.xlf | 114 +++++ .../Resources/xlf/Strings.it.xlf | 114 +++++ .../Resources/xlf/Strings.ja.xlf | 114 +++++ .../Resources/xlf/Strings.ko.xlf | 114 +++++ .../Resources/xlf/Strings.pl.xlf | 114 +++++ .../Resources/xlf/Strings.pt-BR.xlf | 114 +++++ .../Resources/xlf/Strings.ru.xlf | 114 +++++ .../Resources/xlf/Strings.tr.xlf | 114 +++++ .../Resources/xlf/Strings.zh-Hans.xlf | 114 +++++ .../Resources/xlf/Strings.zh-Hant.xlf | 114 +++++ .../UnreachableException.cs | 16 + .../VirtualMethodIndexData.cs | 18 + .../VtableIndexStubGenerator.cs | 415 ++++++++++++++++++ .../ManagedTypeInfo.cs | 1 + .../IUnmanagedVirtualMethodTableProvider.cs | 117 +++++ .../VirtualMethodIndexAttribute.cs | 50 +++ 27 files changed, 3009 insertions(+) create mode 100644 src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.csproj create mode 100644 src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Comparers.cs create mode 100644 src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/GeneratorDiagnostics.cs create mode 100644 src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/LanguageSupport.cs create mode 100644 src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedToNativeVTableMethodGenerator.cs create mode 100644 src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Microsoft.Interop.ComInterfaceGenerator.props create mode 100644 src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/Strings.resx create mode 100644 src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.cs.xlf create mode 100644 src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.de.xlf create mode 100644 src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.es.xlf create mode 100644 src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.fr.xlf create mode 100644 src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.it.xlf create mode 100644 src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.ja.xlf create mode 100644 src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.ko.xlf create mode 100644 src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.pl.xlf create mode 100644 src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.pt-BR.xlf create mode 100644 src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.ru.xlf create mode 100644 src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.tr.xlf create mode 100644 src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.zh-Hans.xlf create mode 100644 src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.zh-Hant.xlf create mode 100644 src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/UnreachableException.cs create mode 100644 src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VirtualMethodIndexData.cs create mode 100644 src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs create mode 100644 src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/IUnmanagedVirtualMethodTableProvider.cs create mode 100644 src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/VirtualMethodIndexAttribute.cs diff --git a/src/libraries/System.Runtime.InteropServices/System.Runtime.InteropServices.sln b/src/libraries/System.Runtime.InteropServices/System.Runtime.InteropServices.sln index 0a0c735457a58..fd72e92df6b20 100644 --- a/src/libraries/System.Runtime.InteropServices/System.Runtime.InteropServices.sln +++ b/src/libraries/System.Runtime.InteropServices/System.Runtime.InteropServices.sln @@ -38,6 +38,7 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ref", "ref", "{D893B9AA-57C5-49E3-97B1-12CC62D84307}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "gen", "gen", "{E1AEBD5D-AE4E-4F61-B9ED-AEF950B0CC33}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ComInterfaceGenerator", "gen\ComInterfaceGenerator\ComInterfaceGenerator.csproj", "{C3EA0A28-A597-4946-9E08-EBBBFA94BFA5}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -340,6 +341,24 @@ Global {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|x64.Build.0 = Debug|Any CPU {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|x86.ActiveCfg = Debug|Any CPU {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|x86.Build.0 = Debug|Any CPU + {C3EA0A28-A597-4946-9E08-EBBBFA94BFA5}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {C3EA0A28-A597-4946-9E08-EBBBFA94BFA5}.Checked|Any CPU.Build.0 = Debug|Any CPU + {C3EA0A28-A597-4946-9E08-EBBBFA94BFA5}.Checked|x64.ActiveCfg = Debug|Any CPU + {C3EA0A28-A597-4946-9E08-EBBBFA94BFA5}.Checked|x64.Build.0 = Debug|Any CPU + {C3EA0A28-A597-4946-9E08-EBBBFA94BFA5}.Checked|x86.ActiveCfg = Debug|Any CPU + {C3EA0A28-A597-4946-9E08-EBBBFA94BFA5}.Checked|x86.Build.0 = Debug|Any CPU + {C3EA0A28-A597-4946-9E08-EBBBFA94BFA5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C3EA0A28-A597-4946-9E08-EBBBFA94BFA5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C3EA0A28-A597-4946-9E08-EBBBFA94BFA5}.Debug|x64.ActiveCfg = Debug|Any CPU + {C3EA0A28-A597-4946-9E08-EBBBFA94BFA5}.Debug|x64.Build.0 = Debug|Any CPU + {C3EA0A28-A597-4946-9E08-EBBBFA94BFA5}.Debug|x86.ActiveCfg = Debug|Any CPU + {C3EA0A28-A597-4946-9E08-EBBBFA94BFA5}.Debug|x86.Build.0 = Debug|Any CPU + {C3EA0A28-A597-4946-9E08-EBBBFA94BFA5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C3EA0A28-A597-4946-9E08-EBBBFA94BFA5}.Release|Any CPU.Build.0 = Release|Any CPU + {C3EA0A28-A597-4946-9E08-EBBBFA94BFA5}.Release|x64.ActiveCfg = Release|Any CPU + {C3EA0A28-A597-4946-9E08-EBBBFA94BFA5}.Release|x64.Build.0 = Release|Any CPU + {C3EA0A28-A597-4946-9E08-EBBBFA94BFA5}.Release|x86.ActiveCfg = Release|Any CPU + {C3EA0A28-A597-4946-9E08-EBBBFA94BFA5}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -361,6 +380,7 @@ Global {1B248B4C-7584-4C04-850A-A50EB592052C} = {E1AEBD5D-AE4E-4F61-B9ED-AEF950B0CC33} {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40} = {E1AEBD5D-AE4E-4F61-B9ED-AEF950B0CC33} {768B77B0-EA45-469D-B39E-545EB72F5A43} = {E1AEBD5D-AE4E-4F61-B9ED-AEF950B0CC33} + {C3EA0A28-A597-4946-9E08-EBBBFA94BFA5} = {E1AEBD5D-AE4E-4F61-B9ED-AEF950B0CC33} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {D4031401-FEB5-4CCF-91C1-38F5646B2BFD} diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.csproj b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.csproj new file mode 100644 index 0000000000000..bc4311cae8137 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.csproj @@ -0,0 +1,40 @@ + + + + Microsoft.Interop.ComInterfaceGenerator + netstandard2.0 + true + Preview + enable + Microsoft.Interop + true + true + + RS2008;$(NoWarn) + + + + false + false + true + https://github.com/dotnet/runtime/tree/main/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator + LibraryImportGenerator + LibraryImportGenerator, analyzers + + + + + + + + + + + + + + + + + diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Comparers.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Comparers.cs new file mode 100644 index 0000000000000..6b8bbd838aac5 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Comparers.cs @@ -0,0 +1,75 @@ +// 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; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; + +namespace Microsoft.Interop +{ + internal static class Comparers + { + /// + /// Comparer for an individual generated stub source as a syntax tree and the generated diagnostics for the stub. + /// + public static readonly IEqualityComparer<(MemberDeclarationSyntax Syntax, ImmutableArray Diagnostics)> GeneratedSyntax = new CustomValueTupleElementComparer>(SyntaxEquivalentComparer.Instance, new ImmutableArraySequenceEqualComparer(EqualityComparer.Default)); + + /// + /// Comparer for the context used to generate a stub and the original user-provided syntax that triggered stub creation. + /// + public static readonly IEqualityComparer<(MethodDeclarationSyntax Syntax, VtableIndexStubGenerator.IncrementalStubGenerationContext StubContext)> CalculatedContextWithSyntax = new CustomValueTupleElementComparer(SyntaxEquivalentComparer.Instance, EqualityComparer.Default); + } + + /// + /// Generic comparer to compare two instances element by element. + /// + /// The type of immutable array element. + internal class ImmutableArraySequenceEqualComparer : IEqualityComparer> + { + private readonly IEqualityComparer _elementComparer; + + /// + /// Creates an with a custom comparer for the elements of the collection. + /// + /// The comparer instance for the collection elements. + public ImmutableArraySequenceEqualComparer(IEqualityComparer elementComparer) + { + _elementComparer = elementComparer; + } + + public bool Equals(ImmutableArray x, ImmutableArray y) + { + return x.SequenceEqual(y, _elementComparer); + } + + public int GetHashCode(ImmutableArray obj) + { + throw new UnreachableException(); + } + } + + internal class CustomValueTupleElementComparer : IEqualityComparer<(T, U)> + { + private readonly IEqualityComparer _item1Comparer; + private readonly IEqualityComparer _item2Comparer; + + public CustomValueTupleElementComparer(IEqualityComparer item1Comparer, IEqualityComparer item2Comparer) + { + _item1Comparer = item1Comparer; + _item2Comparer = item2Comparer; + } + + public bool Equals((T, U) x, (T, U) y) + { + return _item1Comparer.Equals(x.Item1, y.Item1) && _item2Comparer.Equals(x.Item2, y.Item2); + } + + public int GetHashCode((T, U) obj) + { + throw new UnreachableException(); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/GeneratorDiagnostics.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/GeneratorDiagnostics.cs new file mode 100644 index 0000000000000..6c8ba6b00f387 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/GeneratorDiagnostics.cs @@ -0,0 +1,304 @@ +// 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; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using System; +using System.Collections.Generic; +using System.Diagnostics; + +namespace Microsoft.Interop +{ + /// + /// Class for reporting diagnostics in the library import generator + /// + public class GeneratorDiagnostics : IGeneratorDiagnostics + { + public class Ids + { + // SYSLIB1050-SYSLIB1059 are reserved for source-generated Interop + public const string Prefix = "SYSLIB"; + public const string InvalidLibraryImportAttributeUsage = Prefix + "1050"; + public const string TypeNotSupported = Prefix + "1051"; + public const string ConfigurationNotSupported = Prefix + "1052"; + } + + private const string Category = "ComInterfaceGenerator"; + + public static readonly DiagnosticDescriptor InvalidAttributedMethodSignature = + new DiagnosticDescriptor( + Ids.InvalidLibraryImportAttributeUsage, + GetResourceString(nameof(SR.InvalidLibraryImportAttributeUsageTitle)), + GetResourceString(nameof(SR.InvalidAttributedMethodSignatureMessage)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(SR.InvalidAttributedMethodDescription))); + + public static readonly DiagnosticDescriptor InvalidAttributedMethodContainingTypeMissingModifiers = + new DiagnosticDescriptor( + Ids.InvalidLibraryImportAttributeUsage, + GetResourceString(nameof(SR.InvalidLibraryImportAttributeUsageTitle)), + GetResourceString(nameof(SR.InvalidAttributedMethodContainingTypeMissingModifiersMessage)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(SR.InvalidAttributedMethodDescription))); + + public static readonly DiagnosticDescriptor InvalidStringMarshallingConfiguration = + new DiagnosticDescriptor( + Ids.InvalidLibraryImportAttributeUsage, + GetResourceString(nameof(SR.InvalidLibraryImportAttributeUsageTitle)), + GetResourceString(nameof(SR.InvalidStringMarshallingConfigurationMessage)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(SR.InvalidStringMarshallingConfigurationDescription))); + + public static readonly DiagnosticDescriptor ParameterTypeNotSupported = + new DiagnosticDescriptor( + Ids.TypeNotSupported, + GetResourceString(nameof(SR.TypeNotSupportedTitle)), + GetResourceString(nameof(SR.TypeNotSupportedMessageParameter)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(SR.TypeNotSupportedDescription))); + + public static readonly DiagnosticDescriptor ReturnTypeNotSupported = + new DiagnosticDescriptor( + Ids.TypeNotSupported, + GetResourceString(nameof(SR.TypeNotSupportedTitle)), + GetResourceString(nameof(SR.TypeNotSupportedMessageReturn)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(SR.TypeNotSupportedDescription))); + + public static readonly DiagnosticDescriptor ParameterTypeNotSupportedWithDetails = + new DiagnosticDescriptor( + Ids.TypeNotSupported, + GetResourceString(nameof(SR.TypeNotSupportedTitle)), + GetResourceString(nameof(SR.TypeNotSupportedMessageParameterWithDetails)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(SR.TypeNotSupportedDescription))); + + public static readonly DiagnosticDescriptor ReturnTypeNotSupportedWithDetails = + new DiagnosticDescriptor( + Ids.TypeNotSupported, + GetResourceString(nameof(SR.TypeNotSupportedTitle)), + GetResourceString(nameof(SR.TypeNotSupportedMessageReturnWithDetails)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(SR.TypeNotSupportedDescription))); + + public static readonly DiagnosticDescriptor ParameterConfigurationNotSupported = + new DiagnosticDescriptor( + Ids.ConfigurationNotSupported, + GetResourceString(nameof(SR.ConfigurationNotSupportedTitle)), + GetResourceString(nameof(SR.ConfigurationNotSupportedMessageParameter)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(SR.ConfigurationNotSupportedDescription))); + + public static readonly DiagnosticDescriptor ReturnConfigurationNotSupported = + new DiagnosticDescriptor( + Ids.ConfigurationNotSupported, + GetResourceString(nameof(SR.ConfigurationNotSupportedTitle)), + GetResourceString(nameof(SR.ConfigurationNotSupportedMessageReturn)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(SR.ConfigurationNotSupportedDescription))); + + public static readonly DiagnosticDescriptor ConfigurationNotSupported = + new DiagnosticDescriptor( + Ids.ConfigurationNotSupported, + GetResourceString(nameof(SR.ConfigurationNotSupportedTitle)), + GetResourceString(nameof(SR.ConfigurationNotSupportedMessage)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(SR.ConfigurationNotSupportedDescription))); + + public static readonly DiagnosticDescriptor ConfigurationValueNotSupported = + new DiagnosticDescriptor( + Ids.ConfigurationNotSupported, + GetResourceString(nameof(SR.ConfigurationNotSupportedTitle)), + GetResourceString(nameof(SR.ConfigurationNotSupportedMessageValue)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(SR.ConfigurationNotSupportedDescription))); + + public static readonly DiagnosticDescriptor MarshallingAttributeConfigurationNotSupported = + new DiagnosticDescriptor( + Ids.ConfigurationNotSupported, + GetResourceString(nameof(SR.ConfigurationNotSupportedTitle)), + GetResourceString(nameof(SR.ConfigurationNotSupportedMessageMarshallingInfo)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(SR.ConfigurationNotSupportedDescription))); + + private readonly List _diagnostics = new List(); + + public IEnumerable Diagnostics => _diagnostics; + + /// + /// Report diagnostic for invalid configuration for string marshalling. + /// + /// Attribute specifying the invalid configuration + /// Name of the method + /// Specific reason the configuration is invalid + public void ReportInvalidStringMarshallingConfiguration( + AttributeData attributeData, + string methodName, + string detailsMessage) + { + _diagnostics.Add( + attributeData.CreateDiagnostic( + GeneratorDiagnostics.InvalidStringMarshallingConfiguration, + methodName, + detailsMessage)); + } + + /// + /// Report diagnostic for configuration that is not supported by the DLL import source generator + /// + /// Attribute specifying the unsupported configuration + /// Name of the configuration + /// [Optiona] Unsupported configuration value + public void ReportConfigurationNotSupported( + AttributeData attributeData, + string configurationName, + string? unsupportedValue = null) + { + if (unsupportedValue == null) + { + _diagnostics.Add( + attributeData.CreateDiagnostic( + GeneratorDiagnostics.ConfigurationNotSupported, + configurationName)); + } + else + { + _diagnostics.Add( + attributeData.CreateDiagnostic( + GeneratorDiagnostics.ConfigurationValueNotSupported, + unsupportedValue, + configurationName)); + } + } + + /// + /// Report diagnostic for marshalling of a parameter/return that is not supported + /// + /// Method with the parameter/return + /// Type info for the parameter/return + /// [Optional] Specific reason for lack of support + public void ReportMarshallingNotSupported( + MethodDeclarationSyntax method, + TypePositionInfo info, + string? notSupportedDetails) + { + Location diagnosticLocation = Location.None; + string elementName = string.Empty; + + if (info.IsManagedReturnPosition) + { + diagnosticLocation = Location.Create(method.SyntaxTree, method.Identifier.Span); + elementName = method.Identifier.ValueText; + } + else + { + Debug.Assert(info.ManagedIndex <= method.ParameterList.Parameters.Count); + ParameterSyntax param = method.ParameterList.Parameters[info.ManagedIndex]; + diagnosticLocation = Location.Create(param.SyntaxTree, param.Identifier.Span); + elementName = param.Identifier.ValueText; + } + + if (!string.IsNullOrEmpty(notSupportedDetails)) + { + // Report the specific not-supported reason. + if (info.IsManagedReturnPosition) + { + _diagnostics.Add( + diagnosticLocation.CreateDiagnostic( + GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails, + notSupportedDetails!, + elementName)); + } + else + { + _diagnostics.Add( + diagnosticLocation.CreateDiagnostic( + GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails, + notSupportedDetails!, + elementName)); + } + } + else if (info.MarshallingAttributeInfo is MarshalAsInfo) + { + // Report that the specified marshalling configuration is not supported. + // We don't forward marshalling attributes, so this is reported differently + // than when there is no attribute and the type itself is not supported. + if (info.IsManagedReturnPosition) + { + _diagnostics.Add( + diagnosticLocation.CreateDiagnostic( + GeneratorDiagnostics.ReturnConfigurationNotSupported, + nameof(System.Runtime.InteropServices.MarshalAsAttribute), + elementName)); + } + else + { + _diagnostics.Add( + diagnosticLocation.CreateDiagnostic( + GeneratorDiagnostics.ParameterConfigurationNotSupported, + nameof(System.Runtime.InteropServices.MarshalAsAttribute), + elementName)); + } + } + else + { + // Report that the type is not supported + if (info.IsManagedReturnPosition) + { + _diagnostics.Add( + diagnosticLocation.CreateDiagnostic( + GeneratorDiagnostics.ReturnTypeNotSupported, + info.ManagedType.DiagnosticFormattedName, + elementName)); + } + else + { + _diagnostics.Add( + diagnosticLocation.CreateDiagnostic( + GeneratorDiagnostics.ParameterTypeNotSupported, + info.ManagedType.DiagnosticFormattedName, + elementName)); + } + } + } + + public void ReportInvalidMarshallingAttributeInfo( + AttributeData attributeData, + string reasonResourceName, + params string[] reasonArgs) + { + _diagnostics.Add( + attributeData.CreateDiagnostic( + GeneratorDiagnostics.MarshallingAttributeConfigurationNotSupported, + new LocalizableResourceString(reasonResourceName, SR.ResourceManager, typeof(FxResources.Microsoft.Interop.ComInterfaceGenerator.SR), reasonArgs))); + } + private static LocalizableResourceString GetResourceString(string resourceName) + { + return new LocalizableResourceString(resourceName, SR.ResourceManager, typeof(FxResources.Microsoft.Interop.ComInterfaceGenerator.SR)); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/LanguageSupport.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/LanguageSupport.cs new file mode 100644 index 0000000000000..0f983ddc28671 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/LanguageSupport.cs @@ -0,0 +1,11 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// Types defined to enable language support of various features +// in the source generator. +namespace System.Runtime.CompilerServices +{ + // Define IsExternalInit type to support records. + internal class IsExternalInit + { } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedToNativeVTableMethodGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedToNativeVTableMethodGenerator.cs new file mode 100644 index 0000000000000..38315777bef2b --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedToNativeVTableMethodGenerator.cs @@ -0,0 +1,263 @@ +// 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.Collections.Immutable; +using System.Diagnostics; +using System.Linq; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; + +namespace Microsoft.Interop +{ + /// + /// Base code generator for generating the body of a source-generated P/Invoke and providing customization for how to invoke/define the native method. + /// + /// + /// This type enables multiple code generators for P/Invoke-style marshalling + /// to reuse the same basic method body, but with different designs of how to emit the target native method. + /// This enables users to write code generators that work with slightly different semantics. + /// For example, the source generator for [LibraryImport] emits the target P/Invoke as + /// a local function inside the generated stub body. + /// However, other managed-to-native code generators using a P/Invoke style might want to define + /// the target DllImport outside of the stub as a static non-local function or as a function pointer field. + /// This refactoring allows the code generator to have control over where the target method is declared + /// and how it is declared. + /// + internal sealed class ManagedToNativeVTableMethodGenerator + { + private const string ReturnIdentifier = "__retVal"; + private const string LastErrorIdentifier = "__lastError"; + private const string InvokeSucceededIdentifier = "__invokeSucceeded"; + private const string NativeThisParameterIdentifier = "__this"; + private const string VirtualMethodTableIdentifier = $"__vtable{StubCodeContext.GeneratedNativeIdentifierSuffix}"; + + // Error code representing success. This maps to S_OK for Windows HRESULT semantics and 0 for POSIX errno semantics. + private const int SuccessErrorCode = 0; + private readonly bool _setLastError; + private readonly bool _implicitThis; + private readonly BoundGenerators _marshallers; + + private readonly ManagedToNativeStubCodeContext _context; + + public ManagedToNativeVTableMethodGenerator( + StubEnvironment environment, + ImmutableArray argTypes, + bool setLastError, + bool implicitThis, + Action marshallingNotSupportedCallback, + IMarshallingGeneratorFactory generatorFactory) + { + _setLastError = setLastError; + _implicitThis = implicitThis; + if (implicitThis) + { + ImmutableArray.Builder newArgTypes = ImmutableArray.CreateBuilder(argTypes.Length + 1); + newArgTypes.Add(new TypePositionInfo(SpecialTypeInfo.IntPtr, NoMarshallingInfo.Instance) + { + InstanceIdentifier = NativeThisParameterIdentifier, + NativeIndex = 0 + }); + foreach (var arg in argTypes) + { + newArgTypes.Add(arg with + { + NativeIndex = arg.NativeIndex switch + { + TypePositionInfo.UnsetIndex or TypePositionInfo.ReturnIndex => arg.NativeIndex, + int index => index + 1 + } + }); + } + argTypes = newArgTypes.ToImmutableArray(); + } + + _context = new ManagedToNativeStubCodeContext(ReturnIdentifier, ReturnIdentifier); + _marshallers = new BoundGenerators(argTypes, CreateGenerator); + + if (_marshallers.ManagedReturnMarshaller.Generator.UsesNativeIdentifier(_marshallers.ManagedReturnMarshaller.TypeInfo, _context)) + { + // If we need a different native return identifier, then recreate the context with the correct identifier before we generate any code. + _context = new ManagedToNativeStubCodeContext(ReturnIdentifier, $"{ReturnIdentifier}{StubCodeContext.GeneratedNativeIdentifierSuffix}"); + } + + IMarshallingGenerator CreateGenerator(TypePositionInfo p) + { + try + { + // TODO: Remove once helper types (like ArrayMarshaller) are part of the runtime + // This check is to help with enabling the source generator for runtime libraries without making each + // library directly reference System.Memory and System.Runtime.CompilerServices.Unsafe unless it needs to + if (p.MarshallingAttributeInfo is MissingSupportMarshallingInfo + && (environment.TargetFramework == TargetFramework.Net && environment.TargetFrameworkVersion.Major >= 7)) + { + throw new MarshallingNotSupportedException(p, _context); + } + + return generatorFactory.Create(p, _context); + } + catch (MarshallingNotSupportedException e) + { + marshallingNotSupportedCallback(p, e); + return new Forwarder(); + } + } + } + + /// + /// Generate the method body of the p/invoke stub. + /// + /// Name of the target DllImport function to invoke + /// Method body of the p/invoke stub + /// + /// The generated code assumes it will be in an unsafe context. + /// + public BlockSyntax GenerateStubBody(int index, ImmutableArray callConv, TypeSyntax containingTypeName, ManagedTypeInfo typeKeyType) + { + var setupStatements = new List + { + // var (, ) = ((IUnmanagedVirtualMethodTableProvider<>)this).GetFunctionPointerForIndex(.TypeKey) + ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + DeclarationExpression( + IdentifierName("var"), + ParenthesizedVariableDesignation( + SeparatedList( + new[]{ + SingleVariableDesignation( + Identifier(NativeThisParameterIdentifier)), + SingleVariableDesignation( + Identifier(VirtualMethodTableIdentifier))}))), + InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + ParenthesizedExpression( + CastExpression( + GenericName( + Identifier("IUnmanagedVirtualMethodTableProvider")) + .WithTypeArgumentList( + TypeArgumentList( + SingletonSeparatedList(typeKeyType.Syntax))), + ThisExpression())), + IdentifierName("GetFunctionPointerForIndex"))) + .WithArgumentList( + ArgumentList( + SingletonSeparatedList( + Argument( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + containingTypeName, + IdentifierName("TypeKey")))))))) + }; + + GeneratedStatements statements = GeneratedStatements.GenerateStatements( + _marshallers, + _context, + CreateFunctionPointerExpression( + // [] + ElementAccessExpression(IdentifierName(VirtualMethodTableIdentifier), + BracketedArgumentList(SingletonSeparatedList( + Argument(LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(index)))))), + callConv)); + bool shouldInitializeVariables = !statements.GuaranteedUnmarshal.IsEmpty || !statements.Cleanup.IsEmpty; + VariableDeclarations declarations = VariableDeclarations.GenerateDeclarationsForManagedToNative(_marshallers, _context, shouldInitializeVariables); + + + if (_setLastError) + { + // Declare variable for last error + setupStatements.Add(MarshallerHelpers.Declare( + PredefinedType(Token(SyntaxKind.IntKeyword)), + LastErrorIdentifier, + initializeToDefault: false)); + } + + if (!statements.GuaranteedUnmarshal.IsEmpty) + { + setupStatements.Add(MarshallerHelpers.Declare(PredefinedType(Token(SyntaxKind.BoolKeyword)), InvokeSucceededIdentifier, initializeToDefault: true)); + } + + setupStatements.AddRange(declarations.Initializations); + setupStatements.AddRange(declarations.Variables); + setupStatements.AddRange(statements.Setup); + + var tryStatements = new List(); + tryStatements.AddRange(statements.Marshal); + + var invokeStatement = statements.InvokeStatement; + if (_setLastError) + { + StatementSyntax clearLastError = MarshallerHelpers.CreateClearLastSystemErrorStatement(SuccessErrorCode); + + StatementSyntax getLastError = MarshallerHelpers.CreateGetLastSystemErrorStatement(LastErrorIdentifier); + + invokeStatement = Block(clearLastError, invokeStatement, getLastError); + } + invokeStatement = statements.Pin.CastArray().NestFixedStatements(invokeStatement); + + tryStatements.Add(invokeStatement); + // = true; + if (!statements.GuaranteedUnmarshal.IsEmpty) + { + tryStatements.Add(ExpressionStatement(AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, + IdentifierName(InvokeSucceededIdentifier), + LiteralExpression(SyntaxKind.TrueLiteralExpression)))); + } + + tryStatements.AddRange(statements.KeepAlive); + tryStatements.AddRange(statements.Unmarshal); + + List allStatements = setupStatements; + List finallyStatements = new List(); + if (!statements.GuaranteedUnmarshal.IsEmpty) + { + finallyStatements.Add(IfStatement(IdentifierName(InvokeSucceededIdentifier), Block(statements.GuaranteedUnmarshal))); + } + + finallyStatements.AddRange(statements.Cleanup); + if (finallyStatements.Count > 0) + { + // Add try-finally block if there are any statements in the finally block + allStatements.Add( + TryStatement(Block(tryStatements), default, FinallyClause(Block(finallyStatements)))); + } + else + { + allStatements.AddRange(tryStatements); + } + + if (_setLastError) + { + // Marshal.SetLastPInvokeError(); + allStatements.Add(MarshallerHelpers.CreateSetLastPInvokeErrorStatement(LastErrorIdentifier)); + } + + // Return + if (!_marshallers.IsManagedVoidReturn) + allStatements.Add(ReturnStatement(IdentifierName(_context.GetIdentifiers(_marshallers.ManagedReturnMarshaller.TypeInfo).managed))); + + return Block(allStatements); + } + + private ExpressionSyntax CreateFunctionPointerExpression( + ExpressionSyntax untypedFunctionPointerExpression, + ImmutableArray callConv) + { + List functionPointerParameters = new(); + var (paramList, retType, _) = _marshallers.GenerateTargetMethodSignatureData(); + functionPointerParameters.AddRange(paramList.Parameters.Select(p => FunctionPointerParameter(p.Type))); + functionPointerParameters.Add(FunctionPointerParameter(retType)); + + // ((delegate* unmanaged<...>)) + return ParenthesizedExpression(CastExpression( + FunctionPointerType( + FunctionPointerCallingConvention(Token(SyntaxKind.UnmanagedKeyword), callConv.IsEmpty ? null : FunctionPointerUnmanagedCallingConventionList(SeparatedList(callConv))), + FunctionPointerParameterList(SeparatedList(functionPointerParameters))), + untypedFunctionPointerExpression)); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Microsoft.Interop.ComInterfaceGenerator.props b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Microsoft.Interop.ComInterfaceGenerator.props new file mode 100644 index 0000000000000..359b965f88380 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Microsoft.Interop.ComInterfaceGenerator.props @@ -0,0 +1,9 @@ + + + + + diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/Strings.resx b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/Strings.resx new file mode 100644 index 0000000000000..8bacf040d57ab --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/Strings.resx @@ -0,0 +1,188 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Source-generated P/Invokes will ignore any configuration that is not supported. + + + The '{0}' configuration is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + + + The specified marshalling configuration is not supported by source-generated P/Invokes. {0}. + + + The specified '{0}' configuration for parameter '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + + + The specified '{0}' configuration for the return value of method '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + + + The specified value '{0}' for '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + + + Specified configuration is not supported by source-generated P/Invokes. + + + The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' is invalid. + + + The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1} + {1} is a message containing additional details about what is not valid + + + 'StringMarshallingCustomType' must be specified when 'StringMarshalling' is set to 'StringMarshalling.Custom'. + + + 'StringMarshalling' should be set to 'StringMarshalling.Custom' when 'StringMarshallingCustomType' is specified. + + + For types that are not supported by source-generated P/Invokes, the resulting P/Invoke will rely on the underlying runtime to marshal the specified type. + + + The type '{0}' is not supported by source-generated P/Invokes. The generated source will not handle marshalling of parameter '{1}'. + + + {0} The generated source will not handle marshalling of parameter '{1}'. + {0} is a message containing additional details about what is not supported +{1} is the name of the parameter + + + The type '{0}' is not supported by source-generated P/Invokes. The generated source will not handle marshalling of the return value of method '{1}'. + + + {0} The generated source will not handle marshalling of the return value of method '{1}'. + {0} is a message containing additional details about what is not supported +{1} is the name of the method + + + Specified type is not supported by source-generated P/Invokes + + + Method '{0}' is contained in a type '{1}' that is not marked 'partial'. P/Invoke source generation will ignore method '{0}'. + + + Methods marked with 'LibraryImportAttribute' should be 'static', 'partial', and non-generic. P/Invoke source generation will ignore methods that are non-'static', non-'partial', or generic. + + + Method '{0}' should be 'static', 'partial', and non-generic when marked with 'LibraryImportAttribute'. P/Invoke source generation will ignore method '{0}'. + + + Invalid 'LibraryImportAttribute' usage + + \ No newline at end of file diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.cs.xlf b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.cs.xlf new file mode 100644 index 0000000000000..a96bb0372aaf0 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.cs.xlf @@ -0,0 +1,114 @@ + + + + + + Source-generated P/Invokes will ignore any configuration that is not supported. + Zdrojem generovaná volání P/Invokes budou ignorovat všechny nepodporované konfigurace. + + + + The '{0}' configuration is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + Konfiguraci {0} nepodporují zdrojem generovaná volání P/Invokes. Pokud je určená konfigurace povinná, použijte místo ní normální DllImport. + + + + The specified marshalling configuration is not supported by source-generated P/Invokes. {0}. + Určenou konfiguraci zařazování nepodporují zdrojem generovaná volání P/Invokes. {0}. + + + + The specified '{0}' configuration for parameter '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + Určená konfigurace {0} pro parametr {1} není podporována voláním P/Invokes. Pokud je určená konfigurace povinná, použijte místo ní normální DllImport. + + + + The specified '{0}' configuration for the return value of method '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + Určenou konfiguraci {0} návratové hodnoty metody {1} nepodporují zdrojem generovaná volání P/Invokes. Pokud je určená konfigurace povinná, použijte místo ní normální Dllimport. + + + + The specified value '{0}' for '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + Určená hodnota {0} pro {1} se nepodporuje u zdrojem generovaných volání P/Invokes. Pokud je určená konfigurace povinná, použijte místo ní normální Dllimport. + + + + Specified configuration is not supported by source-generated P/Invokes. + Určenou konfiguraci nepodporují zdrojem generovaná volání P/Invokes. + + + + Method '{0}' is contained in a type '{1}' that is not marked 'partial'. P/Invoke source generation will ignore method '{0}'. + Method '{0}' is contained in a type '{1}' that is not marked 'partial'. P/Invoke source generation will ignore method '{0}'. + + + + Methods marked with 'LibraryImportAttribute' should be 'static', 'partial', and non-generic. P/Invoke source generation will ignore methods that are non-'static', non-'partial', or generic. + Methods marked with 'LibraryImportAttribute' should be 'static', 'partial', and non-generic. P/Invoke source generation will ignore methods that are non-'static', non-'partial', or generic. + + + + Method '{0}' should be 'static', 'partial', and non-generic when marked with 'LibraryImportAttribute'. P/Invoke source generation will ignore method '{0}'. + Method '{0}' should be 'static', 'partial', and non-generic when marked with 'LibraryImportAttribute'. P/Invoke source generation will ignore method '{0}'. + + + + Invalid 'LibraryImportAttribute' usage + Invalid 'LibraryImportAttribute' usage + + + + The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' is invalid. + Konfigurace StringMarshalling a StringMarshallingCustomType je neplatná. + + + + The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1} + Konfigurace StringMarshalling a StringMarshallingCustomType u metody {0} je neplatná. {1} + {1} is a message containing additional details about what is not valid + + + 'StringMarshallingCustomType' must be specified when 'StringMarshalling' is set to 'StringMarshalling.Custom'. + StringMarshallingCustomType musí být určený, pokud je StringMarshalling nastavený na StringMarshalling.Custom. + + + + 'StringMarshalling' should be set to 'StringMarshalling.Custom' when 'StringMarshallingCustomType' is specified. + StringMarshalling by měl být nastavený na StringMarshalling.Custom, když je pokud je určený StringMarshallingCustomType. + + + + For types that are not supported by source-generated P/Invokes, the resulting P/Invoke will rely on the underlying runtime to marshal the specified type. + U typů, které nejsou podporovány zdrojem generovanými voláními P/Invoke, bude výsledné volání P/Invoke záviset na podkladovém modulu runtime, aby určený typ zařadil. + + + + The type '{0}' is not supported by source-generated P/Invokes. The generated source will not handle marshalling of parameter '{1}'. + Typ {0} nepodporují zdrojem generovaná volání P/Invokes. Vygenerovaný zdroj nebude zpracovávat zařazování parametru {1}. + + + + {0} The generated source will not handle marshalling of parameter '{1}'. + {0} Generovaný zdroj nebude zpracovávat zařazování parametru {1}. + {0} is a message containing additional details about what is not supported +{1} is the name of the parameter + + + The type '{0}' is not supported by source-generated P/Invokes. The generated source will not handle marshalling of the return value of method '{1}'. + Typ {0} nepodporují zdrojem generovaná volání P/Invokes. Vygenerovaný zdroj nebude zpracovávat zařazování návratové hodnoty metody {1}. + + + + {0} The generated source will not handle marshalling of the return value of method '{1}'. + {0} Generovaný zdroj nebude zpracovávat zařazování návratové hodnoty metody {1}. + {0} is a message containing additional details about what is not supported +{1} is the name of the method + + + Specified type is not supported by source-generated P/Invokes + Určený typ nepodporují zdrojem generovaná volání P/Invokes. + + + + + \ No newline at end of file diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.de.xlf b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.de.xlf new file mode 100644 index 0000000000000..bf465c7641a91 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.de.xlf @@ -0,0 +1,114 @@ + + + + + + Source-generated P/Invokes will ignore any configuration that is not supported. + Quellgenerierte P/Invokes ignorieren alle Konfigurationen, die nicht unterstützt werden. + + + + The '{0}' configuration is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + Die Konfiguration \"{0}\" wird von quellgenerierten P/Invokes nicht unterstützt. Wenn die angegebene Konfiguration erforderlich ist, verwenden Sie stattdessen einen regulären DllImport. + + + + The specified marshalling configuration is not supported by source-generated P/Invokes. {0}. + Die angegebene Marshallingkonfiguration wird von quellgenerierten P/Invokes nicht unterstützt. {0}. + + + + The specified '{0}' configuration for parameter '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + Die angegebene Konfiguration \"{0}\" für den Parameter \"{1}\" wird von quellgenerierten P/Invokes nicht unterstützt. Wenn die angegebene Konfiguration erforderlich ist, verwenden Sie stattdessen einen regulären \"DllImport\". + + + + The specified '{0}' configuration for the return value of method '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + Die angegebene Konfiguration \"{0}\" für den Rückgabewert der Methode \"{1}\" wird von quellgenerierten P/Invokes nicht unterstützt. Wenn die angegebene Konfiguration erforderlich ist, verwenden Sie stattdessen einen regulären DllImport. + + + + The specified value '{0}' for '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + Der angegebene Wert \"{0}\" für \"{1}\" wird von quellgenerierten P/Invokes nicht unterstützt. Wenn die angegebene Konfiguration erforderlich ist, verwenden Sie stattdessen einen regulären \"DllImport\". + + + + Specified configuration is not supported by source-generated P/Invokes. + Die angegebene Konfiguration wird von quellgenerierten P/Invokes nicht unterstützt. + + + + Method '{0}' is contained in a type '{1}' that is not marked 'partial'. P/Invoke source generation will ignore method '{0}'. + Method '{0}' is contained in a type '{1}' that is not marked 'partial'. P/Invoke source generation will ignore method '{0}'. + + + + Methods marked with 'LibraryImportAttribute' should be 'static', 'partial', and non-generic. P/Invoke source generation will ignore methods that are non-'static', non-'partial', or generic. + Methods marked with 'LibraryImportAttribute' should be 'static', 'partial', and non-generic. P/Invoke source generation will ignore methods that are non-'static', non-'partial', or generic. + + + + Method '{0}' should be 'static', 'partial', and non-generic when marked with 'LibraryImportAttribute'. P/Invoke source generation will ignore method '{0}'. + Method '{0}' should be 'static', 'partial', and non-generic when marked with 'LibraryImportAttribute'. P/Invoke source generation will ignore method '{0}'. + + + + Invalid 'LibraryImportAttribute' usage + Invalid 'LibraryImportAttribute' usage + + + + The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' is invalid. + Die Konfiguration von \"StringMarshalling\" und \"StringMarshallingCustomType\" ist ungültig. + + + + The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1} + Die Konfiguration von \"StringMarshalling\" und \"StringMarshallingCustomType\" für die Methode \"{0}\" ist ungültig. {1} + {1} is a message containing additional details about what is not valid + + + 'StringMarshallingCustomType' must be specified when 'StringMarshalling' is set to 'StringMarshalling.Custom'. + \"StringMarshallingCustomType\" muss angegeben werden, wenn \"StringMarshalling\" auf \"StringMarshalling.Custom\" festgelegt ist. + + + + 'StringMarshalling' should be set to 'StringMarshalling.Custom' when 'StringMarshallingCustomType' is specified. + \"StringMarshalling\" muss auf \"StringMarshalling.Custom\" festgelegt werden, wenn \"StringMarshallingCustomType\" angegeben ist. + + + + For types that are not supported by source-generated P/Invokes, the resulting P/Invoke will rely on the underlying runtime to marshal the specified type. + Bei Typen, die von dquellgenerierten P/Invokes nicht unterstützt werden, basiert der resultierende P/Invoke auf der zugrunde liegenden Laufzeit, um den angegebenen Typ zu marshallen. + + + + The type '{0}' is not supported by source-generated P/Invokes. The generated source will not handle marshalling of parameter '{1}'. + Der Typ \"{0}\" wird von vom Quellcode generierten P/Invokes nicht unterstützt. Die generierte Quelle verarbeitet das Marshalling des Parameters \"{1}\" nicht. + + + + {0} The generated source will not handle marshalling of parameter '{1}'. + {0} Die generierte Quelle verarbeitet das Marshalling des Parameters \"{1}\" nicht. + {0} is a message containing additional details about what is not supported +{1} is the name of the parameter + + + The type '{0}' is not supported by source-generated P/Invokes. The generated source will not handle marshalling of the return value of method '{1}'. + Der Typ \"{0}\" wird von vom Quellcode generierten P/Invokes nicht unterstützt. Die generierte Quelle verarbeitet das Marshalling des Rückgabewerts der Methode \"{1}\" nicht. + + + + {0} The generated source will not handle marshalling of the return value of method '{1}'. + {0} Die generierte Quelle verarbeitet das Marshalling des Rückgabewerts der Methode \"{1}\" nicht. + {0} is a message containing additional details about what is not supported +{1} is the name of the method + + + Specified type is not supported by source-generated P/Invokes + Der angegebene Typ wird von quellgenerierten P/Invokes nicht unterstützt. + + + + + \ No newline at end of file diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.es.xlf b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.es.xlf new file mode 100644 index 0000000000000..3f3ce2505f8a8 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.es.xlf @@ -0,0 +1,114 @@ + + + + + + Source-generated P/Invokes will ignore any configuration that is not supported. + Los P/Invoke de un generador de código fuente omitirán cualquier configuración que no esté admitida. + + + + The '{0}' configuration is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + La configuración de “{0}” no está admitida por P/Invokes de un generador de código fuente. Si se requiere la configuración, use un “DllImport” normal en su lugar. + + + + The specified marshalling configuration is not supported by source-generated P/Invokes. {0}. + La configuración de serialización especificada no está admitida por P/Invokes de un generador de código fuente. {0}. + + + + The specified '{0}' configuration for parameter '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + La configuración de “{0}” especificada para el parámetro “{1}” no es compatible con P/Invokes de un generador de código fuente. Si se requiere la configuración especificada, use un “DllImport” normal en su lugar. + + + + The specified '{0}' configuration for the return value of method '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + La configuración de “{0}” especificada para el valor devuelto del método “{1}” no es compatible con P/Invokes generados por origen. Si se requiere la configuración especificada, use un “DllImport” normal en su lugar. + + + + The specified value '{0}' for '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + El valor especificado de “{0}” para “{1}” no es compatible con P/Invokes de un generador de código fuente. Si se requiere la configuración especificada, use un “DllImport” normal en su lugar. + + + + Specified configuration is not supported by source-generated P/Invokes. + La configuración especificada no está admitida por P/Invokes de un generador de código fuente. + + + + Method '{0}' is contained in a type '{1}' that is not marked 'partial'. P/Invoke source generation will ignore method '{0}'. + Method '{0}' is contained in a type '{1}' that is not marked 'partial'. P/Invoke source generation will ignore method '{0}'. + + + + Methods marked with 'LibraryImportAttribute' should be 'static', 'partial', and non-generic. P/Invoke source generation will ignore methods that are non-'static', non-'partial', or generic. + Methods marked with 'LibraryImportAttribute' should be 'static', 'partial', and non-generic. P/Invoke source generation will ignore methods that are non-'static', non-'partial', or generic. + + + + Method '{0}' should be 'static', 'partial', and non-generic when marked with 'LibraryImportAttribute'. P/Invoke source generation will ignore method '{0}'. + Method '{0}' should be 'static', 'partial', and non-generic when marked with 'LibraryImportAttribute'. P/Invoke source generation will ignore method '{0}'. + + + + Invalid 'LibraryImportAttribute' usage + Invalid 'LibraryImportAttribute' usage + + + + The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' is invalid. + La configuración de “StringMarshalling” y “StringMarshallingCustomType” no es válida. + + + + The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1} + La configuración de “StringMarshalling” y “StringMarshallingCustomType” en el método “{0}” no es válida. {1} + {1} is a message containing additional details about what is not valid + + + 'StringMarshallingCustomType' must be specified when 'StringMarshalling' is set to 'StringMarshalling.Custom'. + Se debe especificar “StringMarshallingCustomType” cuando “StringMarshalling” esté establecido en “StringMarshalling.Custom”. + + + + 'StringMarshalling' should be set to 'StringMarshalling.Custom' when 'StringMarshallingCustomType' is specified. + “StringMarshalling” debe establecerse en “StringMarshalling.Custom” cuando “StringMarshallingCustomType” esté especificado. + + + + For types that are not supported by source-generated P/Invokes, the resulting P/Invoke will rely on the underlying runtime to marshal the specified type. + Para los tipos que no son compatibles con P/Invokes de un generador de código fuente, el P/Invoke resultante se basará en el entorno de ejecución subyacente para serializar las referencias del tipo especificado. + + + + The type '{0}' is not supported by source-generated P/Invokes. The generated source will not handle marshalling of parameter '{1}'. + El tipo “{0}” no es compatible con P/Invokes de un generador de código fuente. El código fuente generado no controlará la serialización del parámetro “{1}”. + + + + {0} The generated source will not handle marshalling of parameter '{1}'. + {0} El origen generado no controlará la serialización del parámetro “{1}”. + {0} is a message containing additional details about what is not supported +{1} is the name of the parameter + + + The type '{0}' is not supported by source-generated P/Invokes. The generated source will not handle marshalling of the return value of method '{1}'. + El tipo “{0}” no es compatible con P/Invokes de un generador de código fuente. El código fuente generado no controlará la serialización del valor devuelto del método “{1}”. + + + + {0} The generated source will not handle marshalling of the return value of method '{1}'. + {0} El código fuente generado no controlará la serialización del valor devuelto del método “{1}”. + {0} is a message containing additional details about what is not supported +{1} is the name of the method + + + Specified type is not supported by source-generated P/Invokes + El tipo especificado no está admitido por P/Invokes de un generador de código fuente + + + + + \ No newline at end of file diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.fr.xlf b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.fr.xlf new file mode 100644 index 0000000000000..7a10a0812a863 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.fr.xlf @@ -0,0 +1,114 @@ + + + + + + Source-generated P/Invokes will ignore any configuration that is not supported. + Les P/Invokes générés par la source ignorent toute configuration qui n’est pas prise en charge. + + + + The '{0}' configuration is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + La configuration de « {0} » n’est pas prise en charge par les P/Invok générés par la source. Si la configuration spécifiée est requise, utilisez plutôt un « DllImport » normal. + + + + The specified marshalling configuration is not supported by source-generated P/Invokes. {0}. + La configuration de marshaling spécifiée n’est pas prise en charge par les P/Invokes générés par la source. {0}. + + + + The specified '{0}' configuration for parameter '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + La configuration de « {0} » spécifiée pour le paramètre « {1} » n’est pas prise en charge par les P/Invok générés par la source. Si la configuration spécifiée est requise, utilisez plutôt un « DllImport » normal. + + + + The specified '{0}' configuration for the return value of method '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + La configuration de « {0} » spécifiée pour la valeur renvoyée de la méthode « {1} » n’est pas prise en charge par les P/Invok générés par la source. Si la configuration spécifiée est requise, utilisez plutôt un « DllImport » normal. + + + + The specified value '{0}' for '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + La valeur de « {0} » spécifiée pour « {1} » n’est pas prise en charge par les P/Invok générés par la source. Si la configuration spécifiée est requise, utilisez plutôt un « DllImport » normal. + + + + Specified configuration is not supported by source-generated P/Invokes. + La configuration spécifiée n’est pas prise en charge par les P/Invokes générés par la source. + + + + Method '{0}' is contained in a type '{1}' that is not marked 'partial'. P/Invoke source generation will ignore method '{0}'. + Method '{0}' is contained in a type '{1}' that is not marked 'partial'. P/Invoke source generation will ignore method '{0}'. + + + + Methods marked with 'LibraryImportAttribute' should be 'static', 'partial', and non-generic. P/Invoke source generation will ignore methods that are non-'static', non-'partial', or generic. + Methods marked with 'LibraryImportAttribute' should be 'static', 'partial', and non-generic. P/Invoke source generation will ignore methods that are non-'static', non-'partial', or generic. + + + + Method '{0}' should be 'static', 'partial', and non-generic when marked with 'LibraryImportAttribute'. P/Invoke source generation will ignore method '{0}'. + Method '{0}' should be 'static', 'partial', and non-generic when marked with 'LibraryImportAttribute'. P/Invoke source generation will ignore method '{0}'. + + + + Invalid 'LibraryImportAttribute' usage + Invalid 'LibraryImportAttribute' usage + + + + The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' is invalid. + La configuration de « StringMarshalling » et de « StringMarshallingCustomType » n’est pas valide. + + + + The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1} + La configuration de « StringMarshalling » et de « StringMarshallingCustomType » n’est sur la méthode « {0} » pas valide. {1} + {1} is a message containing additional details about what is not valid + + + 'StringMarshallingCustomType' must be specified when 'StringMarshalling' is set to 'StringMarshalling.Custom'. + « StringMarshallingCustomType » doit être spécifié quand « StringMarshalling » a la valeur « StringMarshalling.Custom ». + + + + 'StringMarshalling' should be set to 'StringMarshalling.Custom' when 'StringMarshallingCustomType' is specified. + « StringMarshalling » doit être défini sur « StringMarshalling.Custom » quand « StringMarshallingCustomType » est spécifié. + + + + For types that are not supported by source-generated P/Invokes, the resulting P/Invoke will rely on the underlying runtime to marshal the specified type. + Pour les types qui ne sont pas pris en charge par les P/Invok générés par la source, le P/Invoke résultant se base sur le runtime sous-jacent pour marshaler le type spécifié. + + + + The type '{0}' is not supported by source-generated P/Invokes. The generated source will not handle marshalling of parameter '{1}'. + Le type « {0} » n’est pas pris en charge par les P/Invokes générés par la source. La source générée ne gère pas le marshaling du paramètre « {1} ». + + + + {0} The generated source will not handle marshalling of parameter '{1}'. + {0} La source générée ne gère pas le marshaling du paramètre « {1} ». + {0} is a message containing additional details about what is not supported +{1} is the name of the parameter + + + The type '{0}' is not supported by source-generated P/Invokes. The generated source will not handle marshalling of the return value of method '{1}'. + Le type « {0} » n’est pas pris en charge par les P/Invokes générés par la source. La source générée ne gère pas le marshaling de la valeur de retour de la méthode « {1} ». + + + + {0} The generated source will not handle marshalling of the return value of method '{1}'. + {0} La source générée ne gère pas le marshaling de la valeur de retour de la méthode « {1} ». + {0} is a message containing additional details about what is not supported +{1} is the name of the method + + + Specified type is not supported by source-generated P/Invokes + Le type spécifié n’est pas prise en charge par les P/Invokes générés par la source. + + + + + \ No newline at end of file diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.it.xlf b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.it.xlf new file mode 100644 index 0000000000000..be3a16f70670c --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.it.xlf @@ -0,0 +1,114 @@ + + + + + + Source-generated P/Invokes will ignore any configuration that is not supported. + I P/Invoke generati dall'origine ignoreranno qualsiasi configurazione non supportata. + + + + The '{0}' configuration is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + La configurazione '{0}' non è supportata dai P/Invoke generati dall'origine. Se la configurazione specificata è obbligatoria, usare un attributo `DllImport` normale. + + + + The specified marshalling configuration is not supported by source-generated P/Invokes. {0}. + La configurazione di marshalling specificata non è supportata dai P/Invoke generati dall'origine. {0}. + + + + The specified '{0}' configuration for parameter '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + La configurazione '{0}' specificata per il parametro '{1}' non è supportata dai P/Invoke generati dall'origine. Se la configurazione specificata è obbligatoria, usare un attributo `DllImport` normale. + + + + The specified '{0}' configuration for the return value of method '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + La configurazione '{0}' specificata per il valore restituito del metodo '{1}' non è supportata dai P/Invoke generati dall'origine. Se la configurazione specificata è obbligatoria, usare un attributo `DllImport` normale. + + + + The specified value '{0}' for '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + Il valore '{0}' specificato per '{1}' non è supportato dai P/Invoke generati dall'origine. Se la configurazione specificata è obbligatoria, usare un attributo `DllImport` normale. + + + + Specified configuration is not supported by source-generated P/Invokes. + La configurazione specificata non è supportata dai P/Invoke generati dall'origine. + + + + Method '{0}' is contained in a type '{1}' that is not marked 'partial'. P/Invoke source generation will ignore method '{0}'. + Method '{0}' is contained in a type '{1}' that is not marked 'partial'. P/Invoke source generation will ignore method '{0}'. + + + + Methods marked with 'LibraryImportAttribute' should be 'static', 'partial', and non-generic. P/Invoke source generation will ignore methods that are non-'static', non-'partial', or generic. + Methods marked with 'LibraryImportAttribute' should be 'static', 'partial', and non-generic. P/Invoke source generation will ignore methods that are non-'static', non-'partial', or generic. + + + + Method '{0}' should be 'static', 'partial', and non-generic when marked with 'LibraryImportAttribute'. P/Invoke source generation will ignore method '{0}'. + Method '{0}' should be 'static', 'partial', and non-generic when marked with 'LibraryImportAttribute'. P/Invoke source generation will ignore method '{0}'. + + + + Invalid 'LibraryImportAttribute' usage + Invalid 'LibraryImportAttribute' usage + + + + The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' is invalid. + La configurazione di 'StringMarshalling' e 'StringMarshallingCustomType' non è valida. + + + + The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1} + La configurazione di 'StringMarshalling' e 'StringMarshallingCustomType' nel metodo '{0}' non è valida. {1} + {1} is a message containing additional details about what is not valid + + + 'StringMarshallingCustomType' must be specified when 'StringMarshalling' is set to 'StringMarshalling.Custom'. + È necessario specificare 'StringMarshallingCustomType' quando 'StringMarshalling' è impostato su 'StringMarshalling.Custom'. + + + + 'StringMarshalling' should be set to 'StringMarshalling.Custom' when 'StringMarshallingCustomType' is specified. + 'StringMarshalling' deve essere impostato su 'StringMarshalling.Custom' quando è specificato 'StringMarshallingCustomType'. + + + + For types that are not supported by source-generated P/Invokes, the resulting P/Invoke will rely on the underlying runtime to marshal the specified type. + Per i tipi non supportati da P/Invoke generati dall'origine, il P/Invoke risultante si baserà sul runtime sottostante per effettuare il marshalling del tipo specificato. + + + + The type '{0}' is not supported by source-generated P/Invokes. The generated source will not handle marshalling of parameter '{1}'. + Il tipo '{0}' non è supportato dai P/Invoke generati dall'origine. L'origine generata non gestirà il marshalling del parametro '{1}'. + + + + {0} The generated source will not handle marshalling of parameter '{1}'. + {0} L'origine generata non gestirà il marshalling del parametro '{1}'. + {0} is a message containing additional details about what is not supported +{1} is the name of the parameter + + + The type '{0}' is not supported by source-generated P/Invokes. The generated source will not handle marshalling of the return value of method '{1}'. + Il tipo '{0}' non è supportato dai P/Invoke generati dall'origine. L'origine generata non gestirà il marshalling del valore restituito del metodo '{1}'. + + + + {0} The generated source will not handle marshalling of the return value of method '{1}'. + {0} L'origine generata non gestirà il marshalling del valore restituito del metodo '{1}'. + {0} is a message containing additional details about what is not supported +{1} is the name of the method + + + Specified type is not supported by source-generated P/Invokes + Il tipo specificato non è supportato dai P/Invoke generati dall'origine + + + + + \ No newline at end of file diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.ja.xlf b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.ja.xlf new file mode 100644 index 0000000000000..f349a06cba61d --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.ja.xlf @@ -0,0 +1,114 @@ + + + + + + Source-generated P/Invokes will ignore any configuration that is not supported. + ソース生成済みの P/Invoke は、サポートされていない構成を無視します。 + + + + The '{0}' configuration is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + '{0}' 構成は、ソース生成済みの P/Invoke ではサポートされていません。指定された構成が必要な場合は、代わりに通常の 'DllImport' を使用します。 + + + + The specified marshalling configuration is not supported by source-generated P/Invokes. {0}. + 指定されたマーシャリング構成は、ソースで生成された P/Invoke ではサポートされていません。{0}。 + + + + The specified '{0}' configuration for parameter '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + パラメーター '{1}' 向けに指定された '{0}' 構成は、ソース生成済みの P/Invoke ではサポートされていません。指定された構成が必要な場合は、代わりに通常の 'DllImport' を使用します。 + + + + The specified '{0}' configuration for the return value of method '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + メソッド '{1}' の戻り値向けに指定された '{0}' 構成は、ソース生成済みの P/Invoke ではサポートされていません。指定された構成が必要な場合は、代わりに通常の 'DllImport' を使用します。 + + + + The specified value '{0}' for '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + '{1}' 向けに指定された値 '{0}' は、ソース生成済みの P/Invoke ではサポートされていません。指定された構成が必要な場合は、代わりに通常の 'DllImport' を使用します。 + + + + Specified configuration is not supported by source-generated P/Invokes. + 指定された構成は、ソースで生成された P/Invoke ではサポートされていません。 + + + + Method '{0}' is contained in a type '{1}' that is not marked 'partial'. P/Invoke source generation will ignore method '{0}'. + Method '{0}' is contained in a type '{1}' that is not marked 'partial'. P/Invoke source generation will ignore method '{0}'. + + + + Methods marked with 'LibraryImportAttribute' should be 'static', 'partial', and non-generic. P/Invoke source generation will ignore methods that are non-'static', non-'partial', or generic. + Methods marked with 'LibraryImportAttribute' should be 'static', 'partial', and non-generic. P/Invoke source generation will ignore methods that are non-'static', non-'partial', or generic. + + + + Method '{0}' should be 'static', 'partial', and non-generic when marked with 'LibraryImportAttribute'. P/Invoke source generation will ignore method '{0}'. + Method '{0}' should be 'static', 'partial', and non-generic when marked with 'LibraryImportAttribute'. P/Invoke source generation will ignore method '{0}'. + + + + Invalid 'LibraryImportAttribute' usage + Invalid 'LibraryImportAttribute' usage + + + + The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' is invalid. + 'StringMarshalling' と 'StringMarshallingCustomType' の構成が無効です。 + + + + The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1} + メソッド '{0}' の 'StringMarshalling' と 'StringMarshallingCustomType' の構成が無効です。{1} + {1} is a message containing additional details about what is not valid + + + 'StringMarshallingCustomType' must be specified when 'StringMarshalling' is set to 'StringMarshalling.Custom'. + 'StringMarshalling' が 'StringMarshalling.Custom' に設定されている場合は、'StringMarshallingCustomType' を指定する必要があります。 + + + + 'StringMarshalling' should be set to 'StringMarshalling.Custom' when 'StringMarshallingCustomType' is specified. + 'StringMarshallingCustomType' が指定されている場合、'StringMarshalling' を 'StringMarshalling.Custom' に設定する必要があります。 + + + + For types that are not supported by source-generated P/Invokes, the resulting P/Invoke will rely on the underlying runtime to marshal the specified type. + ソース生成済みの P/Invoke でサポートされていない型である場合、生成された P/Invoke は、基礎となるなるランタイムに依存して、指定された型をマーシャリングします。 + + + + The type '{0}' is not supported by source-generated P/Invokes. The generated source will not handle marshalling of parameter '{1}'. + 型 '{0}' は、ソース生成済みの P/Invoke ではサポートされていません。生成されたソースは、パラメーター '{1}' のマーシャリングを処理しません。 + + + + {0} The generated source will not handle marshalling of parameter '{1}'. + {0} 生成されたソースはパラメーター '{1}' のマーシャリングを処理しません。 + {0} is a message containing additional details about what is not supported +{1} is the name of the parameter + + + The type '{0}' is not supported by source-generated P/Invokes. The generated source will not handle marshalling of the return value of method '{1}'. + 型 '{0}' は、ソース生成済みの P/Invoke ではサポートされていません。生成されたソースは、メソッド '{1}' の戻り値のマーシャリングを処理しません。 + + + + {0} The generated source will not handle marshalling of the return value of method '{1}'. + {0} 生成されたソースは、メソッド '{1}' の戻り値のマーシャリングを処理しません。 + {0} is a message containing additional details about what is not supported +{1} is the name of the method + + + Specified type is not supported by source-generated P/Invokes + 指定された型は、ソースで生成された P/Invoke ではサポートされていません + + + + + \ No newline at end of file diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.ko.xlf b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.ko.xlf new file mode 100644 index 0000000000000..53bb45e12ef65 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.ko.xlf @@ -0,0 +1,114 @@ + + + + + + Source-generated P/Invokes will ignore any configuration that is not supported. + 소스 생성 P/Invoke는 지원되지 않는 구성을 무시합니다. + + + + The '{0}' configuration is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + '{0}' 구성은 소스 생성 P/Invoke에서 지원되지 않습니다. 지정된 구성이 필요한 경우 일반 'DllImport'를 대신 사용하세요. + + + + The specified marshalling configuration is not supported by source-generated P/Invokes. {0}. + 지정된 마샬링 구성은 소스 생성 P/Invoke에서 지원되지 않습니다. {0}. + + + + The specified '{0}' configuration for parameter '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + 매개 변수 '{1}'에 대해 지정된 '{0}' 구성이 소스 생성 P/Invoke에서 지원되지 않습니다. 지정된 구성이 필요한 경우 일반 'DllImport'를 대신 사용하세요. + + + + The specified '{0}' configuration for the return value of method '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + 메서드 '{1}'의 반환 값에 대해 지정된 '{0}' 구성은 소스 생성 P/Invoke에서 지원되지 않습니다. 지정된 구성이 필요한 경우 일반 'DllImport'를 대신 사용하세요. + + + + The specified value '{0}' for '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + '{1}'에 대해 지정된 값 '{0}'은(는) 소스 생성 P/Invoke에서 지원되지 않습니다. 지정된 구성이 필요한 경우 일반 'DllImport'를 대신 사용하세요. + + + + Specified configuration is not supported by source-generated P/Invokes. + 지정된 구성은 소스 생성 P/Invoke에서 지원되지 않습니다. + + + + Method '{0}' is contained in a type '{1}' that is not marked 'partial'. P/Invoke source generation will ignore method '{0}'. + Method '{0}' is contained in a type '{1}' that is not marked 'partial'. P/Invoke source generation will ignore method '{0}'. + + + + Methods marked with 'LibraryImportAttribute' should be 'static', 'partial', and non-generic. P/Invoke source generation will ignore methods that are non-'static', non-'partial', or generic. + Methods marked with 'LibraryImportAttribute' should be 'static', 'partial', and non-generic. P/Invoke source generation will ignore methods that are non-'static', non-'partial', or generic. + + + + Method '{0}' should be 'static', 'partial', and non-generic when marked with 'LibraryImportAttribute'. P/Invoke source generation will ignore method '{0}'. + Method '{0}' should be 'static', 'partial', and non-generic when marked with 'LibraryImportAttribute'. P/Invoke source generation will ignore method '{0}'. + + + + Invalid 'LibraryImportAttribute' usage + Invalid 'LibraryImportAttribute' usage + + + + The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' is invalid. + 'StringMarshalling' 및 'StringMarshallingCustomType'의 구성이 잘못되었습니다. + + + + The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1} + '{0}' 메서드의 'StringMarshalling' 및 'StringMarshallingCustomType' 구성이 잘못되었습니다. {1} + {1} is a message containing additional details about what is not valid + + + 'StringMarshallingCustomType' must be specified when 'StringMarshalling' is set to 'StringMarshalling.Custom'. + 'StringMarshalling'이 'StringMarshalling.Custom'으로 설정된 경우 'StringMarshallingCustomType'을 지정해야 합니다. + + + + 'StringMarshalling' should be set to 'StringMarshalling.Custom' when 'StringMarshallingCustomType' is specified. + 'StringMarshallingCustomType'이 지정된 경우 'StringMarshalling'은 'StringMarshalling.Custom'으로 설정되어야 합니다. + + + + For types that are not supported by source-generated P/Invokes, the resulting P/Invoke will rely on the underlying runtime to marshal the specified type. + 소스 생성 P/Invoke에서 지원하지 않는 형식의 경우 결과 P/Invoke는 기본 런타임에 의존하여 지정된 형식을 마샬링합니다. + + + + The type '{0}' is not supported by source-generated P/Invokes. The generated source will not handle marshalling of parameter '{1}'. + 형식 '{0}'은(는) 소스 생성 P/Invoke에서 지원되지 않습니다. 생성된 소스는 '{1}' 매개 변수의 마샬링을 처리하지 않습니다. + + + + {0} The generated source will not handle marshalling of parameter '{1}'. + {0} 생성된 소스는 '{1}' 매개 변수의 마샬링을 처리하지 않습니다. + {0} is a message containing additional details about what is not supported +{1} is the name of the parameter + + + The type '{0}' is not supported by source-generated P/Invokes. The generated source will not handle marshalling of the return value of method '{1}'. + 형식 '{0}'은(는) 소스 생성 P/Invoke에서 지원되지 않습니다. 생성된 소스는 '{1}' 메서드의 반환 값 마샬링을 처리하지 않습니다. + + + + {0} The generated source will not handle marshalling of the return value of method '{1}'. + {0} 생성된 소스는 '{1}' 메서드의 반환 값 마샬링을 처리하지 않습니다. + {0} is a message containing additional details about what is not supported +{1} is the name of the method + + + Specified type is not supported by source-generated P/Invokes + 지정된 형식은 소스 생성 P/Invoke에서 지원되지 않습니다. + + + + + \ No newline at end of file diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.pl.xlf b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.pl.xlf new file mode 100644 index 0000000000000..283a271d108ec --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.pl.xlf @@ -0,0 +1,114 @@ + + + + + + Source-generated P/Invokes will ignore any configuration that is not supported. + Funkcja P/Invokes generowana przez źródło zignoruje każdą nieobsługiwaną konfigurację. + + + + The '{0}' configuration is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + Konfiguracja {0} nie jest obsługiwana przez funkcję P/Invokes generowaną przez źródło. Jeśli określona konfiguracja jest wymagana, użyj zamiast tego zwykłego elementu „DllImport”. + + + + The specified marshalling configuration is not supported by source-generated P/Invokes. {0}. + Określona konfiguracja skierowania nie jest obsługiwana przez funkcję P/Invokes generowaną przez źródło. {0}. + + + + The specified '{0}' configuration for parameter '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + Określona konfiguracja „{0}” dla parametru „{1}” nie jest obsługiwana przez funkcję P/Invokes generowaną przez źródło. Jeśli określona konfiguracja jest wymagana, użyj zamiast tego zwykłego elementu „DllImport”. + + + + The specified '{0}' configuration for the return value of method '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + Określona konfiguracja „{0}” dla wartości zwracanej przez metodę „{1}” nie jest obsługiwana przez funkcję P/Invokes generowaną przez źródło. Jeśli określona konfiguracja jest wymagana, użyj zamiast tego zwykłego elementu „DllImport”. + + + + The specified value '{0}' for '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + Określona wartość „{0}” dla parametru „{1}” nie jest obsługiwana przez funkcję P/Invokes generowaną przez źródło. Jeśli określona konfiguracja jest wymagana, użyj zamiast tego zwykłego elementu „DllImport”. + + + + Specified configuration is not supported by source-generated P/Invokes. + Określona konfiguracja nie jest obsługiwana przez funkcję P/Invokes generowaną przez źródło. + + + + Method '{0}' is contained in a type '{1}' that is not marked 'partial'. P/Invoke source generation will ignore method '{0}'. + Method '{0}' is contained in a type '{1}' that is not marked 'partial'. P/Invoke source generation will ignore method '{0}'. + + + + Methods marked with 'LibraryImportAttribute' should be 'static', 'partial', and non-generic. P/Invoke source generation will ignore methods that are non-'static', non-'partial', or generic. + Methods marked with 'LibraryImportAttribute' should be 'static', 'partial', and non-generic. P/Invoke source generation will ignore methods that are non-'static', non-'partial', or generic. + + + + Method '{0}' should be 'static', 'partial', and non-generic when marked with 'LibraryImportAttribute'. P/Invoke source generation will ignore method '{0}'. + Method '{0}' should be 'static', 'partial', and non-generic when marked with 'LibraryImportAttribute'. P/Invoke source generation will ignore method '{0}'. + + + + Invalid 'LibraryImportAttribute' usage + Invalid 'LibraryImportAttribute' usage + + + + The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' is invalid. + Konfiguracja elementów „StringMarshalling” i „StringMarshallingCustomType” jest nieprawidłowa. + + + + The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1} + Konfiguracja elementów „StringMarshalling” i „StringMarshallingCustomType” w metodzie „{0}” jest nieprawidłowa. {1} + {1} is a message containing additional details about what is not valid + + + 'StringMarshallingCustomType' must be specified when 'StringMarshalling' is set to 'StringMarshalling.Custom'. + Element „StringMarshallingCustomType” należy określić, gdy element „StringMarshalling” ma wartość „StringMarshalling.Custom”. + + + + 'StringMarshalling' should be set to 'StringMarshalling.Custom' when 'StringMarshallingCustomType' is specified. + Element „StringMarshalling” należy ustawić na wartość „StringMarshalling.Custom”, gdy określono element „StringMarshallingCustomType”. + + + + For types that are not supported by source-generated P/Invokes, the resulting P/Invoke will rely on the underlying runtime to marshal the specified type. + W przypadku typów, które nie są obsługiwane przez funkcję P/Invokes generowaną przez źródło, wynikowa funkcja P/Invoke będzie polegać na bazowym środowisku uruchomieniowym, aby skierować określony typ. + + + + The type '{0}' is not supported by source-generated P/Invokes. The generated source will not handle marshalling of parameter '{1}'. + Typ „{0}” nie jest obsługiwany przez funkcję P/Invokes generowaną przez źródło. Wygenerowane źródło nie obsługuje skierowania parametru „{1}”. + + + + {0} The generated source will not handle marshalling of parameter '{1}'. + {0} Wygenerowane źródło nie obsługuje skierowania parametru „{1}”. + {0} is a message containing additional details about what is not supported +{1} is the name of the parameter + + + The type '{0}' is not supported by source-generated P/Invokes. The generated source will not handle marshalling of the return value of method '{1}'. + Typ „{0}” nie jest obsługiwany przez funkcję P/Invokes generowaną przez źródło. Wygenerowane źródło nie obsługuje skierowania wartości zwracanej przez metodę „{1}”. + + + + {0} The generated source will not handle marshalling of the return value of method '{1}'. + {0}Wygenerowane źródło nie obsługuje skierowania wartości zwracanej przez metodę „{1}”. + {0} is a message containing additional details about what is not supported +{1} is the name of the method + + + Specified type is not supported by source-generated P/Invokes + Określony typ nie jest obsługiwany przez funkcję P/Invokes generowaną przez źródło + + + + + \ No newline at end of file diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.pt-BR.xlf b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.pt-BR.xlf new file mode 100644 index 0000000000000..8fecda2e4234a --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.pt-BR.xlf @@ -0,0 +1,114 @@ + + + + + + Source-generated P/Invokes will ignore any configuration that is not supported. + P/Invokes gerados pela origem ignorarão qualquer configuração sem suporte. + + + + The '{0}' configuration is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + A configuração '{0}' não é suportada por P/Invokes gerados pela origem. Se a configuração especificada for necessária, use um 'DllImport' regular. + + + + The specified marshalling configuration is not supported by source-generated P/Invokes. {0}. + Não há suporte para a configuração de marshaling especificada por P/Invokes gerados pela origem. {0}. + + + + The specified '{0}' configuration for parameter '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + A configuração '{0}' especificada para o parâmetro '{1}' não é suportada por P/Invokes gerados pela origem. Se a configuração especificada for necessária, use um 'DllImport' regular. + + + + The specified '{0}' configuration for the return value of method '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + A configuração '{0}' especificada para o valor retornado do método '{1}' não é suportada por P/Invokes gerados pela origem. Se a configuração especificada for necessária, use um 'DllImport' regular. + + + + The specified value '{0}' for '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + O valor '{0}' especificado para '{1}' não é suportada por P/Invokes gerados pela origem. Se a configuração especificada for necessária, use um 'DllImport' regular. + + + + Specified configuration is not supported by source-generated P/Invokes. + A configuração especificada não tem suporte de P/Invokes gerados pela origem. + + + + Method '{0}' is contained in a type '{1}' that is not marked 'partial'. P/Invoke source generation will ignore method '{0}'. + Method '{0}' is contained in a type '{1}' that is not marked 'partial'. P/Invoke source generation will ignore method '{0}'. + + + + Methods marked with 'LibraryImportAttribute' should be 'static', 'partial', and non-generic. P/Invoke source generation will ignore methods that are non-'static', non-'partial', or generic. + Methods marked with 'LibraryImportAttribute' should be 'static', 'partial', and non-generic. P/Invoke source generation will ignore methods that are non-'static', non-'partial', or generic. + + + + Method '{0}' should be 'static', 'partial', and non-generic when marked with 'LibraryImportAttribute'. P/Invoke source generation will ignore method '{0}'. + Method '{0}' should be 'static', 'partial', and non-generic when marked with 'LibraryImportAttribute'. P/Invoke source generation will ignore method '{0}'. + + + + Invalid 'LibraryImportAttribute' usage + Invalid 'LibraryImportAttribute' usage + + + + The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' is invalid. + A configuração de 'StringMarshalling' e 'StringMarshallingCustomType' é inválida. + + + + The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1} + A configuração de 'StringMarshalling' e 'StringMarshallingCustomType' no método '{0}' é inválida. {1} + {1} is a message containing additional details about what is not valid + + + 'StringMarshallingCustomType' must be specified when 'StringMarshalling' is set to 'StringMarshalling.Custom'. + 'StringMarshallingCustomType' deve ser especificado quando 'StringMarshalling' está definido como 'StringMarshalling.Custom'. + + + + 'StringMarshalling' should be set to 'StringMarshalling.Custom' when 'StringMarshallingCustomType' is specified. + 'StringMarshalling' deve ser definido como 'StringMarshalling.Custom' quando 'StringMarshallingCustomType' for especificado. + + + + For types that are not supported by source-generated P/Invokes, the resulting P/Invoke will rely on the underlying runtime to marshal the specified type. + Para tipos sem suporte por P/Invokes gerados pela origem, o P/Invoke resultante dependerá do tempo de execução subjacente para realizar marshaling no tipo especificado. + + + + The type '{0}' is not supported by source-generated P/Invokes. The generated source will not handle marshalling of parameter '{1}'. + O tipo '{0}' não é suportado por P/Invokes gerados pela origem. A origem gerada não manipulará o marshalling do parâmetro '{1}'. + + + + {0} The generated source will not handle marshalling of parameter '{1}'. + {0} A origem gerada não manipulará o marshalling do parâmetro '{1}'. + {0} is a message containing additional details about what is not supported +{1} is the name of the parameter + + + The type '{0}' is not supported by source-generated P/Invokes. The generated source will not handle marshalling of the return value of method '{1}'. + O tipo '{0}' não é suportado por P/Invokes gerados pela origem. A origem gerada não tratará marshaling do valor de retorno do método '{1}'. + + + + {0} The generated source will not handle marshalling of the return value of method '{1}'. + {0} A origem gerada não manipulará o marshalling do valor retornado do método '{1}'. + {0} is a message containing additional details about what is not supported +{1} is the name of the method + + + Specified type is not supported by source-generated P/Invokes + O tipo especificado não tem suporte de P/Invokes gerados pela origem. + + + + + \ No newline at end of file diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.ru.xlf b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.ru.xlf new file mode 100644 index 0000000000000..9503e52e57f52 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.ru.xlf @@ -0,0 +1,114 @@ + + + + + + Source-generated P/Invokes will ignore any configuration that is not supported. + P/Invoke с созданием источника будут игнорировать все неподдерживаемые конфигурации. + + + + The '{0}' configuration is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + Конфигурация \"{0}\" не поддерживается в P/Invoke с созданием источника. Если указанная конфигурация обязательна, используйте обычный метод \"DllImport\". + + + + The specified marshalling configuration is not supported by source-generated P/Invokes. {0}. + Указанная конфигурация маршализации не поддерживается в P/Invoke с созданием источника. {0}. + + + + The specified '{0}' configuration for parameter '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + Указанная конфигурация \"{0}\" для параметра \"{1}\" не поддерживается в P/Invoke с созданием источника. Если указанная конфигурация обязательна, используйте обычный метод \"DllImport\". + + + + The specified '{0}' configuration for the return value of method '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + Указанная конфигурация \"{0}\" для возвращаемого значения метода \"{1}\" не поддерживается в P/Invoke с созданием источника. Если указанная конфигурация обязательна, используйте обычный метод \"DllImport\". + + + + The specified value '{0}' for '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + Указанное значение “{0}” для “{1}” не поддерживается в P/Invoke с созданием источника. Если указанная конфигурация обязательна, используйте обычный метод “DllImport”. + + + + Specified configuration is not supported by source-generated P/Invokes. + Указанная конфигурация не поддерживается в P/Invoke с созданием источника. + + + + Method '{0}' is contained in a type '{1}' that is not marked 'partial'. P/Invoke source generation will ignore method '{0}'. + Method '{0}' is contained in a type '{1}' that is not marked 'partial'. P/Invoke source generation will ignore method '{0}'. + + + + Methods marked with 'LibraryImportAttribute' should be 'static', 'partial', and non-generic. P/Invoke source generation will ignore methods that are non-'static', non-'partial', or generic. + Methods marked with 'LibraryImportAttribute' should be 'static', 'partial', and non-generic. P/Invoke source generation will ignore methods that are non-'static', non-'partial', or generic. + + + + Method '{0}' should be 'static', 'partial', and non-generic when marked with 'LibraryImportAttribute'. P/Invoke source generation will ignore method '{0}'. + Method '{0}' should be 'static', 'partial', and non-generic when marked with 'LibraryImportAttribute'. P/Invoke source generation will ignore method '{0}'. + + + + Invalid 'LibraryImportAttribute' usage + Invalid 'LibraryImportAttribute' usage + + + + The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' is invalid. + Конфигурация \"StringMarshalling\" и \"StringMarshallingCustomType\" недопустима. + + + + The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1} + Конфигурация \"StringMarshalling\" и \"StringMarshallingCustomType\" в методе \"{0}\" недопустима. {1} + {1} is a message containing additional details about what is not valid + + + 'StringMarshallingCustomType' must be specified when 'StringMarshalling' is set to 'StringMarshalling.Custom'. + Если для \"StringMarshalling\" задано значение \"StringMarshalling.Custom\", необходимо указать \"StringMarshallingCustomType\". + + + + 'StringMarshalling' should be set to 'StringMarshalling.Custom' when 'StringMarshallingCustomType' is specified. + Если указано \"StringMarshallingCustomType\", для \"StringMarshalling\" следует задать значение \"StringMarshalling.Custom\". + + + + For types that are not supported by source-generated P/Invokes, the resulting P/Invoke will rely on the underlying runtime to marshal the specified type. + Для типов, которые не поддерживаются в P/Invoke с созданием источника, в полученном P/Invoke для маршализации указанного типа будет использоваться среда выполнения. + + + + The type '{0}' is not supported by source-generated P/Invokes. The generated source will not handle marshalling of parameter '{1}'. + Тип \"{0}\" не поддерживается в P/Invoke с созданием источника. Созданный источник не будет обрабатывать маршализацию параметра \"{1}\". + + + + {0} The generated source will not handle marshalling of parameter '{1}'. + {0} Созданный источник не будет обрабатывать маршализацию параметра \"{1}\". + {0} is a message containing additional details about what is not supported +{1} is the name of the parameter + + + The type '{0}' is not supported by source-generated P/Invokes. The generated source will not handle marshalling of the return value of method '{1}'. + Тип \"{0}\" не поддерживается в P/Invoke с созданием источника. Созданный источник не будет обрабатывать маршализацию возвращаемого значения метода \"{1}\". + + + + {0} The generated source will not handle marshalling of the return value of method '{1}'. + {0} Созданный источник не будет обрабатывать маршализацию возвращаемого значения метода \"{1}\". + {0} is a message containing additional details about what is not supported +{1} is the name of the method + + + Specified type is not supported by source-generated P/Invokes + Указанный тип не поддерживается в P/Invoke с созданием источника. + + + + + \ No newline at end of file diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.tr.xlf b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.tr.xlf new file mode 100644 index 0000000000000..305afacff2976 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.tr.xlf @@ -0,0 +1,114 @@ + + + + + + Source-generated P/Invokes will ignore any configuration that is not supported. + Kaynak tarafından oluşturulan P/Invokes desteklenmeyen yapılandırmaları yok sayar. + + + + The '{0}' configuration is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + '{0}' yapılandırması, kaynak tarafından oluşturulan P/Invokes tarafından desteklenmiyor. Belirtilen yapılandırma gerekli ise, bunun yerine normal bir 'DllImport' kullanın. + + + + The specified marshalling configuration is not supported by source-generated P/Invokes. {0}. + Belirtilen sıralama yapılandırması, kaynak tarafından oluşturulan P/Invokes tarafından desteklenmiyor. {0}. + + + + The specified '{0}' configuration for parameter '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + '{1}' parametresi için belirtilen '{0}' yapılandırması, kaynak tarafından oluşturulan P/Invokes tarafından desteklenmiyor. Belirtilen yapılandırma gerekli ise, bunun yerine normal bir 'DllImport' kullanın. + + + + The specified '{0}' configuration for the return value of method '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + '{1}' metodunun dönüş değeri için belirtilen '{0}' yapılandırması, kaynak tarafından oluşturulan P/Invokes tarafından desteklenmiyor. Belirtilen yapılandırma gerekli ise, bunun yerine normal bir 'DllImport' kullanın. + + + + The specified value '{0}' for '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + '{1}' için belirtilen '{0}' değeri, kaynak tarafından oluşturulan P/Invokes tarafından desteklenmiyor. Belirtilen yapılandırma gerekli ise, bunun yerine normal bir 'DllImport' kullanın. + + + + Specified configuration is not supported by source-generated P/Invokes. + Belirtilen yapılandırma, kaynak tarafından oluşturulan P/Invokes tarafından desteklenmiyor. + + + + Method '{0}' is contained in a type '{1}' that is not marked 'partial'. P/Invoke source generation will ignore method '{0}'. + Method '{0}' is contained in a type '{1}' that is not marked 'partial'. P/Invoke source generation will ignore method '{0}'. + + + + Methods marked with 'LibraryImportAttribute' should be 'static', 'partial', and non-generic. P/Invoke source generation will ignore methods that are non-'static', non-'partial', or generic. + Methods marked with 'LibraryImportAttribute' should be 'static', 'partial', and non-generic. P/Invoke source generation will ignore methods that are non-'static', non-'partial', or generic. + + + + Method '{0}' should be 'static', 'partial', and non-generic when marked with 'LibraryImportAttribute'. P/Invoke source generation will ignore method '{0}'. + Method '{0}' should be 'static', 'partial', and non-generic when marked with 'LibraryImportAttribute'. P/Invoke source generation will ignore method '{0}'. + + + + Invalid 'LibraryImportAttribute' usage + Invalid 'LibraryImportAttribute' usage + + + + The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' is invalid. + 'StringMarshalling' ve 'StringMarshallingCustomType' yapılandırması geçersiz. + + + + The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1} + '{0}' metodundaki 'StringMarshalling' ve 'StringMarshallingCustomType' yapılandırması geçersiz. {1} + {1} is a message containing additional details about what is not valid + + + 'StringMarshallingCustomType' must be specified when 'StringMarshalling' is set to 'StringMarshalling.Custom'. + 'StringMarshalling' 'StringMarshalling.Custom' olarak ayarlandığında 'StringMarshallingCustomType' belirtilmelidir. + + + + 'StringMarshalling' should be set to 'StringMarshalling.Custom' when 'StringMarshallingCustomType' is specified. + 'StringMarshallingCustomType' belirtilirken 'StringMarshalling', 'StringMarshalling.Custom' olarak ayarlanmalıdır. + + + + For types that are not supported by source-generated P/Invokes, the resulting P/Invoke will rely on the underlying runtime to marshal the specified type. + Kaynak tarafından oluşturulan P/Invokes tarafından desteklenmeyen türler için, elde edilen P/Invoke, belirtilen türü sıralamak için temel alınan çalışma zamanını kullanır. + + + + The type '{0}' is not supported by source-generated P/Invokes. The generated source will not handle marshalling of parameter '{1}'. + '{0}' türü, kaynak tarafından oluşturulan P/Invokes tarafından desteklenmiyor. Oluşturulan kaynak, '{1}' parametresinin sıralamasını işlemez. + + + + {0} The generated source will not handle marshalling of parameter '{1}'. + {0} Oluşturulan kaynak '{1}' parametresinin sıralamasını işlemez. + {0} is a message containing additional details about what is not supported +{1} is the name of the parameter + + + The type '{0}' is not supported by source-generated P/Invokes. The generated source will not handle marshalling of the return value of method '{1}'. + '{0}' türü, kaynak tarafından oluşturulan P/Invokes tarafından desteklenmiyor. Oluşturulan kaynak, '{1}' metodunun dönüş değerinin sıralamasını işlemez. + + + + {0} The generated source will not handle marshalling of the return value of method '{1}'. + {0} Oluşturulan kaynak, '{1}' metodunun dönüş değerinin sıralamasını işlemez. + {0} is a message containing additional details about what is not supported +{1} is the name of the method + + + Specified type is not supported by source-generated P/Invokes + Belirtilen tür, kaynak tarafından oluşturulan P/Invokes tarafından desteklenmiyor + + + + + \ No newline at end of file diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.zh-Hans.xlf b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.zh-Hans.xlf new file mode 100644 index 0000000000000..bf58dc9b6290a --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.zh-Hans.xlf @@ -0,0 +1,114 @@ + + + + + + Source-generated P/Invokes will ignore any configuration that is not supported. + 源生成的 P/Invoke 将忽略任何不受支持的配置。 + + + + The '{0}' configuration is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + 源生成的 P/Invoke 不支持“{0}”配置。如果需要指定的配置,请改用常规的 “DllImport”。 + + + + The specified marshalling configuration is not supported by source-generated P/Invokes. {0}. + 源生成的 P/Invoke 不支持指定的封送配置。{0}。 + + + + The specified '{0}' configuration for parameter '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + 源生成的 P/Invoke 不支持为参数“{1}”指定的“{0}”配置。如果需要指定的配置,请改用常规的 `DllImport`。 + + + + The specified '{0}' configuration for the return value of method '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + 源生成的 P/Invoke 不支持为方法“{1}”的返回值指定的“{0}”配置。如果需要指定的配置,请改用常规的 “DllImport”。 + + + + The specified value '{0}' for '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + 源生成的 P/Invoke 不支持为“{1}”指定的值“{0}”。如果需要指定的配置,请改用常规的 “DllImport”。 + + + + Specified configuration is not supported by source-generated P/Invokes. + 源生成的 P/Invoke 不支持指定的配置。 + + + + Method '{0}' is contained in a type '{1}' that is not marked 'partial'. P/Invoke source generation will ignore method '{0}'. + Method '{0}' is contained in a type '{1}' that is not marked 'partial'. P/Invoke source generation will ignore method '{0}'. + + + + Methods marked with 'LibraryImportAttribute' should be 'static', 'partial', and non-generic. P/Invoke source generation will ignore methods that are non-'static', non-'partial', or generic. + Methods marked with 'LibraryImportAttribute' should be 'static', 'partial', and non-generic. P/Invoke source generation will ignore methods that are non-'static', non-'partial', or generic. + + + + Method '{0}' should be 'static', 'partial', and non-generic when marked with 'LibraryImportAttribute'. P/Invoke source generation will ignore method '{0}'. + Method '{0}' should be 'static', 'partial', and non-generic when marked with 'LibraryImportAttribute'. P/Invoke source generation will ignore method '{0}'. + + + + Invalid 'LibraryImportAttribute' usage + Invalid 'LibraryImportAttribute' usage + + + + The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' is invalid. + “StringMarshalling” 和 “StringMarshallingCustomType” 的配置无效。 + + + + The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1} + 方法“{0}”上的 “StringMarshalling” 和 “StringMarshallingCustomType” 的配置无效。{1} + {1} is a message containing additional details about what is not valid + + + 'StringMarshallingCustomType' must be specified when 'StringMarshalling' is set to 'StringMarshalling.Custom'. + 在 “StringMarshalling” 设置为 “StringMarshalling.Custom” 时,必须指定 “StringMarshallingCustomType”。 + + + + 'StringMarshalling' should be set to 'StringMarshalling.Custom' when 'StringMarshallingCustomType' is specified. + 在指定 “StringMarshallingCustomType” 时,应将 “StringMarshalling” 设置为 “StringMarshalling.Custom”。 + + + + For types that are not supported by source-generated P/Invokes, the resulting P/Invoke will rely on the underlying runtime to marshal the specified type. + 对于源生成的 P/Invoke 不支持的类型,生成的 P/Invoke 将依赖基础运行时来封送指定的类型。 + + + + The type '{0}' is not supported by source-generated P/Invokes. The generated source will not handle marshalling of parameter '{1}'. + 源生成的 P/Invoke 不支持“{0}”类型。生成的源将不处理参数“{1}”的封送。 + + + + {0} The generated source will not handle marshalling of parameter '{1}'. + {0} 生成的源将不处理参数“{1}”的封送。 + {0} is a message containing additional details about what is not supported +{1} is the name of the parameter + + + The type '{0}' is not supported by source-generated P/Invokes. The generated source will not handle marshalling of the return value of method '{1}'. + 源生成的 P/Invoke 不支持“{0}”类型。生成的源将不处理方法“{1}”的返回值的封送。 + + + + {0} The generated source will not handle marshalling of the return value of method '{1}'. + {0} 生成的源将不处理方法“{1}”的返回值的封送。 + {0} is a message containing additional details about what is not supported +{1} is the name of the method + + + Specified type is not supported by source-generated P/Invokes + 源生成的 P/Invoke 不支持指定的类型 + + + + + \ No newline at end of file diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.zh-Hant.xlf b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.zh-Hant.xlf new file mode 100644 index 0000000000000..9060dc388da01 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Resources/xlf/Strings.zh-Hant.xlf @@ -0,0 +1,114 @@ + + + + + + Source-generated P/Invokes will ignore any configuration that is not supported. + 来源產生的 P/Invokes 將會忽略任何不支援的設定。 + + + + The '{0}' configuration is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + 来源產生的 P/Invokes 不支援為'{0}'設定。如果需要指定的設定,請改用一般 'DllImport'。 + + + + The specified marshalling configuration is not supported by source-generated P/Invokes. {0}. + 来源產生的 P/Invokes 不支援指定的排列設定。{0}。 + + + + The specified '{0}' configuration for parameter '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + 来源產生的 P/Invokes 不支援为参數 '{0}' 指定的'{1}'設定。如果需要指定的設定,請改用一般 'DllImport'。 + + + + The specified '{0}' configuration for the return value of method '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + 来源產生的 P/Invokes 不支援為方法 '{0}' 的傳回值指定的 '{1}' 設定。如果需要指定的設定,請改用一般 'DllImport'。 + + + + The specified value '{0}' for '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + 来源產生的 P/Invokes 不支援為'{0}'指定的值 '{1}'。如果需要指定的設定,請改用一般 'DllImport'。 + + + + Specified configuration is not supported by source-generated P/Invokes. + 来源產生的 P/Invokes 不支援指定的設定。 + + + + Method '{0}' is contained in a type '{1}' that is not marked 'partial'. P/Invoke source generation will ignore method '{0}'. + Method '{0}' is contained in a type '{1}' that is not marked 'partial'. P/Invoke source generation will ignore method '{0}'. + + + + Methods marked with 'LibraryImportAttribute' should be 'static', 'partial', and non-generic. P/Invoke source generation will ignore methods that are non-'static', non-'partial', or generic. + Methods marked with 'LibraryImportAttribute' should be 'static', 'partial', and non-generic. P/Invoke source generation will ignore methods that are non-'static', non-'partial', or generic. + + + + Method '{0}' should be 'static', 'partial', and non-generic when marked with 'LibraryImportAttribute'. P/Invoke source generation will ignore method '{0}'. + Method '{0}' should be 'static', 'partial', and non-generic when marked with 'LibraryImportAttribute'. P/Invoke source generation will ignore method '{0}'. + + + + Invalid 'LibraryImportAttribute' usage + Invalid 'LibraryImportAttribute' usage + + + + The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' is invalid. + 'StringMarshalling' 和 'StringMarshallingCustomType' 的設定無效。 + + + + The configuration of 'StringMarshalling' and 'StringMarshallingCustomType' on method '{0}' is invalid. {1} + 方法 '{0}' 上的 'StringMarshalling' 和 'StringMarshallingCustomType' 設定無效。{1} + {1} is a message containing additional details about what is not valid + + + 'StringMarshallingCustomType' must be specified when 'StringMarshalling' is set to 'StringMarshalling.Custom'. + 當 'StringMarshalling' 設定為 'StringMarshalling.Custom' 時,必須指定 'StringMarshallingCustomType'。 + + + + 'StringMarshalling' should be set to 'StringMarshalling.Custom' when 'StringMarshallingCustomType' is specified. + 指定 'StringMarshallingCustomType' 時,'StringMarshalling' 應設定為 'StringMarshalling.Custom'。 + + + + For types that are not supported by source-generated P/Invokes, the resulting P/Invoke will rely on the underlying runtime to marshal the specified type. + 對於來源產生的 P/Invokes 不支援的類型,產生的 P/Invoke 將依賴基礎運行時間來封送指定的類型。 + + + + The type '{0}' is not supported by source-generated P/Invokes. The generated source will not handle marshalling of parameter '{1}'. + 来源產生的 P/Invokes 不支援類型 '{0}'。產生的来源將不會處理參數 '{1}' 的排列。 + + + + {0} The generated source will not handle marshalling of parameter '{1}'. + {0} 產生的来源将不會處理參數 '{1}' 的排列。 + {0} is a message containing additional details about what is not supported +{1} is the name of the parameter + + + The type '{0}' is not supported by source-generated P/Invokes. The generated source will not handle marshalling of the return value of method '{1}'. + 来源產生的 P/Invokes 不支援類型 '{0}'。產生的來源將不會處理方法 '{1}' 的傳回值排列。 + + + + {0} The generated source will not handle marshalling of the return value of method '{1}'. + {0} 產生的來源將不會處理方法 '{1}' 之傳回值的排列。 + {0} is a message containing additional details about what is not supported +{1} is the name of the method + + + Specified type is not supported by source-generated P/Invokes + 来源產生的 P/Invokes 不支援指定的類型。 + + + + + \ No newline at end of file diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/UnreachableException.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/UnreachableException.cs new file mode 100644 index 0000000000000..ef9da5905e4b2 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/UnreachableException.cs @@ -0,0 +1,16 @@ +// 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; + +namespace Microsoft.Interop +{ + /// + /// An exception that should be thrown on code-paths that are unreachable. + /// + internal class UnreachableException : Exception + { + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VirtualMethodIndexData.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VirtualMethodIndexData.cs new file mode 100644 index 0000000000000..ea2567df3cf72 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VirtualMethodIndexData.cs @@ -0,0 +1,18 @@ +// 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.Runtime.InteropServices; +using Microsoft.CodeAnalysis; + +namespace Microsoft.Interop +{ + /// + /// VirtualMethodIndexAttribute data + /// + internal sealed record VirtualMethodIndexData : InteropAttributeData + { + public int Index { get; init; } + public bool ImplicitThisParameter { get; init; } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs new file mode 100644 index 0000000000000..de33113f62cfa --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs @@ -0,0 +1,415 @@ +// 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.Collections.Immutable; +using System.Diagnostics; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; + +[assembly: System.Resources.NeutralResourcesLanguage("en-US")] + +namespace Microsoft.Interop +{ + [Generator] + public sealed class VtableIndexStubGenerator : IIncrementalGenerator + { + internal sealed record IncrementalStubGenerationContext( + StubEnvironment Environment, + SignatureContext SignatureContext, + ContainingSyntaxContext ContainingSyntaxContext, + ImmutableArray CallingConvention, + VirtualMethodIndexData VtableIndexData, + IMarshallingGeneratorFactory GeneratorFactory, + ManagedTypeInfo TypeKeyType, + ManagedTypeInfo TypeKeyOwner, + ImmutableArray Diagnostics) + { + public bool Equals(IncrementalStubGenerationContext? other) + { + return other is not null + && StubEnvironment.AreCompilationSettingsEqual(Environment, other.Environment) + && SignatureContext.Equals(other.SignatureContext) + && ContainingSyntaxContext.Equals(other.ContainingSyntaxContext) + && VtableIndexData.Equals(other.VtableIndexData) + && CallingConvention.SequenceEqual(other.CallingConvention, (IEqualityComparer)SyntaxEquivalentComparer.Instance) + && Diagnostics.SequenceEqual(other.Diagnostics); + } + + public override int GetHashCode() + { + throw new UnreachableException(); + } + } + + public static class StepNames + { + public const string CalculateStubInformation = nameof(CalculateStubInformation); + public const string GenerateSingleStub = nameof(GenerateSingleStub); + } + + public void Initialize(IncrementalGeneratorInitializationContext context) + { + var attributedMethods = context.SyntaxProvider + .CreateSyntaxProvider( + static (node, ct) => ShouldVisitNode(node), + static (context, ct) => + { + MethodDeclarationSyntax syntax = (MethodDeclarationSyntax)context.Node; + if (context.SemanticModel.GetDeclaredSymbol(syntax, ct) is IMethodSymbol methodSymbol + && methodSymbol.GetAttributes().Any(static attribute => attribute.AttributeClass?.ToDisplayString() == TypeNames.LibraryImportAttribute)) + { + return new { Syntax = syntax, Symbol = methodSymbol }; + } + + return null; + }) + .Where( + static modelData => modelData is not null); + + var methodsWithDiagnostics = attributedMethods.Select(static (data, ct) => + { + Diagnostic? diagnostic = GetDiagnosticIfInvalidMethodForGeneration(data.Syntax, data.Symbol); + return new { Syntax = data.Syntax, Symbol = data.Symbol, Diagnostic = diagnostic }; + }); + + var methodsToGenerate = methodsWithDiagnostics.Where(static data => data.Diagnostic is null); + var invalidMethodDiagnostics = methodsWithDiagnostics.Where(static data => data.Diagnostic is not null); + + context.RegisterSourceOutput(invalidMethodDiagnostics, static (context, invalidMethod) => + { + context.ReportDiagnostic(invalidMethod.Diagnostic); + }); + + IncrementalValuesProvider<(MemberDeclarationSyntax, ImmutableArray)> generateSingleStub = methodsToGenerate + .Combine(context.CreateStubEnvironmentProvider()) + .Select(static (data, ct) => new + { + data.Left.Syntax, + data.Left.Symbol, + Environment = data.Right + }) + .Select( + static (data, ct) => (data.Syntax, StubContext: CalculateStubInformation(data.Syntax, data.Symbol, data.Environment, ct)) + ) + .WithComparer(Comparers.CalculatedContextWithSyntax) + .WithTrackingName(StepNames.CalculateStubInformation) + .Select( + static (data, ct) => GenerateSource(data.StubContext, data.Syntax) + ) + .WithComparer(Comparers.GeneratedSyntax) + .WithTrackingName(StepNames.GenerateSingleStub); + + context.RegisterDiagnostics(generateSingleStub.SelectMany((stubInfo, ct) => stubInfo.Item2)); + + context.RegisterConcatenatedSyntaxOutputs(generateSingleStub.Select((data, ct) => data.Item1), "LibraryImports.g.cs"); + } + + private static ImmutableArray GenerateCallConvSyntaxFromAttributes(AttributeData? suppressGCTransitionAttribute, AttributeData? unmanagedCallConvAttribute) + { + const string CallConvsField = "CallConvs"; + ImmutableArray.Builder callingConventions = ImmutableArray.CreateBuilder(); + + if (suppressGCTransitionAttribute is not null) + { + callingConventions.Add(FunctionPointerUnmanagedCallingConvention(Identifier("SuppressGCTransition"))); + } + if (unmanagedCallConvAttribute is not null) + { + foreach (KeyValuePair arg in unmanagedCallConvAttribute.NamedArguments) + { + if (arg.Key == CallConvsField) + { + foreach (TypedConstant callConv in arg.Value.Values) + { + ITypeSymbol callConvSymbol = (ITypeSymbol)callConv.Value!; + if (callConvSymbol.Name.StartsWith("CallConv")) + { + callingConventions.Add(FunctionPointerUnmanagedCallingConvention(Identifier(callConvSymbol.Name.Substring("CallConv".Length)))); + } + } + } + } + } + return callingConventions.ToImmutable(); + } + + private static SyntaxTokenList StripTriviaFromModifiers(SyntaxTokenList tokenList) + { + SyntaxToken[] strippedTokens = new SyntaxToken[tokenList.Count]; + for (int i = 0; i < tokenList.Count; i++) + { + strippedTokens[i] = tokenList[i].WithoutTrivia(); + } + return new SyntaxTokenList(strippedTokens); + } + + private static SyntaxTokenList AddToModifiers(SyntaxTokenList modifiers, SyntaxKind modifierToAdd) + { + if (modifiers.IndexOf(modifierToAdd) >= 0) + return modifiers; + + int idx = modifiers.IndexOf(SyntaxKind.PartialKeyword); + return idx >= 0 + ? modifiers.Insert(idx, Token(modifierToAdd)) + : modifiers.Add(Token(modifierToAdd)); + } + + private static TypeDeclarationSyntax CreateTypeDeclarationWithoutTrivia(TypeDeclarationSyntax typeDeclaration) + { + return TypeDeclaration( + typeDeclaration.Kind(), + typeDeclaration.Identifier) + .WithTypeParameterList(typeDeclaration.TypeParameterList) + .WithModifiers(StripTriviaFromModifiers(typeDeclaration.Modifiers)); + } + + + private static MemberDeclarationSyntax PrintGeneratedSource( + MethodDeclarationSyntax userDeclaredMethod, + SignatureContext stub, + BlockSyntax stubCode) + { + // Create stub function + return MethodDeclaration(stub.StubReturnType, userDeclaredMethod.Identifier) + .AddAttributeLists(stub.AdditionalAttributes.ToArray()) + .WithModifiers(StripTriviaFromModifiers(userDeclaredMethod.Modifiers)) + .WithParameterList(ParameterList(SeparatedList(stub.StubParameters))) + .WithBody(stubCode); + } + + private static TargetFramework DetermineTargetFramework(Compilation compilation, out Version version) + { + IAssemblySymbol systemAssembly = compilation.GetSpecialType(SpecialType.System_Object).ContainingAssembly; + version = systemAssembly.Identity.Version; + + return systemAssembly.Identity.Name switch + { + // .NET Framework + "mscorlib" => TargetFramework.Framework, + // .NET Standard + "netstandard" => TargetFramework.Standard, + // .NET Core (when version < 5.0) or .NET + "System.Runtime" or "System.Private.CoreLib" => + (version.Major < 5) ? TargetFramework.Core : TargetFramework.Net, + _ => TargetFramework.Unknown, + }; + } + + private static VirtualMethodIndexData? ProcessVirtualMethodIndexAttribute(AttributeData attrData) + { + // Found the LibraryImport, but it has an error so report the error. + // This is most likely an issue with targeting an incorrect TFM. + if (attrData.AttributeClass?.TypeKind is null or TypeKind.Error) + { + return null; + } + + var namedArguments = ImmutableDictionary.CreateRange(attrData.NamedArguments); + + var data = new VirtualMethodIndexData(); + + return data.WithValuesFromNamedArguments(namedArguments); + } + + private static IncrementalStubGenerationContext CalculateStubInformation(MethodDeclarationSyntax syntax, IMethodSymbol symbol, StubEnvironment environment, CancellationToken ct) + { + ct.ThrowIfCancellationRequested(); + INamedTypeSymbol? lcidConversionAttrType = environment.Compilation.GetTypeByMetadataName(TypeNames.LCIDConversionAttribute); + INamedTypeSymbol? suppressGCTransitionAttrType = environment.Compilation.GetTypeByMetadataName(TypeNames.SuppressGCTransitionAttribute); + INamedTypeSymbol? unmanagedCallConvAttrType = environment.Compilation.GetTypeByMetadataName(TypeNames.UnmanagedCallConvAttribute); + // Get any attributes of interest on the method + AttributeData? generatedDllImportAttr = null; + AttributeData? lcidConversionAttr = null; + AttributeData? suppressGCTransitionAttribute = null; + AttributeData? unmanagedCallConvAttribute = null; + foreach (AttributeData attr in symbol.GetAttributes()) + { + if (attr.AttributeClass is not null + && attr.AttributeClass.ToDisplayString() == TypeNames.LibraryImportAttribute) + { + generatedDllImportAttr = attr; + } + else if (lcidConversionAttrType is not null && SymbolEqualityComparer.Default.Equals(attr.AttributeClass, lcidConversionAttrType)) + { + lcidConversionAttr = attr; + } + else if (suppressGCTransitionAttrType is not null && SymbolEqualityComparer.Default.Equals(attr.AttributeClass, suppressGCTransitionAttrType)) + { + suppressGCTransitionAttribute = attr; + } + else if (unmanagedCallConvAttrType is not null && SymbolEqualityComparer.Default.Equals(attr.AttributeClass, unmanagedCallConvAttrType)) + { + unmanagedCallConvAttribute = attr; + } + } + + Debug.Assert(generatedDllImportAttr is not null); + + var generatorDiagnostics = new GeneratorDiagnostics(); + + // Process the LibraryImport attribute + VirtualMethodIndexData? virtualMethodIndexData = ProcessVirtualMethodIndexAttribute(generatedDllImportAttr!); + + if (virtualMethodIndexData is null) + { + generatorDiagnostics.ReportConfigurationNotSupported(generatedDllImportAttr!, "Invalid syntax"); + virtualMethodIndexData = new VirtualMethodIndexData(); + } + + if (virtualMethodIndexData.IsUserDefined.HasFlag(InteropAttributeMember.StringMarshalling)) + { + // User specified StringMarshalling.Custom without specifying StringMarshallingCustomType + if (virtualMethodIndexData.StringMarshalling == StringMarshalling.Custom && virtualMethodIndexData.StringMarshallingCustomType is null) + { + generatorDiagnostics.ReportInvalidStringMarshallingConfiguration( + generatedDllImportAttr, symbol.Name, SR.InvalidStringMarshallingConfigurationMissingCustomType); + } + + // User specified something other than StringMarshalling.Custom while specifying StringMarshallingCustomType + if (virtualMethodIndexData.StringMarshalling != StringMarshalling.Custom && virtualMethodIndexData.StringMarshallingCustomType is not null) + { + generatorDiagnostics.ReportInvalidStringMarshallingConfiguration( + generatedDllImportAttr, symbol.Name, SR.InvalidStringMarshallingConfigurationNotCustom); + } + } + + if (lcidConversionAttr is not null) + { + // Using LCIDConversion with LibraryImport is not supported + generatorDiagnostics.ReportConfigurationNotSupported(lcidConversionAttr, nameof(TypeNames.LCIDConversionAttribute)); + } + + // Create the stub. + var signatureContext = SignatureContext.Create(symbol, virtualMethodIndexData, environment, generatorDiagnostics, typeof(VtableIndexStubGenerator).Assembly); + + var containingSyntaxContext = new ContainingSyntaxContext(syntax); + + ImmutableArray callConv = GenerateCallConvSyntaxFromAttributes(suppressGCTransitionAttribute, unmanagedCallConvAttribute); + + var typeKeyOwner = ManagedTypeInfo.CreateTypeInfoForTypeSymbol(symbol.ContainingType); + ManagedTypeInfo typeKeyType = SpecialTypeInfo.Byte; + + var typeKeyField = symbol.ContainingType.GetMembers("TypeKey").OfType().FirstOrDefault(f => f.IsStatic); + if (typeKeyField is null) + { + // Report invalid configuration + } + else + { + typeKeyType = ManagedTypeInfo.CreateTypeInfoForTypeSymbol(typeKeyField.Type); + } + + return new IncrementalStubGenerationContext( + environment, + signatureContext, + containingSyntaxContext, + callConv, + virtualMethodIndexData, + GetMarshallingGeneratorFactory(environment), + typeKeyType, + typeKeyOwner, + generatorDiagnostics.Diagnostics.ToImmutableArray()); + } + + private static IMarshallingGeneratorFactory GetMarshallingGeneratorFactory(StubEnvironment env) + { + InteropGenerationOptions options = new(UseMarshalType: true); + IMarshallingGeneratorFactory generatorFactory; + + generatorFactory = new UnsupportedMarshallingFactory(); + + generatorFactory = new MarshalAsMarshallingGeneratorFactory(options, generatorFactory); + + IAssemblySymbol coreLibraryAssembly = env.Compilation.GetSpecialType(SpecialType.System_Object).ContainingAssembly; + ITypeSymbol? disabledRuntimeMarshallingAttributeType = coreLibraryAssembly.GetTypeByMetadataName(TypeNames.System_Runtime_CompilerServices_DisableRuntimeMarshallingAttribute); + bool runtimeMarshallingDisabled = disabledRuntimeMarshallingAttributeType is not null + && env.Compilation.Assembly.GetAttributes().Any(attr => SymbolEqualityComparer.Default.Equals(attr.AttributeClass, disabledRuntimeMarshallingAttributeType)); + + IMarshallingGeneratorFactory elementFactory = new AttributedMarshallingModelGeneratorFactory(generatorFactory, new AttributedMarshallingModelOptions(runtimeMarshallingDisabled)); + // We don't need to include the later generator factories for collection elements + // as the later generator factories only apply to parameters. + generatorFactory = new AttributedMarshallingModelGeneratorFactory(generatorFactory, elementFactory, new AttributedMarshallingModelOptions(runtimeMarshallingDisabled)); + + generatorFactory = new ByValueContentsMarshalKindValidator(generatorFactory); + return generatorFactory; + } + + private static (MemberDeclarationSyntax, ImmutableArray) GenerateSource( + IncrementalStubGenerationContext methodStub, + MethodDeclarationSyntax originalSyntax) + { + var diagnostics = new GeneratorDiagnostics(); + + // Generate stub code + var stubGenerator = new ManagedToNativeVTableMethodGenerator( + methodStub.Environment, + methodStub.SignatureContext.ElementTypeInformation, + methodStub.VtableIndexData.SetLastError, + methodStub.VtableIndexData.ImplicitThisParameter, + (elementInfo, ex) => + { + diagnostics.ReportMarshallingNotSupported(originalSyntax, elementInfo, ex.NotSupportedDetails); + }, + methodStub.GeneratorFactory); + + BlockSyntax code = stubGenerator.GenerateStubBody( + methodStub.VtableIndexData.Index, + methodStub.CallingConvention, + methodStub.TypeKeyOwner.Syntax, + methodStub.TypeKeyType); + + return (methodStub.ContainingSyntaxContext.WrapMemberInContainingSyntaxWithUnsafeModifier(PrintGeneratedSource(originalSyntax, methodStub.SignatureContext, code)), methodStub.Diagnostics.AddRange(diagnostics.Diagnostics)); + } + + private static bool ShouldVisitNode(SyntaxNode syntaxNode) + { + // We only support C# method declarations. + if (syntaxNode.Language != LanguageNames.CSharp + || !syntaxNode.IsKind(SyntaxKind.MethodDeclaration)) + { + return false; + } + + // Filter out methods with no attributes early. + return ((MethodDeclarationSyntax)syntaxNode).AttributeLists.Count > 0; + } + + private static Diagnostic? GetDiagnosticIfInvalidMethodForGeneration(MethodDeclarationSyntax methodSyntax, IMethodSymbol method) + { + // Verify the method has no generic types or defined implementation + // and is marked static and partial. + if (methodSyntax.TypeParameterList is not null + || methodSyntax.Body is not null + || !methodSyntax.Modifiers.Any(SyntaxKind.StaticKeyword) + || !methodSyntax.Modifiers.Any(SyntaxKind.PartialKeyword)) + { + return Diagnostic.Create(GeneratorDiagnostics.InvalidAttributedMethodSignature, methodSyntax.Identifier.GetLocation(), method.Name); + } + + // Verify that the types the method is declared in are marked partial. + for (SyntaxNode? parentNode = methodSyntax.Parent; parentNode is TypeDeclarationSyntax typeDecl; parentNode = parentNode.Parent) + { + if (!typeDecl.Modifiers.Any(SyntaxKind.PartialKeyword)) + { + return Diagnostic.Create(GeneratorDiagnostics.InvalidAttributedMethodContainingTypeMissingModifiers, methodSyntax.Identifier.GetLocation(), method.Name, typeDecl.Identifier); + } + } + + // Verify the method does not have a ref return + if (method.ReturnsByRef || method.ReturnsByRefReadonly) + { + return Diagnostic.Create(GeneratorDiagnostics.ReturnConfigurationNotSupported, methodSyntax.Identifier.GetLocation(), "ref return", method.ToDisplayString()); + } + + return null; + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManagedTypeInfo.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManagedTypeInfo.cs index dfb5278daacc0..e1c9fec695d9e 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManagedTypeInfo.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManagedTypeInfo.cs @@ -54,6 +54,7 @@ public sealed record SpecialTypeInfo(string FullTypeName, string DiagnosticForma public static readonly SpecialTypeInfo Byte = new("byte", "byte", SpecialType.System_Byte); public static readonly SpecialTypeInfo Int32 = new("int", "int", SpecialType.System_Int32); public static readonly SpecialTypeInfo Void = new("void", "void", SpecialType.System_Void); + public static readonly SpecialTypeInfo IntPtr = new("System.IntPtr", "System.IntPtr", SpecialType.System_IntPtr); public bool Equals(SpecialTypeInfo? other) { diff --git a/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/IUnmanagedVirtualMethodTableProvider.cs b/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/IUnmanagedVirtualMethodTableProvider.cs new file mode 100644 index 0000000000000..74634cd67e8fb --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/IUnmanagedVirtualMethodTableProvider.cs @@ -0,0 +1,117 @@ +// 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.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace System.Runtime.InteropServices +{ + public readonly ref struct VirtualMethodTableInfo + { + public VirtualMethodTableInfo(IntPtr thisPointer, ReadOnlySpan virtualMethodTable) + { + ThisPointer = thisPointer; + VirtualMethodTable = virtualMethodTable; + } + + public IntPtr ThisPointer { get; } + public ReadOnlySpan VirtualMethodTable { get; } + + public void Deconstruct(out IntPtr thisPointer, out ReadOnlySpan virtualMethodTable) + { + thisPointer = ThisPointer; + virtualMethodTable = VirtualMethodTable; + } + + public void Deconstruct(out ReadOnlySpan virtualMethodTable) + { + if (ThisPointer != IntPtr.Zero) + { + throw new InvalidOperationException(); + } + virtualMethodTable = VirtualMethodTable; + } + } + + public interface IUnmanagedVirtualMethodTableProvider where T : IEquatable + { + VirtualMethodTableInfo GetFunctionPointerForIndex(T typeKey); + } + + // Below here is scratch + /* + readonly record struct NoCasting { } + + //Example using IUnmanagedVirtualMethodTableProvider + public partial class MyWrapper : IUnmanagedVirtualMethodTableProvider, MyNativeAPI.Native + //public partial class MyWrapper : IUnmanagedVirtualMethodTableProvider, IDIC + { + public VirtualMethodTableInfo GetFunctionPointerForIndex(NoCasting type) => throw new NotImplementedException(); + } + + partial interface MyNativeAPI + { + public readonly static NoCasting TypeKey; + + [VirtualMethodIndex(0)] + void Foo(); + } + + // Generated: + partial interface MyNativeAPI + { + [DynamicInterfaceCastableImplementation] + internal interface Native : MyNativeAPI + { + unsafe void MyNativeAPI.Foo() + { + var (thisPtr, vtable) = ((IUnmanagedVirtualMethodTableProvider)this).GetFunctionPointerForIndex(MyNativeAPI.TypeKey); + + ((delegate* unmanaged)vtable[0])(); + } + } + } + + public abstract class GenericComWrappers : ComWrappers + where T: IComObjectWrapper + { + } + + public interface IComObjectWrapper + where T : IComObjectWrapper + { + static abstract T CreateFromIUnknown(IntPtr iUnknown); + } + + + public partial class M : GenericComWrappers + { } + + // Generated + public partial class M + { + protected override object? CreateObject(IntPtr externalComObject, CreateObjectFlags flags) => ComObject.CreateFromIUnknown(externalComObject); + } + + + public class ComObject : IUnmanagedVirtualMethodTableProvider, IDynamicInterfaceCastable, IComObjectWrapper + { + private IntPtr _iUnknown; + + private Dictionary _vtable; + + public static ComObject CreateFromIUnknown(IntPtr iUnknown) => new ComObject { _iUnknown = iUnknown }; + public virtual VirtualMethodTableInfo GetFunctionPointerForIndex(Type type) => QI; + public RuntimeTypeHandle GetInterfaceImplementation(RuntimeTypeHandle interfaceType) => throw new NotImplementedException(); + public bool IsInterfaceImplemented(RuntimeTypeHandle interfaceType, bool throwIfNotImplemented) => throw new NotImplementedException(); + } + + public class MyComObject : ComObject, IComObjectWrapper + { + public static new MyComObject CreateFromIUnknown(IntPtr iUnknown) => new MyComObject { _iUnknown = iUnknown }; + } + */ +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/VirtualMethodIndexAttribute.cs b/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/VirtualMethodIndexAttribute.cs new file mode 100644 index 0000000000000..7eb34b579081f --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/VirtualMethodIndexAttribute.cs @@ -0,0 +1,50 @@ +// 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.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace System.Runtime.InteropServices +{ + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] + internal class VirtualMethodIndexAttribute : Attribute + { + public VirtualMethodIndexAttribute(int index) + { + Index = index; + } + + public int Index { get; } + + public bool ImplicitThisParameter { get; init; } = true; + + public CustomTypeMarshallerDirection Direction { get; init; } = CustomTypeMarshallerDirection.Ref; + + /// + /// Gets or sets how to marshal string arguments to the method. + /// + /// + /// If this field is set to a value other than , + /// must not be specified. + /// + public StringMarshalling StringMarshalling { get; set; } + + /// + /// Gets or sets the used to control how string arguments to the method are marshalled. + /// + /// + /// If this field is specified, must not be specified + /// or must be set to . + /// + public Type? StringMarshallingCustomType { get; set; } + + /// + /// Gets or sets whether the callee sets an error (SetLastError on Windows or errno + /// on other platforms) before returning from the attributed method. + /// + public bool SetLastError { get; set; } + } +} From 4e23511d70e34aeba8facdb78f8ada0f90fc4d1f Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Wed, 13 Apr 2022 17:03:10 -0700 Subject: [PATCH 02/30] Fix up some names and actually parse the right attribute. --- .../VirtualMethodIndexData.cs | 2 +- .../VtableIndexStubGenerator.cs | 18 +++++++++--------- .../TypeNames.cs | 3 +++ .../IUnmanagedVirtualMethodTableProvider.cs | 9 --------- 4 files changed, 13 insertions(+), 19 deletions(-) diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VirtualMethodIndexData.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VirtualMethodIndexData.cs index ea2567df3cf72..65b12680caa9d 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VirtualMethodIndexData.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VirtualMethodIndexData.cs @@ -13,6 +13,6 @@ namespace Microsoft.Interop internal sealed record VirtualMethodIndexData : InteropAttributeData { public int Index { get; init; } - public bool ImplicitThisParameter { get; init; } + public bool ImplicitThisParameter { get; init; } = true; } } diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs index de33113f62cfa..3bd7fa9bd5ecb 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs @@ -226,16 +226,16 @@ private static IncrementalStubGenerationContext CalculateStubInformation(MethodD INamedTypeSymbol? suppressGCTransitionAttrType = environment.Compilation.GetTypeByMetadataName(TypeNames.SuppressGCTransitionAttribute); INamedTypeSymbol? unmanagedCallConvAttrType = environment.Compilation.GetTypeByMetadataName(TypeNames.UnmanagedCallConvAttribute); // Get any attributes of interest on the method - AttributeData? generatedDllImportAttr = null; + AttributeData? virtualMethodIndexAttr = null; AttributeData? lcidConversionAttr = null; AttributeData? suppressGCTransitionAttribute = null; AttributeData? unmanagedCallConvAttribute = null; foreach (AttributeData attr in symbol.GetAttributes()) { if (attr.AttributeClass is not null - && attr.AttributeClass.ToDisplayString() == TypeNames.LibraryImportAttribute) + && attr.AttributeClass.ToDisplayString() == TypeNames.VirtualMethodIndexAttribute) { - generatedDllImportAttr = attr; + virtualMethodIndexAttr = attr; } else if (lcidConversionAttrType is not null && SymbolEqualityComparer.Default.Equals(attr.AttributeClass, lcidConversionAttrType)) { @@ -251,16 +251,16 @@ private static IncrementalStubGenerationContext CalculateStubInformation(MethodD } } - Debug.Assert(generatedDllImportAttr is not null); + Debug.Assert(virtualMethodIndexAttr is not null); var generatorDiagnostics = new GeneratorDiagnostics(); // Process the LibraryImport attribute - VirtualMethodIndexData? virtualMethodIndexData = ProcessVirtualMethodIndexAttribute(generatedDllImportAttr!); + VirtualMethodIndexData? virtualMethodIndexData = ProcessVirtualMethodIndexAttribute(virtualMethodIndexAttr!); if (virtualMethodIndexData is null) { - generatorDiagnostics.ReportConfigurationNotSupported(generatedDllImportAttr!, "Invalid syntax"); + generatorDiagnostics.ReportConfigurationNotSupported(virtualMethodIndexAttr!, "Invalid syntax"); virtualMethodIndexData = new VirtualMethodIndexData(); } @@ -270,14 +270,14 @@ private static IncrementalStubGenerationContext CalculateStubInformation(MethodD if (virtualMethodIndexData.StringMarshalling == StringMarshalling.Custom && virtualMethodIndexData.StringMarshallingCustomType is null) { generatorDiagnostics.ReportInvalidStringMarshallingConfiguration( - generatedDllImportAttr, symbol.Name, SR.InvalidStringMarshallingConfigurationMissingCustomType); + virtualMethodIndexAttr, symbol.Name, SR.InvalidStringMarshallingConfigurationMissingCustomType); } // User specified something other than StringMarshalling.Custom while specifying StringMarshallingCustomType if (virtualMethodIndexData.StringMarshalling != StringMarshalling.Custom && virtualMethodIndexData.StringMarshallingCustomType is not null) { generatorDiagnostics.ReportInvalidStringMarshallingConfiguration( - generatedDllImportAttr, symbol.Name, SR.InvalidStringMarshallingConfigurationNotCustom); + virtualMethodIndexAttr, symbol.Name, SR.InvalidStringMarshallingConfigurationNotCustom); } } @@ -297,7 +297,7 @@ private static IncrementalStubGenerationContext CalculateStubInformation(MethodD var typeKeyOwner = ManagedTypeInfo.CreateTypeInfoForTypeSymbol(symbol.ContainingType); ManagedTypeInfo typeKeyType = SpecialTypeInfo.Byte; - var typeKeyField = symbol.ContainingType.GetMembers("TypeKey").OfType().FirstOrDefault(f => f.IsStatic); + IFieldSymbol? typeKeyField = symbol.ContainingType.GetMembers("TypeKey").OfType().FirstOrDefault(f => f.IsStatic); if (typeKeyField is null) { // Report invalid configuration diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeNames.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeNames.cs index 876dc649001f9..9e03be27dd28e 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeNames.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeNames.cs @@ -26,6 +26,9 @@ public static class TypeNames public const string SuppressGCTransitionAttribute = "System.Runtime.InteropServices.SuppressGCTransitionAttribute"; public const string UnmanagedCallConvAttribute = "System.Runtime.InteropServices.UnmanagedCallConvAttribute"; + + public const string VirtualMethodIndexAttribute = "System.Runtime.InteropServices.VirtualMethodIndexAttribute"; + public const string System_Span_Metadata = "System.Span`1"; public const string System_Span = "System.Span"; public const string System_ReadOnlySpan_Metadata = "System.ReadOnlySpan`1"; diff --git a/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/IUnmanagedVirtualMethodTableProvider.cs b/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/IUnmanagedVirtualMethodTableProvider.cs index 74634cd67e8fb..e19dcdbdd71ce 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/IUnmanagedVirtualMethodTableProvider.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/IUnmanagedVirtualMethodTableProvider.cs @@ -25,15 +25,6 @@ public void Deconstruct(out IntPtr thisPointer, out ReadOnlySpan virtual thisPointer = ThisPointer; virtualMethodTable = VirtualMethodTable; } - - public void Deconstruct(out ReadOnlySpan virtualMethodTable) - { - if (ThisPointer != IntPtr.Zero) - { - throw new InvalidOperationException(); - } - virtualMethodTable = VirtualMethodTable; - } } public interface IUnmanagedVirtualMethodTableProvider where T : IEquatable From 6b6020a7df8cc78ba3a47d3a3c5e0fc93304e9a7 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Thu, 14 Apr 2022 11:55:06 -0700 Subject: [PATCH 03/30] Update ComInterfaceGenerator to not pass syntax around --- .../GeneratorDiagnostics.cs | 13 ++-- .../ManagedToNativeVTableMethodGenerator.cs | 2 - .../VirtualMethodIndexData.cs | 4 +- .../VtableIndexStubGenerator.cs | 76 ++++++++++++++++--- .../MethodSignatureDiagnosticLocations.cs | 0 5 files changed, 74 insertions(+), 21 deletions(-) rename src/libraries/System.Runtime.InteropServices/gen/{LibraryImportGenerator => Microsoft.Interop.SourceGeneration}/MethodSignatureDiagnosticLocations.cs (100%) diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/GeneratorDiagnostics.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/GeneratorDiagnostics.cs index 6c8ba6b00f387..e4f8686445ec3 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/GeneratorDiagnostics.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/GeneratorDiagnostics.cs @@ -202,7 +202,7 @@ public void ReportConfigurationNotSupported( /// Type info for the parameter/return /// [Optional] Specific reason for lack of support public void ReportMarshallingNotSupported( - MethodDeclarationSyntax method, + MethodSignatureDiagnosticLocations method, TypePositionInfo info, string? notSupportedDetails) { @@ -211,15 +211,14 @@ public void ReportMarshallingNotSupported( if (info.IsManagedReturnPosition) { - diagnosticLocation = Location.Create(method.SyntaxTree, method.Identifier.Span); - elementName = method.Identifier.ValueText; + diagnosticLocation = method.FallbackLocation; + elementName = method.MethodIdentifier; } else { - Debug.Assert(info.ManagedIndex <= method.ParameterList.Parameters.Count); - ParameterSyntax param = method.ParameterList.Parameters[info.ManagedIndex]; - diagnosticLocation = Location.Create(param.SyntaxTree, param.Identifier.Span); - elementName = param.Identifier.ValueText; + Debug.Assert(info.ManagedIndex <= method.ManagedParameterLocations.Length); + diagnosticLocation = method.ManagedParameterLocations[info.ManagedIndex]; + elementName = info.InstanceIdentifier; } if (!string.IsNullOrEmpty(notSupportedDetails)) diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedToNativeVTableMethodGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedToNativeVTableMethodGenerator.cs index 38315777bef2b..c45a4630d4c8a 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedToNativeVTableMethodGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedToNativeVTableMethodGenerator.cs @@ -38,7 +38,6 @@ internal sealed class ManagedToNativeVTableMethodGenerator // Error code representing success. This maps to S_OK for Windows HRESULT semantics and 0 for POSIX errno semantics. private const int SuccessErrorCode = 0; private readonly bool _setLastError; - private readonly bool _implicitThis; private readonly BoundGenerators _marshallers; private readonly ManagedToNativeStubCodeContext _context; @@ -52,7 +51,6 @@ public ManagedToNativeVTableMethodGenerator( IMarshallingGeneratorFactory generatorFactory) { _setLastError = setLastError; - _implicitThis = implicitThis; if (implicitThis) { ImmutableArray.Builder newArgTypes = ImmutableArray.CreateBuilder(argTypes.Length + 1); diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VirtualMethodIndexData.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VirtualMethodIndexData.cs index 65b12680caa9d..8067044addad8 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VirtualMethodIndexData.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VirtualMethodIndexData.cs @@ -13,6 +13,8 @@ namespace Microsoft.Interop internal sealed record VirtualMethodIndexData : InteropAttributeData { public int Index { get; init; } - public bool ImplicitThisParameter { get; init; } = true; + public bool ImplicitThisParameter { get; init; } + + public CustomTypeMarshallerDirection Direction { get; init; } } } diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs index 3bd7fa9bd5ecb..de2033e86f089 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs @@ -25,6 +25,8 @@ internal sealed record IncrementalStubGenerationContext( StubEnvironment Environment, SignatureContext SignatureContext, ContainingSyntaxContext ContainingSyntaxContext, + ContainingSyntax StubMethodSyntaxTemplate, + MethodSignatureDiagnosticLocations DiagnosticLocation, ImmutableArray CallingConvention, VirtualMethodIndexData VtableIndexData, IMarshallingGeneratorFactory GeneratorFactory, @@ -97,12 +99,11 @@ public void Initialize(IncrementalGeneratorInitializationContext context) Environment = data.Right }) .Select( - static (data, ct) => (data.Syntax, StubContext: CalculateStubInformation(data.Syntax, data.Symbol, data.Environment, ct)) + static (data, ct) => CalculateStubInformation(data.Syntax, data.Symbol, data.Environment, ct) ) - .WithComparer(Comparers.CalculatedContextWithSyntax) .WithTrackingName(StepNames.CalculateStubInformation) .Select( - static (data, ct) => GenerateSource(data.StubContext, data.Syntax) + static (data, ct) => GenerateSource(data) ) .WithComparer(Comparers.GeneratedSyntax) .WithTrackingName(StepNames.GenerateSingleStub); @@ -173,7 +174,7 @@ private static TypeDeclarationSyntax CreateTypeDeclarationWithoutTrivia(TypeDecl private static MemberDeclarationSyntax PrintGeneratedSource( - MethodDeclarationSyntax userDeclaredMethod, + ContainingSyntax userDeclaredMethod, SignatureContext stub, BlockSyntax stubCode) { @@ -216,7 +217,42 @@ private static TargetFramework DetermineTargetFramework(Compilation compilation, var data = new VirtualMethodIndexData(); - return data.WithValuesFromNamedArguments(namedArguments); + CustomTypeMarshallerDirection direction = CustomTypeMarshallerDirection.Ref; + int index = -1; + bool implicitThis = true; + if (namedArguments.TryGetValue(nameof(VirtualMethodIndexData.Direction), out TypedConstant directionValue)) + { + // TypedConstant's Value property only contains primitive values. + if (directionValue.Value is not int) + { + return null; + } + // A boxed primitive can be unboxed to an enum with the same underlying type. + direction = (CustomTypeMarshallerDirection)directionValue.Value!; + } + if (namedArguments.TryGetValue(nameof(VirtualMethodIndexData.Index), out TypedConstant indexValue)) + { + if (directionValue.Value is not int) + { + return null; + } + index = (int)indexValue.Value!; + } + if (namedArguments.TryGetValue(nameof(VirtualMethodIndexData.ImplicitThisParameter), out TypedConstant implicitThisValue)) + { + if (directionValue.Value is not bool) + { + return null; + } + implicitThis = (bool)implicitThisValue.Value!; + } + + return data.WithValuesFromNamedArguments(namedArguments) with + { + Direction = direction, + Index = index, + ImplicitThisParameter = implicitThis + }; } private static IncrementalStubGenerationContext CalculateStubInformation(MethodDeclarationSyntax syntax, IMethodSymbol symbol, StubEnvironment environment, CancellationToken ct) @@ -281,16 +317,33 @@ private static IncrementalStubGenerationContext CalculateStubInformation(MethodD } } + if (virtualMethodIndexData.Index < 0) + { + // Report missing or invalid index + } + + if (!virtualMethodIndexData.ImplicitThisParameter && virtualMethodIndexData.Direction.HasFlag(CustomTypeMarshallerDirection.Out)) + { + // Report invalid configuration + } + if (lcidConversionAttr is not null) { - // Using LCIDConversion with LibraryImport is not supported + // Using LCIDConversion with source-generated interop is not supported generatorDiagnostics.ReportConfigurationNotSupported(lcidConversionAttr, nameof(TypeNames.LCIDConversionAttribute)); } // Create the stub. var signatureContext = SignatureContext.Create(symbol, virtualMethodIndexData, environment, generatorDiagnostics, typeof(VtableIndexStubGenerator).Assembly); - var containingSyntaxContext = new ContainingSyntaxContext(syntax); + var containingSyntaxContext = new ContainingSyntaxContext(syntax) + .AddContainingSyntax( + new ContainingSyntax( + TokenList(Token(SyntaxKind.PartialKeyword)), + SyntaxKind.InterfaceDeclaration, + Identifier("Native"), + null)); + var methodSyntaxTemplate = new ContainingSyntax(syntax.Modifiers.StripTriviaFromTokens(), SyntaxKind.MethodDeclaration, syntax.Identifier, syntax.TypeParameterList); ImmutableArray callConv = GenerateCallConvSyntaxFromAttributes(suppressGCTransitionAttribute, unmanagedCallConvAttribute); @@ -311,6 +364,8 @@ private static IncrementalStubGenerationContext CalculateStubInformation(MethodD environment, signatureContext, containingSyntaxContext, + methodSyntaxTemplate, + new MethodSignatureDiagnosticLocations(syntax), callConv, virtualMethodIndexData, GetMarshallingGeneratorFactory(environment), @@ -343,8 +398,7 @@ private static IMarshallingGeneratorFactory GetMarshallingGeneratorFactory(StubE } private static (MemberDeclarationSyntax, ImmutableArray) GenerateSource( - IncrementalStubGenerationContext methodStub, - MethodDeclarationSyntax originalSyntax) + IncrementalStubGenerationContext methodStub) { var diagnostics = new GeneratorDiagnostics(); @@ -356,7 +410,7 @@ private static (MemberDeclarationSyntax, ImmutableArray) GenerateSou methodStub.VtableIndexData.ImplicitThisParameter, (elementInfo, ex) => { - diagnostics.ReportMarshallingNotSupported(originalSyntax, elementInfo, ex.NotSupportedDetails); + diagnostics.ReportMarshallingNotSupported(methodStub.DiagnosticLocation, elementInfo, ex.NotSupportedDetails); }, methodStub.GeneratorFactory); @@ -366,7 +420,7 @@ private static (MemberDeclarationSyntax, ImmutableArray) GenerateSou methodStub.TypeKeyOwner.Syntax, methodStub.TypeKeyType); - return (methodStub.ContainingSyntaxContext.WrapMemberInContainingSyntaxWithUnsafeModifier(PrintGeneratedSource(originalSyntax, methodStub.SignatureContext, code)), methodStub.Diagnostics.AddRange(diagnostics.Diagnostics)); + return (methodStub.ContainingSyntaxContext.WrapMemberInContainingSyntaxWithUnsafeModifier(PrintGeneratedSource(methodStub.StubMethodSyntaxTemplate, methodStub.SignatureContext, code)), methodStub.Diagnostics.AddRange(diagnostics.Diagnostics)); } private static bool ShouldVisitNode(SyntaxNode syntaxNode) diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/MethodSignatureDiagnosticLocations.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/MethodSignatureDiagnosticLocations.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/MethodSignatureDiagnosticLocations.cs rename to src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/MethodSignatureDiagnosticLocations.cs From ac354c61da2fb346c88c1bb01b7d64be3dfdf886 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Mon, 18 Apr 2022 17:21:53 -0700 Subject: [PATCH 04/30] Move TestUtils to a shared location and get our first test unit test with the vtable index generator to pass. --- .../System.Runtime.InteropServices.sln | 21 ++++ .../ManagedToNativeVTableMethodGenerator.cs | 2 +- .../VirtualMethodIndexData.cs | 3 +- .../VtableIndexStubGenerator.cs | 111 +++++++++--------- .../ContainingSyntaxContext.cs | 5 +- .../TypeNames.cs | 4 + .../VirtualMethodIndexAttribute.cs | 2 +- .../CodeSnippets.cs | 33 ++++++ .../ComInterfaceGenerator.Unit.Tests.csproj | 36 ++++++ .../Compiles.cs | 34 ++++++ .../Directory.Build.props | 7 ++ .../TestUtils.cs | 2 +- .../AdditionalAttributesOnStub.cs | 1 + .../AttributeForwarding.cs | 1 + .../CompileFails.cs | 1 + .../Compiles.cs | 1 + .../Diagnostics.cs | 1 + .../IncrementalGenerationTests.cs | 1 + .../LibraryImportGenerator.Unit.Tests.csproj | 2 + .../Verifiers/CSharpCodeFixVerifier.cs | 1 + 20 files changed, 206 insertions(+), 63 deletions(-) create mode 100644 src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CodeSnippets.cs create mode 100644 src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/ComInterfaceGenerator.Unit.Tests.csproj create mode 100644 src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/Compiles.cs create mode 100644 src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/Directory.Build.props rename src/libraries/System.Runtime.InteropServices/tests/{LibraryImportGenerator.UnitTests => Common}/TestUtils.cs (99%) diff --git a/src/libraries/System.Runtime.InteropServices/System.Runtime.InteropServices.sln b/src/libraries/System.Runtime.InteropServices/System.Runtime.InteropServices.sln index fd72e92df6b20..8654ddf2b35e1 100644 --- a/src/libraries/System.Runtime.InteropServices/System.Runtime.InteropServices.sln +++ b/src/libraries/System.Runtime.InteropServices/System.Runtime.InteropServices.sln @@ -40,6 +40,8 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "gen", "gen", "{E1AEBD5D-AE4E-4F61-B9ED-AEF950B0CC33}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ComInterfaceGenerator", "gen\ComInterfaceGenerator\ComInterfaceGenerator.csproj", "{C3EA0A28-A597-4946-9E08-EBBBFA94BFA5}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ComInterfaceGenerator.Unit.Tests", "tests\ComInterfaceGenerator.Unit.Tests\ComInterfaceGenerator.Unit.Tests.csproj", "{1D771995-D475-429B-AC31-2B1F618AA45F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -359,6 +361,24 @@ Global {C3EA0A28-A597-4946-9E08-EBBBFA94BFA5}.Release|x64.Build.0 = Release|Any CPU {C3EA0A28-A597-4946-9E08-EBBBFA94BFA5}.Release|x86.ActiveCfg = Release|Any CPU {C3EA0A28-A597-4946-9E08-EBBBFA94BFA5}.Release|x86.Build.0 = Release|Any CPU + {1D771995-D475-429B-AC31-2B1F618AA45F}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {1D771995-D475-429B-AC31-2B1F618AA45F}.Checked|Any CPU.Build.0 = Debug|Any CPU + {1D771995-D475-429B-AC31-2B1F618AA45F}.Checked|x64.ActiveCfg = Debug|Any CPU + {1D771995-D475-429B-AC31-2B1F618AA45F}.Checked|x64.Build.0 = Debug|Any CPU + {1D771995-D475-429B-AC31-2B1F618AA45F}.Checked|x86.ActiveCfg = Debug|Any CPU + {1D771995-D475-429B-AC31-2B1F618AA45F}.Checked|x86.Build.0 = Debug|Any CPU + {1D771995-D475-429B-AC31-2B1F618AA45F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1D771995-D475-429B-AC31-2B1F618AA45F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1D771995-D475-429B-AC31-2B1F618AA45F}.Debug|x64.ActiveCfg = Debug|Any CPU + {1D771995-D475-429B-AC31-2B1F618AA45F}.Debug|x64.Build.0 = Debug|Any CPU + {1D771995-D475-429B-AC31-2B1F618AA45F}.Debug|x86.ActiveCfg = Debug|Any CPU + {1D771995-D475-429B-AC31-2B1F618AA45F}.Debug|x86.Build.0 = Debug|Any CPU + {1D771995-D475-429B-AC31-2B1F618AA45F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1D771995-D475-429B-AC31-2B1F618AA45F}.Release|Any CPU.Build.0 = Release|Any CPU + {1D771995-D475-429B-AC31-2B1F618AA45F}.Release|x64.ActiveCfg = Release|Any CPU + {1D771995-D475-429B-AC31-2B1F618AA45F}.Release|x64.Build.0 = Release|Any CPU + {1D771995-D475-429B-AC31-2B1F618AA45F}.Release|x86.ActiveCfg = Release|Any CPU + {1D771995-D475-429B-AC31-2B1F618AA45F}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -381,6 +401,7 @@ Global {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40} = {E1AEBD5D-AE4E-4F61-B9ED-AEF950B0CC33} {768B77B0-EA45-469D-B39E-545EB72F5A43} = {E1AEBD5D-AE4E-4F61-B9ED-AEF950B0CC33} {C3EA0A28-A597-4946-9E08-EBBBFA94BFA5} = {E1AEBD5D-AE4E-4F61-B9ED-AEF950B0CC33} + {1D771995-D475-429B-AC31-2B1F618AA45F} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {D4031401-FEB5-4CCF-91C1-38F5646B2BFD} diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedToNativeVTableMethodGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedToNativeVTableMethodGenerator.cs index c45a4630d4c8a..d374a5b04c6c1 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedToNativeVTableMethodGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedToNativeVTableMethodGenerator.cs @@ -136,7 +136,7 @@ public BlockSyntax GenerateStubBody(int index, ImmutableArray /// VirtualMethodIndexAttribute data /// - internal sealed record VirtualMethodIndexData : InteropAttributeData + internal sealed record VirtualMethodIndexData(int Index) : InteropAttributeData { - public int Index { get; init; } public bool ImplicitThisParameter { get; init; } public CustomTypeMarshallerDirection Direction { get; init; } diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs index de2033e86f089..01a8f816fc001 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs @@ -54,7 +54,7 @@ public override int GetHashCode() public static class StepNames { public const string CalculateStubInformation = nameof(CalculateStubInformation); - public const string GenerateSingleStub = nameof(GenerateSingleStub); + public const string GenerateManagedToNativeStub = nameof(GenerateManagedToNativeStub); } public void Initialize(IncrementalGeneratorInitializationContext context) @@ -66,7 +66,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) { MethodDeclarationSyntax syntax = (MethodDeclarationSyntax)context.Node; if (context.SemanticModel.GetDeclaredSymbol(syntax, ct) is IMethodSymbol methodSymbol - && methodSymbol.GetAttributes().Any(static attribute => attribute.AttributeClass?.ToDisplayString() == TypeNames.LibraryImportAttribute)) + && methodSymbol.GetAttributes().Any(static attribute => attribute.AttributeClass?.ToDisplayString() == TypeNames.VirtualMethodIndexAttribute)) { return new { Syntax = syntax, Symbol = methodSymbol }; } @@ -90,7 +90,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) context.ReportDiagnostic(invalidMethod.Diagnostic); }); - IncrementalValuesProvider<(MemberDeclarationSyntax, ImmutableArray)> generateSingleStub = methodsToGenerate + IncrementalValuesProvider generateStubInformation = methodsToGenerate .Combine(context.CreateStubEnvironmentProvider()) .Select(static (data, ct) => new { @@ -101,16 +101,26 @@ public void Initialize(IncrementalGeneratorInitializationContext context) .Select( static (data, ct) => CalculateStubInformation(data.Syntax, data.Symbol, data.Environment, ct) ) - .WithTrackingName(StepNames.CalculateStubInformation) + .WithTrackingName(StepNames.CalculateStubInformation); + + IncrementalValuesProvider<(MemberDeclarationSyntax, ImmutableArray)> generateSingleStub = generateStubInformation .Select( - static (data, ct) => GenerateSource(data) + static (data, ct) => GenerateManagedToNativeStub(data) ) .WithComparer(Comparers.GeneratedSyntax) - .WithTrackingName(StepNames.GenerateSingleStub); + .WithTrackingName(StepNames.GenerateManagedToNativeStub); context.RegisterDiagnostics(generateSingleStub.SelectMany((stubInfo, ct) => stubInfo.Item2)); - context.RegisterConcatenatedSyntaxOutputs(generateSingleStub.Select((data, ct) => data.Item1), "LibraryImports.g.cs"); + context.RegisterConcatenatedSyntaxOutputs(generateSingleStub.Select((data, ct) => data.Item1), "ManagedToNativeStubs.g.cs"); + + IncrementalValuesProvider generateNativeInterface = generateStubInformation + .Select(static (context, ct) => context.ContainingSyntaxContext) + .Collect() + .SelectMany(static (syntaxContexts, ct) => syntaxContexts.Distinct()) + .Select(static (context, ct) => GenerateNativeInterfaceMetadata(context)); + + context.RegisterConcatenatedSyntaxOutputs(generateNativeInterface, "NativeInterfaces.g.cs"); } private static ImmutableArray GenerateCallConvSyntaxFromAttributes(AttributeData? suppressGCTransitionAttribute, AttributeData? unmanagedCallConvAttribute) @@ -131,7 +141,7 @@ private static ImmutableArray G foreach (TypedConstant callConv in arg.Value.Values) { ITypeSymbol callConvSymbol = (ITypeSymbol)callConv.Value!; - if (callConvSymbol.Name.StartsWith("CallConv")) + if (callConvSymbol.Name.StartsWith("CallConv", StringComparison.Ordinal)) { callingConventions.Add(FunctionPointerUnmanagedCallingConvention(Identifier(callConvSymbol.Name.Substring("CallConv".Length)))); } @@ -152,34 +162,15 @@ private static SyntaxTokenList StripTriviaFromModifiers(SyntaxTokenList tokenLis return new SyntaxTokenList(strippedTokens); } - private static SyntaxTokenList AddToModifiers(SyntaxTokenList modifiers, SyntaxKind modifierToAdd) - { - if (modifiers.IndexOf(modifierToAdd) >= 0) - return modifiers; - - int idx = modifiers.IndexOf(SyntaxKind.PartialKeyword); - return idx >= 0 - ? modifiers.Insert(idx, Token(modifierToAdd)) - : modifiers.Add(Token(modifierToAdd)); - } - - private static TypeDeclarationSyntax CreateTypeDeclarationWithoutTrivia(TypeDeclarationSyntax typeDeclaration) - { - return TypeDeclaration( - typeDeclaration.Kind(), - typeDeclaration.Identifier) - .WithTypeParameterList(typeDeclaration.TypeParameterList) - .WithModifiers(StripTriviaFromModifiers(typeDeclaration.Modifiers)); - } - - private static MemberDeclarationSyntax PrintGeneratedSource( ContainingSyntax userDeclaredMethod, + ContainingSyntax originalInterfaceType, SignatureContext stub, BlockSyntax stubCode) { // Create stub function return MethodDeclaration(stub.StubReturnType, userDeclaredMethod.Identifier) + .WithExplicitInterfaceSpecifier(ExplicitInterfaceSpecifier(IdentifierName(originalInterfaceType.Identifier))) .AddAttributeLists(stub.AdditionalAttributes.ToArray()) .WithModifiers(StripTriviaFromModifiers(userDeclaredMethod.Modifiers)) .WithParameterList(ParameterList(SeparatedList(stub.StubParameters))) @@ -206,7 +197,7 @@ private static TargetFramework DetermineTargetFramework(Compilation compilation, private static VirtualMethodIndexData? ProcessVirtualMethodIndexAttribute(AttributeData attrData) { - // Found the LibraryImport, but it has an error so report the error. + // Found the attribute, but it has an error so report the error. // This is most likely an issue with targeting an incorrect TFM. if (attrData.AttributeClass?.TypeKind is null or TypeKind.Error) { @@ -215,10 +206,12 @@ private static TargetFramework DetermineTargetFramework(Compilation compilation, var namedArguments = ImmutableDictionary.CreateRange(attrData.NamedArguments); - var data = new VirtualMethodIndexData(); + if (attrData.ConstructorArguments.Length == 0 || attrData.ConstructorArguments[0].Value is not int) + { + return null; + } CustomTypeMarshallerDirection direction = CustomTypeMarshallerDirection.Ref; - int index = -1; bool implicitThis = true; if (namedArguments.TryGetValue(nameof(VirtualMethodIndexData.Direction), out TypedConstant directionValue)) { @@ -230,14 +223,6 @@ private static TargetFramework DetermineTargetFramework(Compilation compilation, // A boxed primitive can be unboxed to an enum with the same underlying type. direction = (CustomTypeMarshallerDirection)directionValue.Value!; } - if (namedArguments.TryGetValue(nameof(VirtualMethodIndexData.Index), out TypedConstant indexValue)) - { - if (directionValue.Value is not int) - { - return null; - } - index = (int)indexValue.Value!; - } if (namedArguments.TryGetValue(nameof(VirtualMethodIndexData.ImplicitThisParameter), out TypedConstant implicitThisValue)) { if (directionValue.Value is not bool) @@ -247,10 +232,9 @@ private static TargetFramework DetermineTargetFramework(Compilation compilation, implicitThis = (bool)implicitThisValue.Value!; } - return data.WithValuesFromNamedArguments(namedArguments) with + return new VirtualMethodIndexData((int)attrData.ConstructorArguments[0].Value).WithValuesFromNamedArguments(namedArguments) with { Direction = direction, - Index = index, ImplicitThisParameter = implicitThis }; } @@ -297,7 +281,7 @@ private static IncrementalStubGenerationContext CalculateStubInformation(MethodD if (virtualMethodIndexData is null) { generatorDiagnostics.ReportConfigurationNotSupported(virtualMethodIndexAttr!, "Invalid syntax"); - virtualMethodIndexData = new VirtualMethodIndexData(); + virtualMethodIndexData = new VirtualMethodIndexData(-1); } if (virtualMethodIndexData.IsUserDefined.HasFlag(InteropAttributeMember.StringMarshalling)) @@ -336,13 +320,8 @@ private static IncrementalStubGenerationContext CalculateStubInformation(MethodD // Create the stub. var signatureContext = SignatureContext.Create(symbol, virtualMethodIndexData, environment, generatorDiagnostics, typeof(VtableIndexStubGenerator).Assembly); - var containingSyntaxContext = new ContainingSyntaxContext(syntax) - .AddContainingSyntax( - new ContainingSyntax( - TokenList(Token(SyntaxKind.PartialKeyword)), - SyntaxKind.InterfaceDeclaration, - Identifier("Native"), - null)); + var containingSyntaxContext = new ContainingSyntaxContext(syntax); + var methodSyntaxTemplate = new ContainingSyntax(syntax.Modifiers.StripTriviaFromTokens(), SyntaxKind.MethodDeclaration, syntax.Identifier, syntax.TypeParameterList); ImmutableArray callConv = GenerateCallConvSyntaxFromAttributes(suppressGCTransitionAttribute, unmanagedCallConvAttribute); @@ -397,7 +376,7 @@ private static IMarshallingGeneratorFactory GetMarshallingGeneratorFactory(StubE return generatorFactory; } - private static (MemberDeclarationSyntax, ImmutableArray) GenerateSource( + private static (MemberDeclarationSyntax, ImmutableArray) GenerateManagedToNativeStub( IncrementalStubGenerationContext methodStub) { var diagnostics = new GeneratorDiagnostics(); @@ -420,7 +399,20 @@ private static (MemberDeclarationSyntax, ImmutableArray) GenerateSou methodStub.TypeKeyOwner.Syntax, methodStub.TypeKeyType); - return (methodStub.ContainingSyntaxContext.WrapMemberInContainingSyntaxWithUnsafeModifier(PrintGeneratedSource(methodStub.StubMethodSyntaxTemplate, methodStub.SignatureContext, code)), methodStub.Diagnostics.AddRange(diagnostics.Diagnostics)); + return ( + methodStub.ContainingSyntaxContext.AddContainingSyntax( + new ContainingSyntax( + TokenList(Token(SyntaxKind.InternalKeyword), Token(SyntaxKind.PartialKeyword)), + SyntaxKind.InterfaceDeclaration, + Identifier("Native"), + null)) + .WrapMemberInContainingSyntaxWithUnsafeModifier( + PrintGeneratedSource( + methodStub.StubMethodSyntaxTemplate, + methodStub.ContainingSyntaxContext.ContainingSyntax[0], + methodStub.SignatureContext, + code)), + methodStub.Diagnostics.AddRange(diagnostics.Diagnostics)); } private static bool ShouldVisitNode(SyntaxNode syntaxNode) @@ -439,11 +431,11 @@ private static bool ShouldVisitNode(SyntaxNode syntaxNode) private static Diagnostic? GetDiagnosticIfInvalidMethodForGeneration(MethodDeclarationSyntax methodSyntax, IMethodSymbol method) { // Verify the method has no generic types or defined implementation - // and is marked static and partial. + // and is not marked static or sealed if (methodSyntax.TypeParameterList is not null || methodSyntax.Body is not null - || !methodSyntax.Modifiers.Any(SyntaxKind.StaticKeyword) - || !methodSyntax.Modifiers.Any(SyntaxKind.PartialKeyword)) + || methodSyntax.Modifiers.Any(SyntaxKind.StaticKeyword) + || methodSyntax.Modifiers.Any(SyntaxKind.SealedKeyword)) { return Diagnostic.Create(GeneratorDiagnostics.InvalidAttributedMethodSignature, methodSyntax.Identifier.GetLocation(), method.Name); } @@ -465,5 +457,14 @@ private static bool ShouldVisitNode(SyntaxNode syntaxNode) return null; } + + private static MemberDeclarationSyntax GenerateNativeInterfaceMetadata(ContainingSyntaxContext context) + { + return context.WrapMemberInContainingSyntaxWithUnsafeModifier( + InterfaceDeclaration("Native") + .WithModifiers(TokenList(Token(SyntaxKind.InternalKeyword), Token(SyntaxKind.PartialKeyword))) + .WithBaseList(BaseList(SingletonSeparatedList((BaseTypeSyntax)SimpleBaseType(IdentifierName(context.ContainingSyntax[0].Identifier))))) + .AddAttributeLists(AttributeList(SingletonSeparatedList(Attribute(ParseName(TypeNames.System_Runtime_InteropServices_DynamicInterfaceCastableImplementationAttribute)))))); + } } } diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ContainingSyntaxContext.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ContainingSyntaxContext.cs index 579dc15739bbf..9d194c9b250fd 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ContainingSyntaxContext.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ContainingSyntaxContext.cs @@ -34,7 +34,7 @@ public ContainingSyntaxContext(MemberDeclarationSyntax memberDeclaration) public ContainingSyntaxContext AddContainingSyntax(ContainingSyntax nestedType) { - return this with { ContainingSyntax = ContainingSyntax.Add(nestedType) }; + return this with { ContainingSyntax = ContainingSyntax.Insert(0, nestedType) }; } private static ImmutableArray GetContainingTypes(MemberDeclarationSyntax memberDeclaration) @@ -42,7 +42,6 @@ private static ImmutableArray GetContainingTypes(MemberDeclara ImmutableArray.Builder containingTypeInfoBuilder = ImmutableArray.CreateBuilder(); for (SyntaxNode? parent = memberDeclaration.Parent; parent is TypeDeclarationSyntax typeDeclaration; parent = parent.Parent) { - containingTypeInfoBuilder.Add(new ContainingSyntax(typeDeclaration.Modifiers.StripTriviaFromTokens(), typeDeclaration.Kind(), typeDeclaration.Identifier.WithoutTrivia(), typeDeclaration.TypeParameterList)); } @@ -75,7 +74,7 @@ public bool Equals(ContainingSyntaxContext other) && ContainingNamespace == other.ContainingNamespace; } - public override int GetHashCode() => throw new UnreachableException(); + public override int GetHashCode() => (ContainingNamespace?.GetHashCode() ?? 0) ^ (!ContainingSyntax.IsEmpty ? ContainingSyntax[0].Identifier.Value.GetHashCode() : 0); public MemberDeclarationSyntax WrapMemberInContainingSyntaxWithUnsafeModifier(MemberDeclarationSyntax member) { diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeNames.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeNames.cs index 9e03be27dd28e..d031ab286ccc0 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeNames.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeNames.cs @@ -29,6 +29,8 @@ public static class TypeNames public const string VirtualMethodIndexAttribute = "System.Runtime.InteropServices.VirtualMethodIndexAttribute"; + public const string IUnmanagedVirtualMethodTableProvider = "System.Runtime.InteropServices.IUnmanagedVirtualMethodTableProvider"; + public const string System_Span_Metadata = "System.Span`1"; public const string System_Span = "System.Span"; public const string System_ReadOnlySpan_Metadata = "System.ReadOnlySpan`1"; @@ -78,5 +80,7 @@ public static string MarshalEx(InteropGenerationOptions options) public const string DllImportSearchPath = "System.Runtime.InteropServices.DllImportSearchPath"; public const string System_CodeDom_Compiler_GeneratedCodeAttribute = "System.CodeDom.Compiler.GeneratedCodeAttribute"; + + public const string System_Runtime_InteropServices_DynamicInterfaceCastableImplementationAttribute = "System.Runtime.InteropServices.DynamicInterfaceCastableImplementationAttribute"; } } diff --git a/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/VirtualMethodIndexAttribute.cs b/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/VirtualMethodIndexAttribute.cs index 7eb34b579081f..47771fc3129d8 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/VirtualMethodIndexAttribute.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/VirtualMethodIndexAttribute.cs @@ -10,7 +10,7 @@ namespace System.Runtime.InteropServices { [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] - internal class VirtualMethodIndexAttribute : Attribute + public class VirtualMethodIndexAttribute : Attribute { public VirtualMethodIndexAttribute(int index) { 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 new file mode 100644 index 0000000000000..9fa6a5b16b814 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CodeSnippets.cs @@ -0,0 +1,33 @@ +// 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.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ComInterfaceGenerator.Unit.Tests +{ + internal static class CodeSnippets + { + public static string SpecifiedMethodIndexNoExplicitParameters = @" +using System.Runtime.InteropServices; + +readonly record struct NoCasting {} +partial interface INativeAPI +{ + public static readonly NoCasting TypeKey = default; + [VirtualMethodIndex(0)] + void Method(); +} + +// Try using the generated native interface +sealed class NativeAPI : IUnmanagedVirtualMethodTableProvider, INativeAPI.Native +{ + public VirtualMethodTableInfo GetFunctionPointerForIndex(NoCasting typeKey) => throw null; +} +"; + + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/ComInterfaceGenerator.Unit.Tests.csproj b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/ComInterfaceGenerator.Unit.Tests.csproj new file mode 100644 index 0000000000000..7b51b148f9ae4 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/ComInterfaceGenerator.Unit.Tests.csproj @@ -0,0 +1,36 @@ + + + + $(NetCoreAppCurrent) + false + Preview + enable + true + + + + + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + + + 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 new file mode 100644 index 0000000000000..a1d406aedb021 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/Compiles.cs @@ -0,0 +1,34 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.Interop.UnitTests; +using Xunit; + +namespace ComInterfaceGenerator.Unit.Tests +{ + public class Compiles + { + public static IEnumerable VTableIndexCodeSnippetsToCompile() + { + yield return new[] { CodeSnippets.SpecifiedMethodIndexNoExplicitParameters }; + } + + [Theory] + [MemberData(nameof(VTableIndexCodeSnippetsToCompile))] + public async Task ValidateVTableIndexSnippets(string source) + { + Compilation comp = await TestUtils.CreateCompilation(source); + // Allow the Native nested type name to be missing in the pre-source-generator compilation + TestUtils.AssertPreSourceGeneratorCompilation(comp, "CS0426"); + + var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.VtableIndexStubGenerator()); + Assert.Empty(generatorDiags); + + var newCompDiags = newComp.GetDiagnostics(); + Assert.Empty(newCompDiags); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/Directory.Build.props b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/Directory.Build.props new file mode 100644 index 0000000000000..fa9c3a4001db5 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/Directory.Build.props @@ -0,0 +1,7 @@ + + + + + true + + diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/TestUtils.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/TestUtils.cs similarity index 99% rename from src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/TestUtils.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/TestUtils.cs index 1498bb587e976..3473b8297ed48 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/TestUtils.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/Common/TestUtils.cs @@ -17,7 +17,7 @@ using System.Threading.Tasks; using Xunit; -namespace LibraryImportGenerator.UnitTests +namespace Microsoft.Interop.UnitTests { /// /// The target framework to compile against. diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/AdditionalAttributesOnStub.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/AdditionalAttributesOnStub.cs index 6082c923a2928..362f2f6a3e760 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/AdditionalAttributesOnStub.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/AdditionalAttributesOnStub.cs @@ -3,6 +3,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Testing; +using Microsoft.Interop.UnitTests; using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/AttributeForwarding.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/AttributeForwarding.cs index a91bf5f5a74ef..174950f2318cd 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/AttributeForwarding.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/AttributeForwarding.cs @@ -4,6 +4,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.Interop; +using Microsoft.Interop.UnitTests; using System; using System.Collections.Generic; using System.Collections.Immutable; diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CompileFails.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CompileFails.cs index 8bdf007ac8619..fc2a72cd47581 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CompileFails.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CompileFails.cs @@ -10,6 +10,7 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis; +using Microsoft.Interop.UnitTests; using Xunit; namespace LibraryImportGenerator.UnitTests diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/Compiles.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/Compiles.cs index 329d4e10fadea..ded3db130cdb9 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/Compiles.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/Compiles.cs @@ -4,6 +4,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.Interop.UnitTests; using System; using System.Collections.Generic; using System.Linq; diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/Diagnostics.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/Diagnostics.cs index 210c4b8c9e165..5f7a41f5bd514 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/Diagnostics.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/Diagnostics.cs @@ -10,6 +10,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Testing; using Microsoft.Interop; +using Microsoft.Interop.UnitTests; using Xunit; using StringMarshalling = Microsoft.Interop.StringMarshalling; diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/IncrementalGenerationTests.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/IncrementalGenerationTests.cs index 204864133c55a..e116bfe339a6e 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/IncrementalGenerationTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/IncrementalGenerationTests.cs @@ -4,6 +4,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.Text; +using Microsoft.Interop.UnitTests; using System; using System.Collections.Generic; using System.Linq; diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/LibraryImportGenerator.Unit.Tests.csproj b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/LibraryImportGenerator.Unit.Tests.csproj index dbbe912f2d38d..a11f95f2580f8 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/LibraryImportGenerator.Unit.Tests.csproj +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/LibraryImportGenerator.Unit.Tests.csproj @@ -11,6 +11,8 @@ + diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/Verifiers/CSharpCodeFixVerifier.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/Verifiers/CSharpCodeFixVerifier.cs index dd30ab7a8c8a8..632ac28caa4fb 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/Verifiers/CSharpCodeFixVerifier.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/Verifiers/CSharpCodeFixVerifier.cs @@ -13,6 +13,7 @@ using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Testing; using Microsoft.CodeAnalysis.Testing.Verifiers; +using Microsoft.Interop.UnitTests; namespace LibraryImportGenerator.UnitTests.Verifiers { From 2af787cf50a57d83f714ad1a9cb31429e5c2ab8c Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Tue, 19 Apr 2022 10:55:31 -0700 Subject: [PATCH 05/30] Add some tests around calling convention handling. --- .../VtableIndexStubGenerator.cs | 2 +- .../VirtualMethodIndexAttribute.cs | 4 +- .../CallingConventionForwarding.cs | 202 ++++++++++++++++++ .../CodeSnippets.cs | 58 ++++- .../Compiles.cs | 2 + 5 files changed, 264 insertions(+), 4 deletions(-) create mode 100644 src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CallingConventionForwarding.cs diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs index 01a8f816fc001..f71d1432ee6ac 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs @@ -225,7 +225,7 @@ private static TargetFramework DetermineTargetFramework(Compilation compilation, } if (namedArguments.TryGetValue(nameof(VirtualMethodIndexData.ImplicitThisParameter), out TypedConstant implicitThisValue)) { - if (directionValue.Value is not bool) + if (implicitThisValue.Value is not bool) { return null; } diff --git a/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/VirtualMethodIndexAttribute.cs b/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/VirtualMethodIndexAttribute.cs index 47771fc3129d8..26b4fe8a81726 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/VirtualMethodIndexAttribute.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/VirtualMethodIndexAttribute.cs @@ -19,9 +19,9 @@ public VirtualMethodIndexAttribute(int index) public int Index { get; } - public bool ImplicitThisParameter { get; init; } = true; + public bool ImplicitThisParameter { get; set; } = true; - public CustomTypeMarshallerDirection Direction { get; init; } = CustomTypeMarshallerDirection.Ref; + public CustomTypeMarshallerDirection Direction { get; set; } = CustomTypeMarshallerDirection.Ref; /// /// Gets or sets how to marshal string arguments to the method. diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CallingConventionForwarding.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CallingConventionForwarding.cs new file mode 100644 index 0000000000000..04abaf832d544 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CallingConventionForwarding.cs @@ -0,0 +1,202 @@ +// 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.Linq; +using System.Reflection.Metadata; +using System.Text; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Operations; +using Microsoft.Interop.UnitTests; +using Xunit; + +namespace ComInterfaceGenerator.Unit.Tests +{ + public class CallingConventionForwarding + { + [Fact] + public async Task NoSpecifiedCallConvForwardsDefault() + { + string source = @" +using System.Runtime.InteropServices; + +readonly record struct NoCasting {} +partial interface INativeAPI +{ + public static readonly NoCasting TypeKey = default; + [VirtualMethodIndex(0)] + void Method(); +}"; + Compilation comp = await TestUtils.CreateCompilation(source); + // Allow the Native nested type name to be missing in the pre-source-generator compilation + TestUtils.AssertPreSourceGeneratorCompilation(comp); + + var newComp = TestUtils.RunGenerators(comp, out _, new Microsoft.Interop.VtableIndexStubGenerator()); + + var signature = await FindFunctionPointerInvocationSignature(newComp, "INativeAPI", "Method"); + + Assert.Equal(SignatureCallingConvention.Unmanaged, signature.CallingConvention); + Assert.Empty(signature.UnmanagedCallingConventionTypes); + } + + [Fact] + public async Task SuppressGCTransitionAttributeForwarded() + { + string source = @" +using System.Runtime.InteropServices; + +readonly record struct NoCasting {} +partial interface INativeAPI +{ + public static readonly NoCasting TypeKey = default; + [SuppressGCTransitionAttribute] + [VirtualMethodIndex(0)] + void Method(); +}"; + Compilation comp = await TestUtils.CreateCompilation(source); + // Allow the Native nested type name to be missing in the pre-source-generator compilation + TestUtils.AssertPreSourceGeneratorCompilation(comp); + + var newComp = TestUtils.RunGenerators(comp, out _, new Microsoft.Interop.VtableIndexStubGenerator()); + + var signature = await FindFunctionPointerInvocationSignature(newComp, "INativeAPI", "Method"); + + Assert.Equal(SignatureCallingConvention.Unmanaged, signature.CallingConvention); + Assert.Equal(newComp.GetTypeByMetadataName("System.Runtime.CompilerServices.CallConvSuppressGCTransition"), Assert.Single(signature.UnmanagedCallingConventionTypes)); + } + + [Fact] + public async Task EmptyUnmanagedCallConvAttributeForwarded() + { + string source = @" +using System.Runtime.InteropServices; + +readonly record struct NoCasting {} +partial interface INativeAPI +{ + public static readonly NoCasting TypeKey = default; + [UnmanagedCallConv] + [VirtualMethodIndex(0)] + void Method(); +}"; + Compilation comp = await TestUtils.CreateCompilation(source); + // Allow the Native nested type name to be missing in the pre-source-generator compilation + TestUtils.AssertPreSourceGeneratorCompilation(comp); + + var newComp = TestUtils.RunGenerators(comp, out _, new Microsoft.Interop.VtableIndexStubGenerator()); + + var signature = await FindFunctionPointerInvocationSignature(newComp, "INativeAPI", "Method"); + + Assert.Equal(SignatureCallingConvention.Unmanaged, signature.CallingConvention); + Assert.Empty(signature.UnmanagedCallingConventionTypes); + } + + [Fact] + public async Task SimpleUnmanagedCallConvAttributeForwarded() + { + string source = @" +using System.Runtime.InteropServices; + +readonly record struct NoCasting {} +partial interface INativeAPI +{ + public static readonly NoCasting TypeKey = default; + [UnmanagedCallConv(CallConvs = new[] { typeof(CallConvCdecl) })] + [VirtualMethodIndex(0)] + void Method(); +}"; + Compilation comp = await TestUtils.CreateCompilation(source); + // Allow the Native nested type name to be missing in the pre-source-generator compilation + TestUtils.AssertPreSourceGeneratorCompilation(comp); + + var newComp = TestUtils.RunGenerators(comp, out _, new Microsoft.Interop.VtableIndexStubGenerator()); + + var signature = await FindFunctionPointerInvocationSignature(newComp, "INativeAPI", "Method"); + + Assert.Equal(SignatureCallingConvention.CDecl, signature.CallingConvention); + Assert.Empty(signature.UnmanagedCallingConventionTypes); + } + + [Fact] + public async Task ComplexUnmanagedCallConvAttributeForwarded() + { + string source = @" +using System.Runtime.InteropServices; + +readonly record struct NoCasting {} +partial interface INativeAPI +{ + public static readonly NoCasting TypeKey = default; + [UnmanagedCallConv(CallConvs = new[] { typeof(CallConvCdecl), typeof(CallConvMemberFunction) })] + [VirtualMethodIndex(0)] + void Method(); +}"; + Compilation comp = await TestUtils.CreateCompilation(source); + // Allow the Native nested type name to be missing in the pre-source-generator compilation + TestUtils.AssertPreSourceGeneratorCompilation(comp); + + var newComp = TestUtils.RunGenerators(comp, out _, new Microsoft.Interop.VtableIndexStubGenerator()); + + var signature = await FindFunctionPointerInvocationSignature(newComp, "INativeAPI", "Method"); + + Assert.Equal(SignatureCallingConvention.Unmanaged, signature.CallingConvention); + Assert.Equal(new[] + { + newComp.GetTypeByMetadataName("System.Runtime.CompilerServices.CallConvCdecl"), + newComp.GetTypeByMetadataName("System.Runtime.CompilerServices.CallConvMemberFunction"), + }, signature.UnmanagedCallingConventionTypes); + } + + [Fact] + public async Task ComplexUnmanagedCallConvAttributeWithSuppressGCTransitionForwarded() + { + string source = @" +using System.Runtime.InteropServices; + +readonly record struct NoCasting {} +partial interface INativeAPI +{ + public static readonly NoCasting TypeKey = default; + [SuppressGCTransition] + [UnmanagedCallConv(CallConvs = new[] { typeof(CallConvCdecl), typeof(CallConvMemberFunction) })] + [VirtualMethodIndex(0)] + void Method(); +}"; + Compilation comp = await TestUtils.CreateCompilation(source); + // Allow the Native nested type name to be missing in the pre-source-generator compilation + TestUtils.AssertPreSourceGeneratorCompilation(comp); + + var newComp = TestUtils.RunGenerators(comp, out _, new Microsoft.Interop.VtableIndexStubGenerator()); + + var signature = await FindFunctionPointerInvocationSignature(newComp, "INativeAPI", "Method"); + + Assert.Equal(SignatureCallingConvention.Unmanaged, signature.CallingConvention); + Assert.Equal(new[] + { + newComp.GetTypeByMetadataName("System.Runtime.CompilerServices.CallConvSuppressGCTransition"), + newComp.GetTypeByMetadataName("System.Runtime.CompilerServices.CallConvCdecl"), + newComp.GetTypeByMetadataName("System.Runtime.CompilerServices.CallConvMemberFunction"), + }, signature.UnmanagedCallingConventionTypes); + } + + private static async Task FindFunctionPointerInvocationSignature(Compilation compilation, string userDefinedInterfaceName, string methodName) + { + INamedTypeSymbol? userDefinedInterface = compilation.Assembly.GetTypeByMetadataName(userDefinedInterfaceName); + Assert.NotNull(userDefinedInterface); + + INamedTypeSymbol generatedInterfaceImplementation = Assert.Single(userDefinedInterface.GetTypeMembers("Native")); + + IMethodSymbol methodImplementation = Assert.Single(generatedInterfaceImplementation.GetMembers($"{userDefinedInterfaceName}.{methodName}").OfType()); + + SyntaxNode emittedImplementationSyntax = await methodImplementation.DeclaringSyntaxReferences[0].GetSyntaxAsync(); + + SemanticModel model = compilation.GetSemanticModel(emittedImplementationSyntax.SyntaxTree); + + IOperation body = model.GetOperation(emittedImplementationSyntax)!; + + return Assert.Single(body.Descendants().OfType()).GetFunctionPointerSignature(); + } + } +} 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 9fa6a5b16b814..78a5d550260d7 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 @@ -11,7 +11,7 @@ namespace ComInterfaceGenerator.Unit.Tests { internal static class CodeSnippets { - public static string SpecifiedMethodIndexNoExplicitParameters = @" + public static readonly string SpecifiedMethodIndexNoExplicitParameters = @" using System.Runtime.InteropServices; readonly record struct NoCasting {} @@ -22,6 +22,62 @@ partial interface INativeAPI void Method(); } +// Try using the generated native interface +sealed class NativeAPI : IUnmanagedVirtualMethodTableProvider, INativeAPI.Native +{ + public VirtualMethodTableInfo GetFunctionPointerForIndex(NoCasting typeKey) => throw null; +} +"; + + public static readonly string SpecifiedMethodIndexNoExplicitParametersNoImplicitThis = @" +using System.Runtime.InteropServices; + +readonly record struct NoCasting {} +partial interface INativeAPI +{ + public static readonly NoCasting TypeKey = default; + [VirtualMethodIndex(0, ImplicitThisParameter = false)] + void Method(); +} + +// Try using the generated native interface +sealed class NativeAPI : IUnmanagedVirtualMethodTableProvider, INativeAPI.Native +{ + public VirtualMethodTableInfo GetFunctionPointerForIndex(NoCasting typeKey) => throw null; +} +"; + + public static readonly string SpecifiedMethodIndexNoExplicitParametersCallConvWithCallingConventions = @" +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +readonly record struct NoCasting {} +partial interface INativeAPI +{ + public static readonly NoCasting TypeKey = default; + + [UnmanagedCallConv(CallConvs = new[] { typeof(CallConvCdecl) })] + [VirtualMethodIndex(0)] + void Method(); + [UnmanagedCallConv(CallConvs = new[] { typeof(CallConvCdecl), typeof(CallConvMemberFunction) })] + [VirtualMethodIndex(1)] + void Method1(); + + [SuppressGCTransition] + [UnmanagedCallConv(CallConvs = new[] { typeof(CallConvCdecl), typeof(CallConvMemberFunction) })] + [VirtualMethodIndex(2)] + void Method2(); + + [SuppressGCTransition] + [UnmanagedCallConv] + [VirtualMethodIndex(3)] + void Method3(); + + [SuppressGCTransition] + [VirtualMethodIndex(4)] + void Method4(); +} + // Try using the generated native interface sealed class NativeAPI : IUnmanagedVirtualMethodTableProvider, INativeAPI.Native { 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 a1d406aedb021..ad1933c03563d 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 @@ -14,6 +14,8 @@ public class Compiles public static IEnumerable VTableIndexCodeSnippetsToCompile() { yield return new[] { CodeSnippets.SpecifiedMethodIndexNoExplicitParameters }; + yield return new[] { CodeSnippets.SpecifiedMethodIndexNoExplicitParametersNoImplicitThis }; + yield return new[] { CodeSnippets.SpecifiedMethodIndexNoExplicitParametersCallConvWithCallingConventions }; } [Theory] From 6d7327b53f2c69a44816d1bfbdb6db8b12bb7640 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Tue, 19 Apr 2022 13:42:13 -0700 Subject: [PATCH 06/30] Add tests for the emitted native interface type shape --- .../CallingConventionForwarding.cs | 10 +- .../NativeInterfaceShape.cs | 99 +++++++++++++++++++ 2 files changed, 106 insertions(+), 3 deletions(-) create mode 100644 src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/NativeInterfaceShape.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CallingConventionForwarding.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CallingConventionForwarding.cs index 04abaf832d544..9ec1ecc2a5870 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CallingConventionForwarding.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CallingConventionForwarding.cs @@ -64,7 +64,7 @@ partial interface INativeAPI var signature = await FindFunctionPointerInvocationSignature(newComp, "INativeAPI", "Method"); Assert.Equal(SignatureCallingConvention.Unmanaged, signature.CallingConvention); - Assert.Equal(newComp.GetTypeByMetadataName("System.Runtime.CompilerServices.CallConvSuppressGCTransition"), Assert.Single(signature.UnmanagedCallingConventionTypes)); + Assert.Equal(newComp.GetTypeByMetadataName("System.Runtime.CompilerServices.CallConvSuppressGCTransition"), Assert.Single(signature.UnmanagedCallingConventionTypes), SymbolEqualityComparer.Default); } [Fact] @@ -146,7 +146,9 @@ partial interface INativeAPI { newComp.GetTypeByMetadataName("System.Runtime.CompilerServices.CallConvCdecl"), newComp.GetTypeByMetadataName("System.Runtime.CompilerServices.CallConvMemberFunction"), - }, signature.UnmanagedCallingConventionTypes); + }, + signature.UnmanagedCallingConventionTypes, + SymbolEqualityComparer.Default); } [Fact] @@ -178,7 +180,9 @@ partial interface INativeAPI newComp.GetTypeByMetadataName("System.Runtime.CompilerServices.CallConvSuppressGCTransition"), newComp.GetTypeByMetadataName("System.Runtime.CompilerServices.CallConvCdecl"), newComp.GetTypeByMetadataName("System.Runtime.CompilerServices.CallConvMemberFunction"), - }, signature.UnmanagedCallingConventionTypes); + }, + signature.UnmanagedCallingConventionTypes, + SymbolEqualityComparer.Default); } private static async Task FindFunctionPointerInvocationSignature(Compilation compilation, string userDefinedInterfaceName, string methodName) diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/NativeInterfaceShape.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/NativeInterfaceShape.cs new file mode 100644 index 0000000000000..643fe93630031 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/NativeInterfaceShape.cs @@ -0,0 +1,99 @@ +// 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.Linq; +using System.Reflection.Metadata; +using System.Text; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Operations; +using Microsoft.Interop.UnitTests; +using Xunit; + +namespace ComInterfaceGenerator.Unit.Tests +{ + public class NativeInterfaceShape + { + [Fact] + public async Task NativeInterfaceNestedInUserInterface() + { + string source = @" +using System.Runtime.InteropServices; + +readonly record struct NoCasting {} +partial interface INativeAPI +{ + public static readonly NoCasting TypeKey = default; + [VirtualMethodIndex(0)] + void Method(); +}"; + Compilation comp = await TestUtils.CreateCompilation(source); + // Allow the Native nested type name to be missing in the pre-source-generator compilation + TestUtils.AssertPreSourceGeneratorCompilation(comp); + + var newComp = TestUtils.RunGenerators(comp, out _, new Microsoft.Interop.VtableIndexStubGenerator()); + + INamedTypeSymbol? userDefinedInterface = newComp.Assembly.GetTypeByMetadataName("INativeAPI"); + Assert.NotNull(userDefinedInterface); + + Assert.Single(userDefinedInterface.GetTypeMembers("Native")); + } + + [Fact] + public async Task NativeInterfaceInheritsFromUserInterface() + { + string source = @" +using System.Runtime.InteropServices; + +readonly record struct NoCasting {} +partial interface INativeAPI +{ + public static readonly NoCasting TypeKey = default; + [VirtualMethodIndex(0)] + void Method(); +}"; + Compilation comp = await TestUtils.CreateCompilation(source); + // Allow the Native nested type name to be missing in the pre-source-generator compilation + TestUtils.AssertPreSourceGeneratorCompilation(comp); + + var newComp = TestUtils.RunGenerators(comp, out _, new Microsoft.Interop.VtableIndexStubGenerator()); + + INamedTypeSymbol? userDefinedInterface = newComp.Assembly.GetTypeByMetadataName("INativeAPI"); + Assert.NotNull(userDefinedInterface); + + Assert.Equal(userDefinedInterface, Assert.Single(Assert.Single(userDefinedInterface.GetTypeMembers("Native")).Interfaces), SymbolEqualityComparer.Default); + } + + [Fact] + public async Task NativeInterfaceHasDynamicInterfaceCastableImplementationAttribute() + { + string source = @" +using System.Runtime.InteropServices; + +readonly record struct NoCasting {} +partial interface INativeAPI +{ + public static readonly NoCasting TypeKey = default; + [VirtualMethodIndex(0)] + void Method(); +}"; + Compilation comp = await TestUtils.CreateCompilation(source); + // Allow the Native nested type name to be missing in the pre-source-generator compilation + TestUtils.AssertPreSourceGeneratorCompilation(comp); + + var newComp = TestUtils.RunGenerators(comp, out _, new Microsoft.Interop.VtableIndexStubGenerator()); + + INamedTypeSymbol? userDefinedInterface = newComp.Assembly.GetTypeByMetadataName("INativeAPI"); + Assert.NotNull(userDefinedInterface); + + INamedTypeSymbol dynamicInterfaceCastableImplementationAttribute = newComp.GetTypeByMetadataName("System.Runtime.InteropServices.DynamicInterfaceCastableImplementationAttribute")!; + + Assert.Contains( + dynamicInterfaceCastableImplementationAttribute, + Assert.Single(userDefinedInterface.GetTypeMembers("Native")).GetAttributes().Select(attr => attr.AttributeClass), + SymbolEqualityComparer.Default); + } + } +} From b9f3597a8caa1277b5375ea1682e58345238a478 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Tue, 19 Apr 2022 14:18:20 -0700 Subject: [PATCH 07/30] Add some basic marshalling tests to give some validation that we set up the marshalling generator correctly (E2E-style validation) --- .../VtableIndexStubGenerator.cs | 7 +- .../BoundGenerators.cs | 10 ++- .../CodeSnippets.cs | 85 +++++++++++++++++++ .../Compiles.cs | 24 ++++++ 4 files changed, 121 insertions(+), 5 deletions(-) diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs index f71d1432ee6ac..6a5c8f0d91b7c 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs @@ -103,16 +103,17 @@ public void Initialize(IncrementalGeneratorInitializationContext context) ) .WithTrackingName(StepNames.CalculateStubInformation); - IncrementalValuesProvider<(MemberDeclarationSyntax, ImmutableArray)> generateSingleStub = generateStubInformation + IncrementalValuesProvider<(MemberDeclarationSyntax, ImmutableArray)> generateManagedToNativeStub = generateStubInformation + .Where(data => data.VtableIndexData.Direction.HasFlag(CustomTypeMarshallerDirection.In)) .Select( static (data, ct) => GenerateManagedToNativeStub(data) ) .WithComparer(Comparers.GeneratedSyntax) .WithTrackingName(StepNames.GenerateManagedToNativeStub); - context.RegisterDiagnostics(generateSingleStub.SelectMany((stubInfo, ct) => stubInfo.Item2)); + context.RegisterDiagnostics(generateManagedToNativeStub.SelectMany((stubInfo, ct) => stubInfo.Item2)); - context.RegisterConcatenatedSyntaxOutputs(generateSingleStub.Select((data, ct) => data.Item1), "ManagedToNativeStubs.g.cs"); + context.RegisterConcatenatedSyntaxOutputs(generateManagedToNativeStub.Select((data, ct) => data.Item1), "ManagedToNativeStubs.g.cs"); IncrementalValuesProvider generateNativeInterface = generateStubInformation .Select(static (context, ct) => context.ContainingSyntaxContext) diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/BoundGenerators.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/BoundGenerators.cs index 90ca43a64abbd..b1f95c1903a1c 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/BoundGenerators.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/BoundGenerators.cs @@ -101,10 +101,16 @@ static IEnumerable GetInfoDependencies(TypePositionInfo info) static int GetInfoIndex(TypePositionInfo info) { + // A TypePositionInfo needs to have either a managed or native index. + // We use negative values of the native index to distinguish them from the managed index. if (info.ManagedIndex == TypePositionInfo.UnsetIndex) { - // A TypePositionInfo needs to have either a managed or native index. - // We use negative values of the native index to distinguish them from the managed index. + if (info.NativeIndex == 0) + { + // If we don't have a managed index and the native index is zero, use ReturnIndex + 1 as our + // index to avoid conflict with managed parameter 0. + return TypePositionInfo.ReturnIndex + 1; + } return -info.NativeIndex; } return info.ManagedIndex; 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 78a5d550260d7..af21ae18bd081 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 @@ -85,5 +85,90 @@ sealed class NativeAPI : IUnmanagedVirtualMethodTableProvider, INativ } "; + public static string BasicParametersAndModifiers(string typeName) => $@" +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly:DisableRuntimeMarshalling] + +readonly record struct NoCasting {{}} +partial interface INativeAPI +{{ + public static readonly NoCasting TypeKey = default; + [VirtualMethodIndex(0)] + {typeName} Method({typeName} value, in {typeName} inValue, ref {typeName} refValue, out {typeName} outValue); +}} + +// Try using the generated native interface +sealed class NativeAPI : IUnmanagedVirtualMethodTableProvider, INativeAPI.Native +{{ + public VirtualMethodTableInfo GetFunctionPointerForIndex(NoCasting typeKey) => throw null; +}} +"; + + public static string BasicParametersAndModifiers() => BasicParametersAndModifiers(typeof(T).FullName!); + + public const string CustomTypeMarshallingTestsTypeName = "S"; + + public static string SimpleCustomTypeMarshallingDeclaration = $@" +[NativeMarshalling(typeof(Marshaller))] +struct {CustomTypeMarshallingTestsTypeName} {{}} + +[CustomTypeMarshaller(typeof({CustomTypeMarshallingTestsTypeName}))] +struct Marshaller +{{ + public Marshaller({CustomTypeMarshallingTestsTypeName} managed) {{}} + + public {CustomTypeMarshallingTestsTypeName} ToManaged() => throw null; +}} +"; + + public static string TwoStageCustomTypeMarshallingDeclaration = $@" +[NativeMarshalling(typeof(Marshaller))] +struct {CustomTypeMarshallingTestsTypeName} {{}} + +[CustomTypeMarshaller(typeof({CustomTypeMarshallingTestsTypeName}), Features = CustomTypeMarshallerFeatures.TwoStageMarshalling)] +struct Marshaller +{{ + public Marshaller({CustomTypeMarshallingTestsTypeName} managed) {{}} + + public {CustomTypeMarshallingTestsTypeName} ToManaged() => throw null; + + public int ToNativeValue() => throw null; + + public void FromNativeValue(int i) => throw null; +}} +"; + + public static string OptionalCallerAllocatedBufferMarshallingDeclaration = $@" +[NativeMarshalling(typeof(Marshaller))] +struct {CustomTypeMarshallingTestsTypeName} +{{ +}} + +[CustomTypeMarshaller(typeof({CustomTypeMarshallingTestsTypeName}), Features = CustomTypeMarshallerFeatures.CallerAllocatedBuffer, BufferSize = 1)] +struct Marshaller +{{ + public Marshaller({CustomTypeMarshallingTestsTypeName} s, System.Span b) {{}} + public Marshaller({CustomTypeMarshallingTestsTypeName} managed) {{}} + + public {CustomTypeMarshallingTestsTypeName} ToManaged() => throw null; +}} +"; + + public static string UnmanagedResourcesCustomTypeMarshallingDeclaration = $@" +[NativeMarshalling(typeof(Marshaller))] +struct {CustomTypeMarshallingTestsTypeName} {{}} + +[CustomTypeMarshaller(typeof({CustomTypeMarshallingTestsTypeName}), Features = CustomTypeMarshallerFeatures.UnmanagedResources)] +struct Marshaller +{{ + public Marshaller({CustomTypeMarshallingTestsTypeName} managed) {{}} + + public {CustomTypeMarshallingTestsTypeName} ToManaged() => throw null; + + public void FreeNative() {{}} +}} +"; } } 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 ad1933c03563d..b395fae11037d 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 @@ -1,6 +1,7 @@ // 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.Threading.Tasks; using Microsoft.CodeAnalysis; @@ -16,6 +17,29 @@ public static IEnumerable VTableIndexCodeSnippetsToCompile() yield return new[] { CodeSnippets.SpecifiedMethodIndexNoExplicitParameters }; yield return new[] { CodeSnippets.SpecifiedMethodIndexNoExplicitParametersNoImplicitThis }; yield return new[] { CodeSnippets.SpecifiedMethodIndexNoExplicitParametersCallConvWithCallingConventions }; + + // Basic marshalling validation + yield return new[] { CodeSnippets.BasicParametersAndModifiers() }; + yield return new[] { CodeSnippets.BasicParametersAndModifiers() }; + yield return new[] { CodeSnippets.BasicParametersAndModifiers() }; + yield return new[] { CodeSnippets.BasicParametersAndModifiers() }; + yield return new[] { CodeSnippets.BasicParametersAndModifiers() }; + yield return new[] { CodeSnippets.BasicParametersAndModifiers() }; + yield return new[] { CodeSnippets.BasicParametersAndModifiers() }; + yield return new[] { CodeSnippets.BasicParametersAndModifiers() }; + yield return new[] { CodeSnippets.BasicParametersAndModifiers() }; + yield return new[] { CodeSnippets.BasicParametersAndModifiers() }; + yield return new[] { CodeSnippets.BasicParametersAndModifiers() }; + yield return new[] { CodeSnippets.BasicParametersAndModifiers() }; + + // Attributed marshalling model validation + yield return new[] { CodeSnippets.BasicParametersAndModifiers(CodeSnippets.CustomTypeMarshallingTestsTypeName) + CodeSnippets.SimpleCustomTypeMarshallingDeclaration }; + yield return new[] { CodeSnippets.BasicParametersAndModifiers(CodeSnippets.CustomTypeMarshallingTestsTypeName) + CodeSnippets.TwoStageCustomTypeMarshallingDeclaration }; + yield return new[] { CodeSnippets.BasicParametersAndModifiers(CodeSnippets.CustomTypeMarshallingTestsTypeName) + CodeSnippets.OptionalCallerAllocatedBufferMarshallingDeclaration }; + yield return new[] { CodeSnippets.BasicParametersAndModifiers(CodeSnippets.CustomTypeMarshallingTestsTypeName) + CodeSnippets.UnmanagedResourcesCustomTypeMarshallingDeclaration }; + + // SafeHandles + yield return new[] { CodeSnippets.BasicParametersAndModifiers("Microsoft.Win32.SafeHandles.SafeFileHandle") }; } [Theory] From 7caa3c798785b9c61cf58b5c4cdb1cec1c2351a1 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Wed, 20 Apr 2022 09:29:54 -0700 Subject: [PATCH 08/30] Add design doc, update API name, remove scratch pad --- .../ComInterfaceGenerator/VTableStubs.md | 399 ++++++++++++++++++ .../IUnmanagedVirtualMethodTableProvider.cs | 75 +--- .../CodeSnippets.cs | 8 +- 3 files changed, 404 insertions(+), 78 deletions(-) create mode 100644 docs/design/libraries/ComInterfaceGenerator/VTableStubs.md diff --git a/docs/design/libraries/ComInterfaceGenerator/VTableStubs.md b/docs/design/libraries/ComInterfaceGenerator/VTableStubs.md new file mode 100644 index 0000000000000..ddf99389efeb0 --- /dev/null +++ b/docs/design/libraries/ComInterfaceGenerator/VTableStubs.md @@ -0,0 +1,399 @@ +# Generating Virtual Method Table Stubs + +As a building block for the COM interface source generator, we've decided to build a source generator that enables developers to mark that a given interface method should invoke a function pointer at a particular offset into an unmanaged virtual method table, or vtable. We've decided to build this generator as a building block for a few reasons: + +1. As part of the migration of dotnet/runtime to use source-generated P/Invokes, we encountered a few scenarios, particularly in the networking stacks, where non-blittable delegate interop was used because the native APIs do not have static entry points. For at least one of these scenarios, MsQuic, the native library provides a table of function pointers. From our experience, this mechanism for versioning is not uncommon and we feel that supporting native libraries that use a versioning scheme similar to this model is worthwhile for us to support. +2. There are native APIs that we are likely to interoperate with in the future that use native vtables but are not COM-oriented. In particular, the Java Native Interface API, which both dotnet/runtime and xamarin/java.interop interface with in various capacities, uses a vtable model to support exposing their APIs to C and C++. Additionally, its API does not conform to a COM-style IUnknown-based API. +3. Some COM-style APIs have some corner cases with non-COM-style interfaces. Specifically, some corners of the DirectX APIs are still vtable-based, but do not implement IUnknown. Providing this building block will allow developers to more easily consume these APIs with similar gestures as the rest of the DirectX API surface. +4. Our future COM interface source generator can build on this building block to provide sane defaults while allowing developers to use the features of this generator to override any default settings provided by the COM generator. + +## Defined types + +To support this generator, we will define the following APIs. + +The `VirtualMethodIndexAttribute` can be applied to an interface method to trigger the generator. This method will provide the index into the vtable for the method, whether or not the method implicitly takes the native `this` pointer, and which marshalling directions to support. It also has many of the same members as `LibraryImportAttribute` to consistently provide the same marshalling support across source-generated marshalling. + +```csharp +namespace System.Runtime.InteropServices; + +[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] +public class VirtualMethodIndexAttribute : Attribute +{ + public VirtualMethodIndexAttribute(int index) + { + Index = index; + } + + public int Index { get; } + + public bool ImplicitThisParameter { get; set; } = true; + + public CustomTypeMarshallerDirection Direction { get; set; } = CustomTypeMarshallerDirection.Ref; + + /// + /// Gets or sets how to marshal string arguments to the method. + /// + /// + /// If this field is set to a value other than , + /// must not be specified. + /// + public StringMarshalling StringMarshalling { get; set; } + + /// + /// Gets or sets the used to control how string arguments to the method are marshalled. + /// + /// + /// If this field is specified, must not be specified + /// or must be set to . + /// + public Type? StringMarshallingCustomType { get; set; } + + /// + /// Gets or sets whether the callee sets an error (SetLastError on Windows or errno + /// on other platforms) before returning from the attributed method. + /// + public bool SetLastError { get; set; } +} + +``` + +Additionally, a new interface will be provided. This new interface will be used by the source generator to fetch the native `this` pointer and the vtable that the function pointer is stored in. This interface is designed to provide an API that various native platforms, like COM, WinRT, or Swift, could use to provide support for multiple managed interface wrappers from a single native object. In particular, this interface was designed to ensure it is possible support a managed gesture to do an unmanaged "type cast" (i.e. `QueryInterface` in the COM and WinRT worlds). + +```csharp +namespace System.Runtime.InteropServices; + +public readonly ref struct VirtualMethodTableInfo +{ + public VirtualMethodTableInfo(IntPtr thisPointer, ReadOnlySpan virtualMethodTable) + { + ThisPointer = thisPointer; + VirtualMethodTable = virtualMethodTable; + } + + public IntPtr ThisPointer { get; } + public ReadOnlySpan VirtualMethodTable { get; } + + public void Deconstruct(out IntPtr thisPointer, out ReadOnlySpan virtualMethodTable) // This method allows tuple-style `var (thisPtr, vtable) = virtualMethodTableInfo;` statements from this type. + { + thisPointer = ThisPointer; + virtualMethodTable = VirtualMethodTable; + } +} + +public interface IUnmanagedVirtualMethodTableProvider where T : IEquatable +{ + VirtualMethodTableInfo GetVirtualMethodTableInfoForKey(T typeKey); +} +``` + +## Required API Shapes + +In addition to the provided APIs above, users will be required to add a `readonly static` field or `get`-able property to their user-defined interface type named `TypeKey`. The type of this member will be used as the `T` in `IUnmanagedVirtualMethodTableProvider` and the value will be passed to `GetVirtualMethodTableInfoForKey`. This mechanism is designed to enable each native API platform to provide their own casting key, for example `IID`s in COM, without interfering with each other or requiring using reflection-based types like `System.Type`. + +## Example Usage + +### Flat function table + +In this example, the native API provides a flat table of functions based on the provided version. + +```cpp +// NativeAPI.cpp + +struct NativeAPI +{ + int(*getVersion)(); + int(*add)(int x, int y); + int(*multiply)(int x, int y); +}; + +namespace +{ + int getVersion() + { + return 1; + } + int add(int x, int y) + { + return x + y; + } + int multiply(int x, int y) + { + return x * y; + } + const NativeAPI g_nativeAPI = { + &getVersion, + &add, + &multiply + }; +} + +extern "C" bool GetNativeAPI(int version, NativeAPI const** ppNativeAPI) +{ + if (version > getVersion()) + { + *ppNativeAPI = nullptr; + return false; + } + *ppNativeAPI = &g_nativeAPI; + return true; +} + +``` + +```csharp +// User-written code +// NativeAPI.cs +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly:DisableRuntimeMarshalling] + +// Define the interface of the native API +partial interface INativeAPI +{ + // There is no concept of casting for this API, but providing a type key is still required by the generator. + // Use an empty readonly record struct to provide a type that implements IEquatable but contains no data. + readonly static NoCasting TypeKey = default; + + [VirtualMethodIndex(0, ImplicitThisParameter = false, Direction = CustomTypeMarshallerDirection.In)] + int GetVersion(); + + [VirtualMethodIndex(1, ImplicitThisParameter = false, Direction = CustomTypeMarshallerDirection.In)] + int Add(int x, int y); + + [VirtualMethodIndex(2, ImplicitThisParameter = false, Direction = CustomTypeMarshallerDirection.In)] + int Multiply(int x, int y); +} + +// Define the key for native "casting" support for our scenario +readonly record struct NoCasting {} + +// Define our runtime wrapper type for the native interface. +unsafe class NativeAPI : IUnmanagedVirtualMethodTableProvider, INativeAPI.Native +{ + private CNativeAPI* _nativeAPI; + + public NativeAPI() + { + if (!CNativeAPI.GetNativeAPI(1, out _nativeAPI)) + { + throw new InvalidOperationException(); + } + } + + VirtualMethodTableInfo IUnmanagedVirtualMethodTableProvider.GetVirtualMethodTableInfoForKey(NoCasting _) + { + return new(IntPtr.Zero, MemoryMarshal.Cast(new ReadOnlySpan(_nativeAPI, 1))); + } +} + +unsafe partial struct CNativeAPI +{ + IntPtr getVersion; + IntPtr add; + IntPtr multiply; + + [LibraryImport(nameof(NativeAPI))] + public static partial bool GetNativeAPI(int version, out CNativeAPI* ppNativeAPI); +}; + +// Generated code for VirtualMethodIndex generator + +// NativeInterfaces.g.cs +partial interface INativeAPI +{ + [DynamicInterfaceCastableImplementation] + partial interface Native : INativeAPI + { + } +} + +// ManagedToNativeStubs.g.cs +partial interface INativeAPI +{ + unsafe partial interface Native + { + int INativeAPI.GetVersion() + { + var (_, vtable) = ((IUnmanagedVirtualMethodTableProvider)this).GetVirtualMethodTableInfoForKey(INativeAPI.TypeKey); + int retVal; + retVal = ((delegate* unmanaged)vtable[0])(); + return retVal; + } + } +} +partial interface INativeAPI +{ + unsafe partial interface Native + { + int INativeAPI.Add(int x, int y) + { + var (_, vtable) = ((IUnmanagedVirtualMethodTableProvider)this).GetVirtualMethodTableInfoForKey(INativeAPI.TypeKey); + int retVal; + retVal = ((delegate* unmanaged)vtable[1])(x, y); + return retVal; + } + } +} +partial interface INativeAPI +{ + unsafe partial interface Native + { + int INativeAPI.Multiply(int x, int y) + { + var (_, vtable) = ((IUnmanagedVirtualMethodTableProvider)this).GetVirtualMethodTableInfoForKey(INativeAPI.TypeKey); + int retVal; + retVal = ((delegate* unmanaged)vtable[2])(x, y); + return retVal; + } + } +} + +// LibraryImport-generated code omitted for brevity +``` + +As this generator is primarily designed to provide building blocks for future work, it has a larger requirement on user-written code. In particular, this generator does not provide any support for authoring a runtime wrapper object that stores the native pointers for the underlying object or the virtual method table. However, this lack of support also provides significant flexibility for developers. The only requirement for the runtime wrapper object type is that it implements `IUnmanagedVirtualMethodTableProvider` with a `T` matching the `TypeKey` type of the native interface. + +The emitted interface implementation can be used in two ways: + +1. The user's runtime wrapper object can directly implement the emitted `Native` interface. This method works for cases where all interfaces are statically known to exist (interfaces are not conditionally implemented on each object). +2. The user's runtime wrapper object can implement `IDynamicInterfaceCastable` and can return the handle of `INativeAPI.Native` when user code casts the wrapper to `INativeAPI`. This style is more commonly used for COM-style APIs. + +### COM interface + +```cpp +// C++ code +struct IUnknown +{ + virtual HRESULT QueryInterface(REFIID riid, void **ppvObject) = 0; + virtual ULONG AddRef() = 0; + virtual ULONG Release() = 0; +}; + +``` +```csharp +// User-defined C# code +using System; +using System.Runtime.InteropServices; + +interface IUnknown +{ + public static readonly Guid TypeKey = Guid.Parse("00000000-0000-0000-C000-000000000046"); + + [UnmanagedCallConv(CallConvs = new[] { typeof(CallConvStdcall), typeof(CallConvMemberFunction) })] + [VirtualMethodIndex(0)] + int QueryInterface(in Guid riid, out IntPtr ppvObject); + + [UnmanagedCallConv(CallConvs = new[] { typeof(CallConvStdcall), typeof(CallConvMemberFunction) })] + [VirtualMethodIndex(1)] + uint AddRef(); + + [UnmanagedCallConv(CallConvs = new[] { typeof(CallConvStdcall), typeof(CallConvMemberFunction) })] + [VirtualMethodIndex(2)] + uint Release(); +} + +class UnknownCOMObject : IUnmanagedVirtualMethodTableProvider, IDynamicInterfaceCastable +{ + private IntPtr _unknownPtr; + + public UnknownCOMObject(IntPtr unknown) + { + _unknownPtr = unknown; + } + + unsafe VirtualMethodTableInfo IUnmanagedVirtualMethodTableProvider.GetVirtualMethodTableInfoForKey(Guid iid) + { + if (iid == IUnknown.TypeKey) + { + return new VirtualMethodTableInfo(_unknownPtr, new ReadOnlySpan(**(IntPtr***)_unknownPtr), 3); + } + return default; + } + + RuntimeTypeHandle IDynamicInterfaceCastable.GetInterfaceImplementation(RuntimeTypeHandle interfaceType) + { + if (Type.GetTypeFromHandle(interfaceType) == typeof(IUnknown)) + { + return typeof(IUnknown.Native).TypeHandle; + } + return default; + } + + bool IDynamicInterfaceCastable.IsInterfaceImplemented(RuntimeTypeHandle interfaceType, bool throwIfNotImplemented) + { + return Type.GetTypeFromHandle(interfaceType) == typeof(IUnknown); + } +} + +// Generated code for VirtualMethodIndex generator + +// NativeInterfaces.g.cs +partial interface IUnknown +{ + [DynamicInterfaceCastableImplementation] + partial interface Native : IUnknown + { + } +} + +// ManagedToNativeStubs.g.cs +partial interface IUnknown +{ + partial interface Native + { + int IUnknown.QueryInterface(in Guid riid, out IntPtr ppvObject) + { + var (thisPtr, vtable) = ((IUnmanagedVirtualMethodTableProvider)this).GetVirtualMethodTableInfoForKey(IUnknown.TypeKey); + int retVal; + fixed (Guid* riid__gen_native = &riid) + fixed (IntPtr* ppvObject__gen_native = &ppvObject) + { + retVal = ((delegate* unmanaged[Stdcall, MemberFunction])vtable[0])(thisPtr, riid__gen_native, ppvObject__gen_native); + } + return retVal; + } + } +} +partial interface IUnknown +{ + partial interface Native + { + uint IUnknown.AddRef() + { + var (thisPtr, vtable) = ((IUnmanagedVirtualMethodTableProvider)this).GetVirtualMethodTableInfoForKey(IUnknown.TypeKey); + uint retVal; + retVal = ((delegate* unmanaged[Stdcall, MemberFunction])vtable[1])(thisPtr); + return retVal; + } + } +} +partial interface IUnknown +{ + partial interface Native + { + uint IUnknown.Release() + { + var (thisPtr, vtable) = ((IUnmanagedVirtualMethodTableProvider)this).GetVirtualMethodTableInfoForKey(IUnknown.TypeKey); + uint retVal; + retVal = ((delegate* unmanaged[Stdcall, MemberFunction])vtable[2])(thisPtr); + return retVal; + } + } +} + +// Native-To-Managed code omitted as the design has not been finalized yet. +``` + +This example shows how we can build COM support on top of the vtable stub generator. The generator will support specifying a custom calling convention using the already-existing `UnmanagedCallConvAttribute`, so it will automatically support forwarding any calling conventions we implement with our extensible calling convention support to the function pointer signature. + +## FAQ + +- Why emit a nested interface instead of a DIM on the existing interface? + - By emitting a nested interface, we enable flexibility in the implementation of the user-defined interface without our implementations getting in the way. With the current design, a managed implementation of a given interface would require the user to implement all members. If we emitted the member implementations directly as DIM implementations, then the compiler would happily allow a developer to only override one method and leave the rest using the native implementation, which would make the development experience of a managed implementation more difficult as there would be no IDE/compiler assistance to fully implement the contract. + +## Open Questions + +- Should we automatically apply the `[DynamicInterfaceCastableImplementation]` attribute to the generated `Native` interface? + - It is a nice convenience, but it isn't applicable in all scenarios and bloats the metadata size. Additionally, since the generated interface is `partial`, we could direct users to add it themselves to the generated interface. + diff --git a/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/IUnmanagedVirtualMethodTableProvider.cs b/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/IUnmanagedVirtualMethodTableProvider.cs index e19dcdbdd71ce..29e56c729f5c2 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/IUnmanagedVirtualMethodTableProvider.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/IUnmanagedVirtualMethodTableProvider.cs @@ -29,80 +29,7 @@ public void Deconstruct(out IntPtr thisPointer, out ReadOnlySpan virtual public interface IUnmanagedVirtualMethodTableProvider where T : IEquatable { - VirtualMethodTableInfo GetFunctionPointerForIndex(T typeKey); + VirtualMethodTableInfo GetVirtualMethodTableInfoForKey(T typeKey); } - // Below here is scratch - /* - readonly record struct NoCasting { } - - //Example using IUnmanagedVirtualMethodTableProvider - public partial class MyWrapper : IUnmanagedVirtualMethodTableProvider, MyNativeAPI.Native - //public partial class MyWrapper : IUnmanagedVirtualMethodTableProvider, IDIC - { - public VirtualMethodTableInfo GetFunctionPointerForIndex(NoCasting type) => throw new NotImplementedException(); - } - - partial interface MyNativeAPI - { - public readonly static NoCasting TypeKey; - - [VirtualMethodIndex(0)] - void Foo(); - } - - // Generated: - partial interface MyNativeAPI - { - [DynamicInterfaceCastableImplementation] - internal interface Native : MyNativeAPI - { - unsafe void MyNativeAPI.Foo() - { - var (thisPtr, vtable) = ((IUnmanagedVirtualMethodTableProvider)this).GetFunctionPointerForIndex(MyNativeAPI.TypeKey); - - ((delegate* unmanaged)vtable[0])(); - } - } - } - - public abstract class GenericComWrappers : ComWrappers - where T: IComObjectWrapper - { - } - - public interface IComObjectWrapper - where T : IComObjectWrapper - { - static abstract T CreateFromIUnknown(IntPtr iUnknown); - } - - - public partial class M : GenericComWrappers - { } - - // Generated - public partial class M - { - protected override object? CreateObject(IntPtr externalComObject, CreateObjectFlags flags) => ComObject.CreateFromIUnknown(externalComObject); - } - - - public class ComObject : IUnmanagedVirtualMethodTableProvider, IDynamicInterfaceCastable, IComObjectWrapper - { - private IntPtr _iUnknown; - - private Dictionary _vtable; - - public static ComObject CreateFromIUnknown(IntPtr iUnknown) => new ComObject { _iUnknown = iUnknown }; - public virtual VirtualMethodTableInfo GetFunctionPointerForIndex(Type type) => QI; - public RuntimeTypeHandle GetInterfaceImplementation(RuntimeTypeHandle interfaceType) => throw new NotImplementedException(); - public bool IsInterfaceImplemented(RuntimeTypeHandle interfaceType, bool throwIfNotImplemented) => throw new NotImplementedException(); - } - - public class MyComObject : ComObject, IComObjectWrapper - { - public static new MyComObject CreateFromIUnknown(IntPtr iUnknown) => new MyComObject { _iUnknown = iUnknown }; - } - */ } 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 af21ae18bd081..0ce40ee7f5be0 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 @@ -25,7 +25,7 @@ partial interface INativeAPI // Try using the generated native interface sealed class NativeAPI : IUnmanagedVirtualMethodTableProvider, INativeAPI.Native { - public VirtualMethodTableInfo GetFunctionPointerForIndex(NoCasting typeKey) => throw null; + public VirtualMethodTableInfo GetVirtualMethodTableInfoForKey(NoCasting typeKey) => throw null; } "; @@ -43,7 +43,7 @@ partial interface INativeAPI // Try using the generated native interface sealed class NativeAPI : IUnmanagedVirtualMethodTableProvider, INativeAPI.Native { - public VirtualMethodTableInfo GetFunctionPointerForIndex(NoCasting typeKey) => throw null; + public VirtualMethodTableInfo GetVirtualMethodTableInfoForKey(NoCasting typeKey) => throw null; } "; @@ -81,7 +81,7 @@ partial interface INativeAPI // Try using the generated native interface sealed class NativeAPI : IUnmanagedVirtualMethodTableProvider, INativeAPI.Native { - public VirtualMethodTableInfo GetFunctionPointerForIndex(NoCasting typeKey) => throw null; + public VirtualMethodTableInfo GetVirtualMethodTableInfoForKey(NoCasting typeKey) => throw null; } "; @@ -102,7 +102,7 @@ partial interface INativeAPI // Try using the generated native interface sealed class NativeAPI : IUnmanagedVirtualMethodTableProvider, INativeAPI.Native {{ - public VirtualMethodTableInfo GetFunctionPointerForIndex(NoCasting typeKey) => throw null; + public VirtualMethodTableInfo GetVirtualMethodTableInfoForKey(NoCasting typeKey) => throw null; }} "; From 6e7e119cdf7f24a4ba75bfc7b0d1c520ac1736fd Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Thu, 12 May 2022 17:16:21 -0700 Subject: [PATCH 09/30] Fix build and run --- .../System.Runtime.InteropServices.sln | 222 +++++++++--------- .../gen/ComInterfaceGenerator/Comparers.cs | 9 +- .../ComInterfaceGenerator/LanguageSupport.cs | 2 +- .../ManagedToNativeVTableMethodGenerator.cs | 6 +- .../UnreachableException.cs | 2 +- .../VirtualMethodIndexAttribute.cs | 1 + .../CodeSnippets.cs | 1 + .../ComInterfaceGenerator.Unit.Tests.csproj | 4 - .../Compiles.cs | 3 +- 9 files changed, 125 insertions(+), 125 deletions(-) diff --git a/src/libraries/System.Runtime.InteropServices/System.Runtime.InteropServices.sln b/src/libraries/System.Runtime.InteropServices/System.Runtime.InteropServices.sln index 8654ddf2b35e1..f91791b13b1ff 100644 --- a/src/libraries/System.Runtime.InteropServices/System.Runtime.InteropServices.sln +++ b/src/libraries/System.Runtime.InteropServices/System.Runtime.InteropServices.sln @@ -1,4 +1,8 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.3.32509.446 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Private.CoreLib", "..\..\coreclr\System.Private.CoreLib\System.Private.CoreLib.csproj", "{94B59BA0-491F-4B59-ADFF-A057EC3EC835}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestUtilities", "..\Common\tests\TestUtilities\TestUtilities.csproj", "{1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}" @@ -38,23 +42,30 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ref", "ref", "{D893B9AA-57C5-49E3-97B1-12CC62D84307}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "gen", "gen", "{E1AEBD5D-AE4E-4F61-B9ED-AEF950B0CC33}" +EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ComInterfaceGenerator", "gen\ComInterfaceGenerator\ComInterfaceGenerator.csproj", "{C3EA0A28-A597-4946-9E08-EBBBFA94BFA5}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ComInterfaceGenerator.Unit.Tests", "tests\ComInterfaceGenerator.Unit.Tests\ComInterfaceGenerator.Unit.Tests.csproj", "{1D771995-D475-429B-AC31-2B1F618AA45F}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ComInterfaceGenerator.Unit.Tests", "tests\ComInterfaceGenerator.Unit.Tests\ComInterfaceGenerator.Unit.Tests.csproj", "{1D771995-D475-429B-AC31-2B1F618AA45F}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Checked|Any CPU = Checked|Any CPU + Checked|x64 = Checked|x64 + Checked|x86 = Checked|x86 Debug|Any CPU = Debug|Any CPU Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU Release|x64 = Release|x64 Release|x86 = Release|x86 - Checked|Any CPU = Checked|Any CPU - Checked|x64 = Checked|x64 - Checked|x86 = Checked|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|Any CPU.ActiveCfg = Checked|x64 + {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|Any CPU.Build.0 = Checked|x64 + {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|x64.ActiveCfg = Checked|x64 + {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|x64.Build.0 = Checked|x64 + {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|x86.ActiveCfg = Checked|x86 + {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|x86.Build.0 = Checked|x86 {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Debug|Any CPU.ActiveCfg = Debug|x64 {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Debug|Any CPU.Build.0 = Debug|x64 {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Debug|x64.ActiveCfg = Debug|x64 @@ -67,12 +78,12 @@ Global {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Release|x64.Build.0 = Release|x64 {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Release|x86.ActiveCfg = Release|x86 {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Release|x86.Build.0 = Release|x86 - {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|Any CPU.ActiveCfg = Checked|x64 - {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|Any CPU.Build.0 = Checked|x64 - {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|x64.ActiveCfg = Checked|x64 - {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|x64.Build.0 = Checked|x64 - {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|x86.ActiveCfg = Checked|x86 - {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|x86.Build.0 = Checked|x86 + {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|Any CPU.Build.0 = Debug|Any CPU + {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|x64.ActiveCfg = Debug|Any CPU + {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|x64.Build.0 = Debug|Any CPU + {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|x86.ActiveCfg = Debug|Any CPU + {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|x86.Build.0 = Debug|Any CPU {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Debug|Any CPU.Build.0 = Debug|Any CPU {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -85,12 +96,12 @@ Global {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Release|x64.Build.0 = Release|Any CPU {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Release|x86.ActiveCfg = Release|Any CPU {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Release|x86.Build.0 = Release|Any CPU - {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|Any CPU.Build.0 = Debug|Any CPU - {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|x64.ActiveCfg = Debug|Any CPU - {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|x64.Build.0 = Debug|Any CPU - {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|x86.ActiveCfg = Debug|Any CPU - {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|x86.Build.0 = Debug|Any CPU + {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Checked|Any CPU.Build.0 = Debug|Any CPU + {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Checked|x64.ActiveCfg = Debug|Any CPU + {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Checked|x64.Build.0 = Debug|Any CPU + {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Checked|x86.ActiveCfg = Debug|Any CPU + {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Checked|x86.Build.0 = Debug|Any CPU {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Debug|Any CPU.Build.0 = Debug|Any CPU {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -103,12 +114,12 @@ Global {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Release|x64.Build.0 = Release|Any CPU {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Release|x86.ActiveCfg = Release|Any CPU {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Release|x86.Build.0 = Release|Any CPU - {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Checked|Any CPU.Build.0 = Debug|Any CPU - {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Checked|x64.ActiveCfg = Debug|Any CPU - {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Checked|x64.Build.0 = Debug|Any CPU - {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Checked|x86.ActiveCfg = Debug|Any CPU - {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Checked|x86.Build.0 = Debug|Any CPU + {1B248B4C-7584-4C04-850A-A50EB592052C}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {1B248B4C-7584-4C04-850A-A50EB592052C}.Checked|Any CPU.Build.0 = Debug|Any CPU + {1B248B4C-7584-4C04-850A-A50EB592052C}.Checked|x64.ActiveCfg = Debug|Any CPU + {1B248B4C-7584-4C04-850A-A50EB592052C}.Checked|x64.Build.0 = Debug|Any CPU + {1B248B4C-7584-4C04-850A-A50EB592052C}.Checked|x86.ActiveCfg = Debug|Any CPU + {1B248B4C-7584-4C04-850A-A50EB592052C}.Checked|x86.Build.0 = Debug|Any CPU {1B248B4C-7584-4C04-850A-A50EB592052C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1B248B4C-7584-4C04-850A-A50EB592052C}.Debug|Any CPU.Build.0 = Debug|Any CPU {1B248B4C-7584-4C04-850A-A50EB592052C}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -121,12 +132,12 @@ Global {1B248B4C-7584-4C04-850A-A50EB592052C}.Release|x64.Build.0 = Release|Any CPU {1B248B4C-7584-4C04-850A-A50EB592052C}.Release|x86.ActiveCfg = Release|Any CPU {1B248B4C-7584-4C04-850A-A50EB592052C}.Release|x86.Build.0 = Release|Any CPU - {1B248B4C-7584-4C04-850A-A50EB592052C}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {1B248B4C-7584-4C04-850A-A50EB592052C}.Checked|Any CPU.Build.0 = Debug|Any CPU - {1B248B4C-7584-4C04-850A-A50EB592052C}.Checked|x64.ActiveCfg = Debug|Any CPU - {1B248B4C-7584-4C04-850A-A50EB592052C}.Checked|x64.Build.0 = Debug|Any CPU - {1B248B4C-7584-4C04-850A-A50EB592052C}.Checked|x86.ActiveCfg = Debug|Any CPU - {1B248B4C-7584-4C04-850A-A50EB592052C}.Checked|x86.Build.0 = Debug|Any CPU + {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Checked|Any CPU.Build.0 = Debug|Any CPU + {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Checked|x64.ActiveCfg = Debug|Any CPU + {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Checked|x64.Build.0 = Debug|Any CPU + {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Checked|x86.ActiveCfg = Debug|Any CPU + {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Checked|x86.Build.0 = Debug|Any CPU {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Debug|Any CPU.Build.0 = Debug|Any CPU {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -139,12 +150,12 @@ Global {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Release|x64.Build.0 = Release|Any CPU {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Release|x86.ActiveCfg = Release|Any CPU {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Release|x86.Build.0 = Release|Any CPU - {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Checked|Any CPU.Build.0 = Debug|Any CPU - {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Checked|x64.ActiveCfg = Debug|Any CPU - {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Checked|x64.Build.0 = Debug|Any CPU - {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Checked|x86.ActiveCfg = Debug|Any CPU - {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Checked|x86.Build.0 = Debug|Any CPU + {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|Any CPU.Build.0 = Debug|Any CPU + {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|x64.ActiveCfg = Debug|Any CPU + {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|x64.Build.0 = Debug|Any CPU + {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|x86.ActiveCfg = Debug|Any CPU + {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|x86.Build.0 = Debug|Any CPU {768B77B0-EA45-469D-B39E-545EB72F5A43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {768B77B0-EA45-469D-B39E-545EB72F5A43}.Debug|Any CPU.Build.0 = Debug|Any CPU {768B77B0-EA45-469D-B39E-545EB72F5A43}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -157,12 +168,12 @@ Global {768B77B0-EA45-469D-B39E-545EB72F5A43}.Release|x64.Build.0 = Release|Any CPU {768B77B0-EA45-469D-B39E-545EB72F5A43}.Release|x86.ActiveCfg = Release|Any CPU {768B77B0-EA45-469D-B39E-545EB72F5A43}.Release|x86.Build.0 = Release|Any CPU - {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|Any CPU.Build.0 = Debug|Any CPU - {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|x64.ActiveCfg = Debug|Any CPU - {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|x64.Build.0 = Debug|Any CPU - {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|x86.ActiveCfg = Debug|Any CPU - {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|x86.Build.0 = Debug|Any CPU + {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|Any CPU.Build.0 = Debug|Any CPU + {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|x64.ActiveCfg = Debug|Any CPU + {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|x64.Build.0 = Debug|Any CPU + {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|x86.ActiveCfg = Debug|Any CPU + {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|x86.Build.0 = Debug|Any CPU {8671F164-F78C-44FA-93B7-A310F67890FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8671F164-F78C-44FA-93B7-A310F67890FE}.Debug|Any CPU.Build.0 = Debug|Any CPU {8671F164-F78C-44FA-93B7-A310F67890FE}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -175,12 +186,12 @@ Global {8671F164-F78C-44FA-93B7-A310F67890FE}.Release|x64.Build.0 = Release|Any CPU {8671F164-F78C-44FA-93B7-A310F67890FE}.Release|x86.ActiveCfg = Release|Any CPU {8671F164-F78C-44FA-93B7-A310F67890FE}.Release|x86.Build.0 = Release|Any CPU - {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|Any CPU.Build.0 = Debug|Any CPU - {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|x64.ActiveCfg = Debug|Any CPU - {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|x64.Build.0 = Debug|Any CPU - {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|x86.ActiveCfg = Debug|Any CPU - {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|x86.Build.0 = Debug|Any CPU + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|Any CPU.Build.0 = Debug|Any CPU + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|x64.ActiveCfg = Debug|Any CPU + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|x64.Build.0 = Debug|Any CPU + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|x86.ActiveCfg = Debug|Any CPU + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|x86.Build.0 = Debug|Any CPU {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Debug|Any CPU.Build.0 = Debug|Any CPU {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -193,12 +204,12 @@ Global {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Release|x64.Build.0 = Release|Any CPU {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Release|x86.ActiveCfg = Release|Any CPU {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Release|x86.Build.0 = Release|Any CPU - {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|Any CPU.Build.0 = Debug|Any CPU - {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|x64.ActiveCfg = Debug|Any CPU - {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|x64.Build.0 = Debug|Any CPU - {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|x86.ActiveCfg = Debug|Any CPU - {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|x86.Build.0 = Debug|Any CPU + {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|Any CPU.Build.0 = Debug|Any CPU + {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|x64.ActiveCfg = Debug|Any CPU + {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|x64.Build.0 = Debug|Any CPU + {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|x86.ActiveCfg = Debug|Any CPU + {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|x86.Build.0 = Debug|Any CPU {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Debug|Any CPU.Build.0 = Debug|Any CPU {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -211,12 +222,12 @@ Global {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Release|x64.Build.0 = Release|Any CPU {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Release|x86.ActiveCfg = Release|Any CPU {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Release|x86.Build.0 = Release|Any CPU - {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|Any CPU.Build.0 = Debug|Any CPU - {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|x64.ActiveCfg = Debug|Any CPU - {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|x64.Build.0 = Debug|Any CPU - {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|x86.ActiveCfg = Debug|Any CPU - {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|x86.Build.0 = Debug|Any CPU + {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Checked|Any CPU.Build.0 = Debug|Any CPU + {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Checked|x64.ActiveCfg = Debug|Any CPU + {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Checked|x64.Build.0 = Debug|Any CPU + {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Checked|x86.ActiveCfg = Debug|Any CPU + {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Checked|x86.Build.0 = Debug|Any CPU {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Debug|Any CPU.Build.0 = Debug|Any CPU {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -229,12 +240,12 @@ Global {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Release|x64.Build.0 = Release|Any CPU {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Release|x86.ActiveCfg = Release|Any CPU {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Release|x86.Build.0 = Release|Any CPU - {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Checked|Any CPU.Build.0 = Debug|Any CPU - {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Checked|x64.ActiveCfg = Debug|Any CPU - {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Checked|x64.Build.0 = Debug|Any CPU - {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Checked|x86.ActiveCfg = Debug|Any CPU - {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Checked|x86.Build.0 = Debug|Any CPU + {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Checked|Any CPU.Build.0 = Debug|Any CPU + {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Checked|x64.ActiveCfg = Debug|Any CPU + {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Checked|x64.Build.0 = Debug|Any CPU + {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Checked|x86.ActiveCfg = Debug|Any CPU + {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Checked|x86.Build.0 = Debug|Any CPU {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Debug|Any CPU.Build.0 = Debug|Any CPU {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -247,12 +258,12 @@ Global {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Release|x64.Build.0 = Release|Any CPU {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Release|x86.ActiveCfg = Release|Any CPU {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Release|x86.Build.0 = Release|Any CPU - {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Checked|Any CPU.Build.0 = Debug|Any CPU - {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Checked|x64.ActiveCfg = Debug|Any CPU - {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Checked|x64.Build.0 = Debug|Any CPU - {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Checked|x86.ActiveCfg = Debug|Any CPU - {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Checked|x86.Build.0 = Debug|Any CPU + {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|Any CPU.Build.0 = Debug|Any CPU + {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|x64.ActiveCfg = Debug|Any CPU + {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|x64.Build.0 = Debug|Any CPU + {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|x86.ActiveCfg = Debug|Any CPU + {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|x86.Build.0 = Debug|Any CPU {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Debug|Any CPU.Build.0 = Debug|Any CPU {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -265,12 +276,12 @@ Global {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Release|x64.Build.0 = Release|Any CPU {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Release|x86.ActiveCfg = Release|Any CPU {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Release|x86.Build.0 = Release|Any CPU - {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|Any CPU.Build.0 = Debug|Any CPU - {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|x64.ActiveCfg = Debug|Any CPU - {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|x64.Build.0 = Debug|Any CPU - {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|x86.ActiveCfg = Debug|Any CPU - {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|x86.Build.0 = Debug|Any CPU + {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|Any CPU.Build.0 = Debug|Any CPU + {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|x64.ActiveCfg = Debug|Any CPU + {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|x64.Build.0 = Debug|Any CPU + {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|x86.ActiveCfg = Debug|Any CPU + {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|x86.Build.0 = Debug|Any CPU {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Debug|Any CPU.Build.0 = Debug|Any CPU {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -283,12 +294,12 @@ Global {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Release|x64.Build.0 = Release|Any CPU {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Release|x86.ActiveCfg = Release|Any CPU {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Release|x86.Build.0 = Release|Any CPU - {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|Any CPU.Build.0 = Debug|Any CPU - {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|x64.ActiveCfg = Debug|Any CPU - {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|x64.Build.0 = Debug|Any CPU - {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|x86.ActiveCfg = Debug|Any CPU - {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|x86.Build.0 = Debug|Any CPU + {866D295E-424A-4747-9417-CD7746936138}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {866D295E-424A-4747-9417-CD7746936138}.Checked|Any CPU.Build.0 = Debug|Any CPU + {866D295E-424A-4747-9417-CD7746936138}.Checked|x64.ActiveCfg = Debug|Any CPU + {866D295E-424A-4747-9417-CD7746936138}.Checked|x64.Build.0 = Debug|Any CPU + {866D295E-424A-4747-9417-CD7746936138}.Checked|x86.ActiveCfg = Debug|Any CPU + {866D295E-424A-4747-9417-CD7746936138}.Checked|x86.Build.0 = Debug|Any CPU {866D295E-424A-4747-9417-CD7746936138}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {866D295E-424A-4747-9417-CD7746936138}.Debug|Any CPU.Build.0 = Debug|Any CPU {866D295E-424A-4747-9417-CD7746936138}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -301,12 +312,12 @@ Global {866D295E-424A-4747-9417-CD7746936138}.Release|x64.Build.0 = Release|Any CPU {866D295E-424A-4747-9417-CD7746936138}.Release|x86.ActiveCfg = Release|Any CPU {866D295E-424A-4747-9417-CD7746936138}.Release|x86.Build.0 = Release|Any CPU - {866D295E-424A-4747-9417-CD7746936138}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {866D295E-424A-4747-9417-CD7746936138}.Checked|Any CPU.Build.0 = Debug|Any CPU - {866D295E-424A-4747-9417-CD7746936138}.Checked|x64.ActiveCfg = Debug|Any CPU - {866D295E-424A-4747-9417-CD7746936138}.Checked|x64.Build.0 = Debug|Any CPU - {866D295E-424A-4747-9417-CD7746936138}.Checked|x86.ActiveCfg = Debug|Any CPU - {866D295E-424A-4747-9417-CD7746936138}.Checked|x86.Build.0 = Debug|Any CPU + {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|Any CPU.Build.0 = Debug|Any CPU + {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|x64.ActiveCfg = Debug|Any CPU + {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|x64.Build.0 = Debug|Any CPU + {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|x86.ActiveCfg = Debug|Any CPU + {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|x86.Build.0 = Debug|Any CPU {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Debug|Any CPU.Build.0 = Debug|Any CPU {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -319,12 +330,12 @@ Global {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Release|x64.Build.0 = Release|Any CPU {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Release|x86.ActiveCfg = Release|Any CPU {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Release|x86.Build.0 = Release|Any CPU - {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|Any CPU.Build.0 = Debug|Any CPU - {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|x64.ActiveCfg = Debug|Any CPU - {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|x64.Build.0 = Debug|Any CPU - {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|x86.ActiveCfg = Debug|Any CPU - {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|x86.Build.0 = Debug|Any CPU + {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|Any CPU.Build.0 = Debug|Any CPU + {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|x64.ActiveCfg = Debug|Any CPU + {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|x64.Build.0 = Debug|Any CPU + {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|x86.ActiveCfg = Debug|Any CPU + {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|x86.Build.0 = Debug|Any CPU {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Debug|Any CPU.Build.0 = Debug|Any CPU {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -337,12 +348,6 @@ Global {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Release|x64.Build.0 = Release|Any CPU {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Release|x86.ActiveCfg = Release|Any CPU {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Release|x86.Build.0 = Release|Any CPU - {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|Any CPU.Build.0 = Debug|Any CPU - {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|x64.ActiveCfg = Debug|Any CPU - {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|x64.Build.0 = Debug|Any CPU - {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|x86.ActiveCfg = Debug|Any CPU - {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|x86.Build.0 = Debug|Any CPU {C3EA0A28-A597-4946-9E08-EBBBFA94BFA5}.Checked|Any CPU.ActiveCfg = Debug|Any CPU {C3EA0A28-A597-4946-9E08-EBBBFA94BFA5}.Checked|Any CPU.Build.0 = Debug|Any CPU {C3EA0A28-A597-4946-9E08-EBBBFA94BFA5}.Checked|x64.ActiveCfg = Debug|Any CPU @@ -385,8 +390,13 @@ Global EndGlobalSection GlobalSection(NestedProjects) = preSolution {94B59BA0-491F-4B59-ADFF-A057EC3EC835} = {B1678CCD-95C8-4419-B9F9-14A03061BE4B} - {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1} = {B1678CCD-95C8-4419-B9F9-14A03061BE4B} {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} + {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A} = {D893B9AA-57C5-49E3-97B1-12CC62D84307} + {1B248B4C-7584-4C04-850A-A50EB592052C} = {E1AEBD5D-AE4E-4F61-B9ED-AEF950B0CC33} + {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40} = {E1AEBD5D-AE4E-4F61-B9ED-AEF950B0CC33} + {768B77B0-EA45-469D-B39E-545EB72F5A43} = {E1AEBD5D-AE4E-4F61-B9ED-AEF950B0CC33} + {8671F164-F78C-44FA-93B7-A310F67890FE} = {D893B9AA-57C5-49E3-97B1-12CC62D84307} + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1} = {B1678CCD-95C8-4419-B9F9-14A03061BE4B} {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} {EA8DBC12-60BC-433E-ABFF-A89DFA795283} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} @@ -394,16 +404,14 @@ Global {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} {866D295E-424A-4747-9417-CD7746936138} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} - {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A} = {D893B9AA-57C5-49E3-97B1-12CC62D84307} - {8671F164-F78C-44FA-93B7-A310F67890FE} = {D893B9AA-57C5-49E3-97B1-12CC62D84307} {0B5FD0C2-367D-4AD6-8001-80AD79B2441C} = {D893B9AA-57C5-49E3-97B1-12CC62D84307} - {1B248B4C-7584-4C04-850A-A50EB592052C} = {E1AEBD5D-AE4E-4F61-B9ED-AEF950B0CC33} - {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40} = {E1AEBD5D-AE4E-4F61-B9ED-AEF950B0CC33} - {768B77B0-EA45-469D-B39E-545EB72F5A43} = {E1AEBD5D-AE4E-4F61-B9ED-AEF950B0CC33} {C3EA0A28-A597-4946-9E08-EBBBFA94BFA5} = {E1AEBD5D-AE4E-4F61-B9ED-AEF950B0CC33} {1D771995-D475-429B-AC31-2B1F618AA45F} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {D4031401-FEB5-4CCF-91C1-38F5646B2BFD} EndGlobalSection + GlobalSection(SharedMSBuildProjectFiles) = preSolution + ..\System.Private.CoreLib\src\System.Private.CoreLib.Shared.projitems*{94b59ba0-491f-4b59-adff-a057ec3ec835}*SharedItemsImports = 5 + EndGlobalSection EndGlobal diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Comparers.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Comparers.cs index 6b8bbd838aac5..3d710b6290e86 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Comparers.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Comparers.cs @@ -16,18 +16,13 @@ internal static class Comparers /// Comparer for an individual generated stub source as a syntax tree and the generated diagnostics for the stub. /// public static readonly IEqualityComparer<(MemberDeclarationSyntax Syntax, ImmutableArray Diagnostics)> GeneratedSyntax = new CustomValueTupleElementComparer>(SyntaxEquivalentComparer.Instance, new ImmutableArraySequenceEqualComparer(EqualityComparer.Default)); - - /// - /// Comparer for the context used to generate a stub and the original user-provided syntax that triggered stub creation. - /// - public static readonly IEqualityComparer<(MethodDeclarationSyntax Syntax, VtableIndexStubGenerator.IncrementalStubGenerationContext StubContext)> CalculatedContextWithSyntax = new CustomValueTupleElementComparer(SyntaxEquivalentComparer.Instance, EqualityComparer.Default); } /// /// Generic comparer to compare two instances element by element. /// /// The type of immutable array element. - internal class ImmutableArraySequenceEqualComparer : IEqualityComparer> + internal sealed class ImmutableArraySequenceEqualComparer : IEqualityComparer> { private readonly IEqualityComparer _elementComparer; @@ -51,7 +46,7 @@ public int GetHashCode(ImmutableArray obj) } } - internal class CustomValueTupleElementComparer : IEqualityComparer<(T, U)> + internal sealed class CustomValueTupleElementComparer : IEqualityComparer<(T, U)> { private readonly IEqualityComparer _item1Comparer; private readonly IEqualityComparer _item2Comparer; diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/LanguageSupport.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/LanguageSupport.cs index 0f983ddc28671..2cf6b88120615 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/LanguageSupport.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/LanguageSupport.cs @@ -6,6 +6,6 @@ namespace System.Runtime.CompilerServices { // Define IsExternalInit type to support records. - internal class IsExternalInit + internal sealed class IsExternalInit { } } diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedToNativeVTableMethodGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedToNativeVTableMethodGenerator.cs index d374a5b04c6c1..454a45e648ee3 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedToNativeVTableMethodGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedToNativeVTableMethodGenerator.cs @@ -117,7 +117,7 @@ public BlockSyntax GenerateStubBody(int index, ImmutableArray { - // var (, ) = ((IUnmanagedVirtualMethodTableProvider<>)this).GetFunctionPointerForIndex(.TypeKey) + // var (, ) = ((IUnmanagedVirtualMethodTableProvider<>)this).GetVirtualMethodTableInfoForKey(.TypeKey) ExpressionStatement( AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, @@ -141,7 +141,7 @@ public BlockSyntax GenerateStubBody(int index, ImmutableArray /// An exception that should be thrown on code-paths that are unreachable. /// - internal class UnreachableException : Exception + internal sealed class UnreachableException : Exception { } } diff --git a/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/VirtualMethodIndexAttribute.cs b/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/VirtualMethodIndexAttribute.cs index 26b4fe8a81726..1cada51d6dede 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/VirtualMethodIndexAttribute.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/VirtualMethodIndexAttribute.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.InteropServices.Marshalling; using System.Text; using System.Threading.Tasks; 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 0ce40ee7f5be0..81fbee52b716c 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 @@ -88,6 +88,7 @@ sealed class NativeAPI : IUnmanagedVirtualMethodTableProvider, INativ public static string BasicParametersAndModifiers(string typeName) => $@" using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; [assembly:DisableRuntimeMarshalling] diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/ComInterfaceGenerator.Unit.Tests.csproj b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/ComInterfaceGenerator.Unit.Tests.csproj index 7b51b148f9ae4..ea25b2b4edb6d 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/ComInterfaceGenerator.Unit.Tests.csproj +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/ComInterfaceGenerator.Unit.Tests.csproj @@ -19,10 +19,6 @@ - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - 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 b395fae11037d..6b3642619d67c 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 @@ -53,8 +53,7 @@ public async Task ValidateVTableIndexSnippets(string source) var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.VtableIndexStubGenerator()); Assert.Empty(generatorDiags); - var newCompDiags = newComp.GetDiagnostics(); - Assert.Empty(newCompDiags); + TestUtils.AssertPostSourceGeneratorCompilation(newComp); } } } From f862f15122d6d2fe42842c57933c124eda7791eb Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Fri, 13 May 2022 11:43:06 -0700 Subject: [PATCH 10/30] Fix markdownlint failures --- docs/design/libraries/ComInterfaceGenerator/VTableStubs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/design/libraries/ComInterfaceGenerator/VTableStubs.md b/docs/design/libraries/ComInterfaceGenerator/VTableStubs.md index ddf99389efeb0..d59a021265418 100644 --- a/docs/design/libraries/ComInterfaceGenerator/VTableStubs.md +++ b/docs/design/libraries/ComInterfaceGenerator/VTableStubs.md @@ -252,7 +252,7 @@ partial interface INativeAPI // LibraryImport-generated code omitted for brevity ``` -As this generator is primarily designed to provide building blocks for future work, it has a larger requirement on user-written code. In particular, this generator does not provide any support for authoring a runtime wrapper object that stores the native pointers for the underlying object or the virtual method table. However, this lack of support also provides significant flexibility for developers. The only requirement for the runtime wrapper object type is that it implements `IUnmanagedVirtualMethodTableProvider` with a `T` matching the `TypeKey` type of the native interface. +As this generator is primarily designed to provide building blocks for future work, it has a larger requirement on user-written code. In particular, this generator does not provide any support for authoring a runtime wrapper object that stores the native pointers for the underlying object or the virtual method table. However, this lack of support also provides significant flexibility for developers. The only requirement for the runtime wrapper object type is that it implements `IUnmanagedVirtualMethodTableProvider` with a `T` matching the `TypeKey` type of the native interface. The emitted interface implementation can be used in two ways: From 09dc2c457e98b5cc0b9eaa83448a2a68e772166d Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Fri, 13 May 2022 16:17:00 -0700 Subject: [PATCH 11/30] infra fixes for ComInterfaceGenerator test runs --- eng/testing/tests.props | 2 +- src/libraries/tests.proj | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/eng/testing/tests.props b/eng/testing/tests.props index e91ec1bbcf0e3..e3bf0ce52d415 100644 --- a/eng/testing/tests.props +++ b/eng/testing/tests.props @@ -39,7 +39,7 @@ - + + @@ -109,12 +110,14 @@ + + From a83b09254377edad7bd35e15339329837e3c56a4 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Fri, 13 May 2022 16:20:07 -0700 Subject: [PATCH 12/30] Add more tests --- .../CodeSnippets.cs | 24 ++++++++++++++++++- .../Compiles.cs | 12 ++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) 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 81fbee52b716c..35ade46c6e2b1 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 @@ -106,8 +106,30 @@ sealed class NativeAPI : IUnmanagedVirtualMethodTableProvider, INativ public VirtualMethodTableInfo GetVirtualMethodTableInfoForKey(NoCasting typeKey) => throw null; }} "; - public static string BasicParametersAndModifiers() => BasicParametersAndModifiers(typeof(T).FullName!); + public static string BasicParametersAndModifiersNoImplicitThis(string typeName) => $@" +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; + +[assembly:DisableRuntimeMarshalling] + +readonly record struct NoCasting {{}} +partial interface INativeAPI +{{ + public static readonly NoCasting TypeKey = default; + [VirtualMethodIndex(0, ImplicitThisParameter = false)] + {typeName} Method({typeName} value, in {typeName} inValue, ref {typeName} refValue, out {typeName} outValue); +}} + +// Try using the generated native interface +sealed class NativeAPI : IUnmanagedVirtualMethodTableProvider, INativeAPI.Native +{{ + public VirtualMethodTableInfo GetVirtualMethodTableInfoForKey(NoCasting typeKey) => throw null; +}} +"; + + public static string BasicParametersAndModifiersNoImplicitThis() => BasicParametersAndModifiersNoImplicitThis(typeof(T).FullName!); public const string CustomTypeMarshallingTestsTypeName = "S"; 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 6b3642619d67c..53ebacea6ba70 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 @@ -31,6 +31,18 @@ public static IEnumerable VTableIndexCodeSnippetsToCompile() yield return new[] { CodeSnippets.BasicParametersAndModifiers() }; yield return new[] { CodeSnippets.BasicParametersAndModifiers() }; yield return new[] { CodeSnippets.BasicParametersAndModifiers() }; + yield return new[] { CodeSnippets.BasicParametersAndModifiersNoImplicitThis() }; + yield return new[] { CodeSnippets.BasicParametersAndModifiersNoImplicitThis() }; + yield return new[] { CodeSnippets.BasicParametersAndModifiersNoImplicitThis() }; + yield return new[] { CodeSnippets.BasicParametersAndModifiersNoImplicitThis() }; + yield return new[] { CodeSnippets.BasicParametersAndModifiersNoImplicitThis() }; + yield return new[] { CodeSnippets.BasicParametersAndModifiersNoImplicitThis() }; + yield return new[] { CodeSnippets.BasicParametersAndModifiersNoImplicitThis() }; + yield return new[] { CodeSnippets.BasicParametersAndModifiersNoImplicitThis() }; + yield return new[] { CodeSnippets.BasicParametersAndModifiersNoImplicitThis() }; + yield return new[] { CodeSnippets.BasicParametersAndModifiersNoImplicitThis() }; + yield return new[] { CodeSnippets.BasicParametersAndModifiersNoImplicitThis() }; + yield return new[] { CodeSnippets.BasicParametersAndModifiersNoImplicitThis() }; // Attributed marshalling model validation yield return new[] { CodeSnippets.BasicParametersAndModifiers(CodeSnippets.CustomTypeMarshallingTestsTypeName) + CodeSnippets.SimpleCustomTypeMarshallingDeclaration }; From faa674eeb99c909e0e83f3416920b26c8a188962 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Mon, 16 May 2022 09:25:13 -0700 Subject: [PATCH 13/30] Exclude ComInterfaceGenerator on mobile platforms --- src/libraries/tests.proj | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libraries/tests.proj b/src/libraries/tests.proj index b2e1289e8a96f..e4101c3fb5e97 100644 --- a/src/libraries/tests.proj +++ b/src/libraries/tests.proj @@ -82,6 +82,7 @@ + From a55e3373e2f5066c62005968695c3ea9b2ee75c7 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Mon, 16 May 2022 10:57:32 -0700 Subject: [PATCH 14/30] Add basic runtime tests --- .../System.Runtime.InteropServices.sln | 21 ++++ .../ComInterfaceGenerator.Tests.csproj | 23 +++++ .../ComInterfaceGenerator.Tests/Constants.cs | 10 ++ .../Directory.Build.props | 7 ++ .../ImplicitThisTests.cs | 83 ++++++++++++++++ .../NoImplicitThisTests.cs | 73 ++++++++++++++ .../NativeExports/VirtualMethodTables.cs | 99 +++++++++++++++++++ 7 files changed, 316 insertions(+) create mode 100644 src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/ComInterfaceGenerator.Tests.csproj create mode 100644 src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/Constants.cs create mode 100644 src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/Directory.Build.props create mode 100644 src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/ImplicitThisTests.cs create mode 100644 src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/NoImplicitThisTests.cs create mode 100644 src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/VirtualMethodTables.cs diff --git a/src/libraries/System.Runtime.InteropServices/System.Runtime.InteropServices.sln b/src/libraries/System.Runtime.InteropServices/System.Runtime.InteropServices.sln index f91791b13b1ff..1668d1b8414b3 100644 --- a/src/libraries/System.Runtime.InteropServices/System.Runtime.InteropServices.sln +++ b/src/libraries/System.Runtime.InteropServices/System.Runtime.InteropServices.sln @@ -47,6 +47,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ComInterfaceGenerator", "ge EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ComInterfaceGenerator.Unit.Tests", "tests\ComInterfaceGenerator.Unit.Tests\ComInterfaceGenerator.Unit.Tests.csproj", "{1D771995-D475-429B-AC31-2B1F618AA45F}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ComInterfaceGenerator.Tests", "tests\ComInterfaceGenerator.Tests\ComInterfaceGenerator.Tests.csproj", "{3741C833-C364-4269-9B1D-D442055DA7CE}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Checked|Any CPU = Checked|Any CPU @@ -384,6 +386,24 @@ Global {1D771995-D475-429B-AC31-2B1F618AA45F}.Release|x64.Build.0 = Release|Any CPU {1D771995-D475-429B-AC31-2B1F618AA45F}.Release|x86.ActiveCfg = Release|Any CPU {1D771995-D475-429B-AC31-2B1F618AA45F}.Release|x86.Build.0 = Release|Any CPU + {3741C833-C364-4269-9B1D-D442055DA7CE}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {3741C833-C364-4269-9B1D-D442055DA7CE}.Checked|Any CPU.Build.0 = Debug|Any CPU + {3741C833-C364-4269-9B1D-D442055DA7CE}.Checked|x64.ActiveCfg = Debug|Any CPU + {3741C833-C364-4269-9B1D-D442055DA7CE}.Checked|x64.Build.0 = Debug|Any CPU + {3741C833-C364-4269-9B1D-D442055DA7CE}.Checked|x86.ActiveCfg = Debug|Any CPU + {3741C833-C364-4269-9B1D-D442055DA7CE}.Checked|x86.Build.0 = Debug|Any CPU + {3741C833-C364-4269-9B1D-D442055DA7CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3741C833-C364-4269-9B1D-D442055DA7CE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3741C833-C364-4269-9B1D-D442055DA7CE}.Debug|x64.ActiveCfg = Debug|Any CPU + {3741C833-C364-4269-9B1D-D442055DA7CE}.Debug|x64.Build.0 = Debug|Any CPU + {3741C833-C364-4269-9B1D-D442055DA7CE}.Debug|x86.ActiveCfg = Debug|Any CPU + {3741C833-C364-4269-9B1D-D442055DA7CE}.Debug|x86.Build.0 = Debug|Any CPU + {3741C833-C364-4269-9B1D-D442055DA7CE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3741C833-C364-4269-9B1D-D442055DA7CE}.Release|Any CPU.Build.0 = Release|Any CPU + {3741C833-C364-4269-9B1D-D442055DA7CE}.Release|x64.ActiveCfg = Release|Any CPU + {3741C833-C364-4269-9B1D-D442055DA7CE}.Release|x64.Build.0 = Release|Any CPU + {3741C833-C364-4269-9B1D-D442055DA7CE}.Release|x86.ActiveCfg = Release|Any CPU + {3741C833-C364-4269-9B1D-D442055DA7CE}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -407,6 +427,7 @@ Global {0B5FD0C2-367D-4AD6-8001-80AD79B2441C} = {D893B9AA-57C5-49E3-97B1-12CC62D84307} {C3EA0A28-A597-4946-9E08-EBBBFA94BFA5} = {E1AEBD5D-AE4E-4F61-B9ED-AEF950B0CC33} {1D771995-D475-429B-AC31-2B1F618AA45F} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} + {3741C833-C364-4269-9B1D-D442055DA7CE} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {D4031401-FEB5-4CCF-91C1-38F5646B2BFD} diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/ComInterfaceGenerator.Tests.csproj b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/ComInterfaceGenerator.Tests.csproj new file mode 100644 index 0000000000000..56e29a19f19e1 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/ComInterfaceGenerator.Tests.csproj @@ -0,0 +1,23 @@ + + + $(NetCoreAppCurrent) + false + Preview + true + true + + false + + + + + + + + + + + + + + diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/Constants.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/Constants.cs new file mode 100644 index 0000000000000..0ac4254a02287 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/Constants.cs @@ -0,0 +1,10 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace ComInterfaceGenerator.Tests +{ + partial class NativeExportsNE + { + public const string NativeExportsNE_Binary = "Microsoft.Interop.Tests." + nameof(NativeExportsNE); + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/Directory.Build.props b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/Directory.Build.props new file mode 100644 index 0000000000000..fa9c3a4001db5 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/Directory.Build.props @@ -0,0 +1,7 @@ + + + + + true + + diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/ImplicitThisTests.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/ImplicitThisTests.cs new file mode 100644 index 0000000000000..454937d764f03 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/ImplicitThisTests.cs @@ -0,0 +1,83 @@ +// 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.Linq; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; +using System.Text; +using System.Threading.Tasks; +using Xunit; + +namespace ComInterfaceGenerator.Tests +{ + internal unsafe partial class NativeExportsNE + { + internal partial class ImplicitThis + { + public readonly record struct NoCasting; + + internal partial interface INativeObject + { + public static readonly NoCasting TypeKey = default; + + [VirtualMethodIndex(0)] + int GetData(); + [VirtualMethodIndex(1)] + void SetData(int x); + } + + [NativeMarshalling(typeof(NativeObjectMarshaller))] + public class NativeObject : INativeObject.Native, IUnmanagedVirtualMethodTableProvider, IDisposable + { + private readonly void* _pointer; + + public NativeObject(void* pointer) + { + _pointer = pointer; + } + + public VirtualMethodTableInfo GetVirtualMethodTableInfoForKey(NoCasting typeKey) => new VirtualMethodTableInfo((IntPtr)_pointer, new ReadOnlySpan(*(void**)_pointer, 2)); + + public void Dispose() + { + DeleteNativeObject(_pointer); + } + } + + [CustomTypeMarshaller(typeof(NativeObject), CustomTypeMarshallerKind.Value, Direction = CustomTypeMarshallerDirection.Out, Features = CustomTypeMarshallerFeatures.TwoStageMarshalling)] + struct NativeObjectMarshaller + { + private void* _nativeValue; + + public void FromNativeValue(void* value) => _nativeValue = value; + + public NativeObject ToManaged() => new NativeObject(_nativeValue); + } + + [LibraryImport(NativeExportsNE_Binary, EntryPoint = "new_native_object")] + public static partial NativeObject NewNativeObject(); + + [LibraryImport(NativeExportsNE_Binary, EntryPoint = "delete_native_object")] + public static partial void DeleteNativeObject(void* obj); + } + } + + public class ImplicitThisTests + { + [Fact] + public void ValidateImplicitThisFunctionCallsSucceed() + { + const int value = 42; + + using NativeExportsNE.ImplicitThis.NativeObject obj = NativeExportsNE.ImplicitThis.NewNativeObject(); + + NativeExportsNE.ImplicitThis.INativeObject nativeObjInterface = obj; + + nativeObjInterface.SetData(value); + + Assert.Equal(value, nativeObjInterface.GetData()); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/NoImplicitThisTests.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/NoImplicitThisTests.cs new file mode 100644 index 0000000000000..dd1e984eca8df --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/NoImplicitThisTests.cs @@ -0,0 +1,73 @@ +// 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.Linq; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; +using System.Text; +using System.Threading.Tasks; +using Xunit; + +namespace ComInterfaceGenerator.Tests +{ + internal unsafe partial class NativeExportsNE + { + internal partial class NoImplicitThis + { + public readonly record struct NoCasting; + + internal partial interface IStaticMethodTable + { + public static readonly NoCasting TypeKey = default; + + [VirtualMethodIndex(0, ImplicitThisParameter = false)] + int Add(int x, int y); + [VirtualMethodIndex(1, ImplicitThisParameter = false)] + int Multiply(int x, int y); + } + + [NativeMarshalling(typeof(StaticMethodTableMarshaller))] + public class StaticMethodTable : IStaticMethodTable.Native, IUnmanagedVirtualMethodTableProvider + { + private readonly void* _vtableStart; + + public StaticMethodTable(void* vtableStart) + { + _vtableStart = vtableStart; + } + + public VirtualMethodTableInfo GetVirtualMethodTableInfoForKey(NoCasting typeKey) => new VirtualMethodTableInfo(IntPtr.Zero, new ReadOnlySpan(_vtableStart, 2)); + } + + [CustomTypeMarshaller(typeof(StaticMethodTable), CustomTypeMarshallerKind.Value, Direction = CustomTypeMarshallerDirection.Out, Features = CustomTypeMarshallerFeatures.TwoStageMarshalling)] + struct StaticMethodTableMarshaller + { + private void* _nativeValue; + + public void FromNativeValue(void* value) => _nativeValue = value; + + public StaticMethodTable ToManaged() => new StaticMethodTable(_nativeValue); + } + + [LibraryImport(NativeExportsNE_Binary, EntryPoint = "get_static_function_table")] + public static partial StaticMethodTable GetStaticFunctionTable(); + } + } + + public class NoImplicitThisTests + { + [Fact] + public void ValidateNoImplicitThisFunctionCallsSucceed() + { + int x = 7; + int y = 56; + + NativeExportsNE.NoImplicitThis.IStaticMethodTable staticMethodTable = NativeExportsNE.NoImplicitThis.GetStaticFunctionTable(); + + Assert.Equal(x + y, staticMethodTable.Add(x, y)); + Assert.Equal(x * y, staticMethodTable.Multiply(x, y)); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/VirtualMethodTables.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/VirtualMethodTables.cs new file mode 100644 index 0000000000000..b0b5e019b7b8e --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/VirtualMethodTables.cs @@ -0,0 +1,99 @@ +// 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.Linq; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace NativeExports +{ + internal unsafe static class VirtualMethodTables + { + struct StaticFunctionTable + { + public delegate* unmanaged Add; + public delegate* unmanaged Multiply; + } + + [UnmanagedCallersOnly] + private static int Add(int x, int y) => x + y; + + [UnmanagedCallersOnly] + private static int Multiply(int x, int y) => x * y; + + private static readonly StaticFunctionTable* StaticTable; + + static VirtualMethodTables() + { + StaticTable = (StaticFunctionTable*)RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(VirtualMethodTables), sizeof(StaticFunctionTable)); + + StaticTable->Add = &Add; + StaticTable->Multiply = &Multiply; + } + + [UnmanagedCallersOnly(EntryPoint = "get_static_function_table")] + public static void* GetStaticFunctionTable() + { + return StaticTable; + } + + public struct NativeObject + { + private struct VirtualFunctionTable + { + public delegate* unmanaged getData; + public delegate* unmanaged setData; + } + + static NativeObject() + { + VTablePointer = (VirtualFunctionTable*)RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(NativeObject), sizeof(VirtualFunctionTable)); + VTablePointer->getData = &GetData; + VTablePointer->setData = &SetData; + } + + private static readonly VirtualFunctionTable* VTablePointer; + + private readonly VirtualFunctionTable* vtable = VTablePointer; + + public NativeObject() + { + } + + public int Data { get; set; } = 0; + + [UnmanagedCallersOnly] + private static int GetData(NativeObject* obj) + { + return obj->Data; + } + + [UnmanagedCallersOnly] + private static void SetData(NativeObject* obj, int value) + { + obj->Data = value; + } + } + + [UnmanagedCallersOnly(EntryPoint = "new_native_object")] + [DNNE.C99DeclCode("struct NativeObject;")] + [return: DNNE.C99Type("struct NativeObject*")] + public static NativeObject* NewNativeObject() + { + NativeObject* memory = (NativeObject*)NativeMemory.Alloc((nuint)sizeof(NativeObject)); + *memory = new NativeObject(); + return memory; + } + + [UnmanagedCallersOnly(EntryPoint = "delete_native_object")] + [DNNE.C99DeclCode("struct NativeObject;")] + public static void DeleteNativeObject([DNNE.C99Type("struct NativeObject*")] NativeObject* obj) + { + NativeMemory.Free(obj); + } + } +} From 7e92bd40a09b8d143105c7dbeee8fc94d72e8465 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Thu, 26 May 2022 15:07:38 -0700 Subject: [PATCH 15/30] Remove extraneous diagnostic --- .../gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs index 6a5c8f0d91b7c..44d8db136a403 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs @@ -281,7 +281,6 @@ private static IncrementalStubGenerationContext CalculateStubInformation(MethodD if (virtualMethodIndexData is null) { - generatorDiagnostics.ReportConfigurationNotSupported(virtualMethodIndexAttr!, "Invalid syntax"); virtualMethodIndexData = new VirtualMethodIndexData(-1); } From d95cdacb8c9d81048e716dd42204e65835df9c63 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Tue, 7 Jun 2022 13:34:42 -0700 Subject: [PATCH 16/30] PR feedback --- .../ComInterfaceGenerator/VTableStubs.md | 11 +++++--- .../VtableIndexStubGenerator.cs | 27 +++---------------- .../ContainingSyntaxContext.cs | 10 ++++++- .../Microsoft.Interop.SourceGeneration.csproj | 2 +- .../ImplicitThisTests.cs | 4 +-- 5 files changed, 23 insertions(+), 31 deletions(-) diff --git a/docs/design/libraries/ComInterfaceGenerator/VTableStubs.md b/docs/design/libraries/ComInterfaceGenerator/VTableStubs.md index d59a021265418..310552c24d4b1 100644 --- a/docs/design/libraries/ComInterfaceGenerator/VTableStubs.md +++ b/docs/design/libraries/ComInterfaceGenerator/VTableStubs.md @@ -5,7 +5,7 @@ As a building block for the COM interface source generator, we've decided to bui 1. As part of the migration of dotnet/runtime to use source-generated P/Invokes, we encountered a few scenarios, particularly in the networking stacks, where non-blittable delegate interop was used because the native APIs do not have static entry points. For at least one of these scenarios, MsQuic, the native library provides a table of function pointers. From our experience, this mechanism for versioning is not uncommon and we feel that supporting native libraries that use a versioning scheme similar to this model is worthwhile for us to support. 2. There are native APIs that we are likely to interoperate with in the future that use native vtables but are not COM-oriented. In particular, the Java Native Interface API, which both dotnet/runtime and xamarin/java.interop interface with in various capacities, uses a vtable model to support exposing their APIs to C and C++. Additionally, its API does not conform to a COM-style IUnknown-based API. 3. Some COM-style APIs have some corner cases with non-COM-style interfaces. Specifically, some corners of the DirectX APIs are still vtable-based, but do not implement IUnknown. Providing this building block will allow developers to more easily consume these APIs with similar gestures as the rest of the DirectX API surface. -4. Our future COM interface source generator can build on this building block to provide sane defaults while allowing developers to use the features of this generator to override any default settings provided by the COM generator. +4. Our future COM interface source generator can build on this building block to provide defaults while allowing developers to use the features of this generator to override any default settings provided by the COM generator. ## Defined types @@ -57,7 +57,7 @@ public class VirtualMethodIndexAttribute : Attribute ``` -Additionally, a new interface will be provided. This new interface will be used by the source generator to fetch the native `this` pointer and the vtable that the function pointer is stored in. This interface is designed to provide an API that various native platforms, like COM, WinRT, or Swift, could use to provide support for multiple managed interface wrappers from a single native object. In particular, this interface was designed to ensure it is possible support a managed gesture to do an unmanaged "type cast" (i.e. `QueryInterface` in the COM and WinRT worlds). +A new interface will be defined and used by the source generator to fetch the native `this` pointer and the vtable that the function pointer is stored in. This interface is designed to provide an API that various native platforms, like COM, WinRT, or Swift, could use to provide support for multiple managed interface wrappers from a single native object. In particular, this interface was designed to ensure it is possible support a managed gesture to do an unmanaged "type cast" (i.e., `QueryInterface` in the COM and WinRT worlds). ```csharp namespace System.Runtime.InteropServices; @@ -187,6 +187,9 @@ unsafe class NativeAPI : IUnmanagedVirtualMethodTableProvider, INativ } } +// This struct represent a flat table of function pointers that implements the native API. +// This can either be returned by the API (MSQuic) or be constructed manually from calling +// a method that returns function pointers and be used as a cache (OpenGL and Vulkan) unsafe partial struct CNativeAPI { IntPtr getVersion; @@ -293,11 +296,11 @@ interface IUnknown uint Release(); } -class UnknownCOMObject : IUnmanagedVirtualMethodTableProvider, IDynamicInterfaceCastable +class BaseIUnknownComObject : IUnmanagedVirtualMethodTableProvider, IDynamicInterfaceCastable { private IntPtr _unknownPtr; - public UnknownCOMObject(IntPtr unknown) + public BaseIUnknownComObject(IntPtr unknown) { _unknownPtr = unknown; } diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs index 44d8db136a403..650f1e171cad6 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs @@ -178,24 +178,6 @@ private static MemberDeclarationSyntax PrintGeneratedSource( .WithBody(stubCode); } - private static TargetFramework DetermineTargetFramework(Compilation compilation, out Version version) - { - IAssemblySymbol systemAssembly = compilation.GetSpecialType(SpecialType.System_Object).ContainingAssembly; - version = systemAssembly.Identity.Version; - - return systemAssembly.Identity.Name switch - { - // .NET Framework - "mscorlib" => TargetFramework.Framework, - // .NET Standard - "netstandard" => TargetFramework.Standard, - // .NET Core (when version < 5.0) or .NET - "System.Runtime" or "System.Private.CoreLib" => - (version.Major < 5) ? TargetFramework.Core : TargetFramework.Net, - _ => TargetFramework.Unknown, - }; - } - private static VirtualMethodIndexData? ProcessVirtualMethodIndexAttribute(AttributeData attrData) { // Found the attribute, but it has an error so report the error. @@ -283,6 +265,10 @@ private static IncrementalStubGenerationContext CalculateStubInformation(MethodD { virtualMethodIndexData = new VirtualMethodIndexData(-1); } + else if (virtualMethodIndexData.Index < 0) + { + // Report missing or invalid index + } if (virtualMethodIndexData.IsUserDefined.HasFlag(InteropAttributeMember.StringMarshalling)) { @@ -301,11 +287,6 @@ private static IncrementalStubGenerationContext CalculateStubInformation(MethodD } } - if (virtualMethodIndexData.Index < 0) - { - // Report missing or invalid index - } - if (!virtualMethodIndexData.ImplicitThisParameter && virtualMethodIndexData.Direction.HasFlag(CustomTypeMarshallerDirection.Out)) { // Report invalid configuration diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ContainingSyntaxContext.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ContainingSyntaxContext.cs index 9d194c9b250fd..3dc261df0c749 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ContainingSyntaxContext.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ContainingSyntaxContext.cs @@ -74,7 +74,15 @@ public bool Equals(ContainingSyntaxContext other) && ContainingNamespace == other.ContainingNamespace; } - public override int GetHashCode() => (ContainingNamespace?.GetHashCode() ?? 0) ^ (!ContainingSyntax.IsEmpty ? ContainingSyntax[0].Identifier.Value.GetHashCode() : 0); + public override int GetHashCode() + { + int code = ContainingNamespace.GetHashCode(); + foreach (ContainingSyntax containingSyntax in ContainingSyntax) + { + code ^= containingSyntax.Identifier.Value.GetHashCode(); + } + return code; + } public MemberDeclarationSyntax WrapMemberInContainingSyntaxWithUnsafeModifier(MemberDeclarationSyntax member) { diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj index 1033928da4f67..9506ef2d81ede 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj @@ -1,4 +1,4 @@ - + netstandard2.0 diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/ImplicitThisTests.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/ImplicitThisTests.cs index 454937d764f03..6344a8a3e9037 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/ImplicitThisTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/ImplicitThisTests.cs @@ -22,9 +22,9 @@ internal partial interface INativeObject { public static readonly NoCasting TypeKey = default; - [VirtualMethodIndex(0)] + [VirtualMethodIndex(0, ImplicitThisParameter = true)] int GetData(); - [VirtualMethodIndex(1)] + [VirtualMethodIndex(1, ImplicitThisParameter = true)] void SetData(int x); } From 8fef10969b3ed7118254ceaceb5bb927758bd6b8 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Thu, 9 Jun 2022 16:03:14 -0700 Subject: [PATCH 17/30] Fix build break --- .../ManagedToNativeVTableMethodGenerator.cs | 4 ++-- .../ComInterfaceGenerator/VtableIndexStubGenerator.cs | 11 ++++------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedToNativeVTableMethodGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedToNativeVTableMethodGenerator.cs index 454a45e648ee3..40586f01ba62b 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedToNativeVTableMethodGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedToNativeVTableMethodGenerator.cs @@ -73,13 +73,13 @@ public ManagedToNativeVTableMethodGenerator( argTypes = newArgTypes.ToImmutableArray(); } - _context = new ManagedToNativeStubCodeContext(ReturnIdentifier, ReturnIdentifier); + _context = new ManagedToNativeStubCodeContext(environment, ReturnIdentifier, ReturnIdentifier); _marshallers = new BoundGenerators(argTypes, CreateGenerator); if (_marshallers.ManagedReturnMarshaller.Generator.UsesNativeIdentifier(_marshallers.ManagedReturnMarshaller.TypeInfo, _context)) { // If we need a different native return identifier, then recreate the context with the correct identifier before we generate any code. - _context = new ManagedToNativeStubCodeContext(ReturnIdentifier, $"{ReturnIdentifier}{StubCodeContext.GeneratedNativeIdentifierSuffix}"); + _context = new ManagedToNativeStubCodeContext(environment, ReturnIdentifier, $"{ReturnIdentifier}{StubCodeContext.GeneratedNativeIdentifierSuffix}"); } IMarshallingGenerator CreateGenerator(TypePositionInfo p) diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs index 650f1e171cad6..1c121872d0317 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs @@ -336,18 +336,15 @@ private static IncrementalStubGenerationContext CalculateStubInformation(MethodD private static IMarshallingGeneratorFactory GetMarshallingGeneratorFactory(StubEnvironment env) { - InteropGenerationOptions options = new(UseMarshalType: true); - IMarshallingGeneratorFactory generatorFactory; - - generatorFactory = new UnsupportedMarshallingFactory(); - - generatorFactory = new MarshalAsMarshallingGeneratorFactory(options, generatorFactory); - IAssemblySymbol coreLibraryAssembly = env.Compilation.GetSpecialType(SpecialType.System_Object).ContainingAssembly; ITypeSymbol? disabledRuntimeMarshallingAttributeType = coreLibraryAssembly.GetTypeByMetadataName(TypeNames.System_Runtime_CompilerServices_DisableRuntimeMarshallingAttribute); bool runtimeMarshallingDisabled = disabledRuntimeMarshallingAttributeType is not null && env.Compilation.Assembly.GetAttributes().Any(attr => SymbolEqualityComparer.Default.Equals(attr.AttributeClass, disabledRuntimeMarshallingAttributeType)); + InteropGenerationOptions options = new(UseMarshalType: true, RuntimeMarshallingDisabled: runtimeMarshallingDisabled); + IMarshallingGeneratorFactory generatorFactory; + generatorFactory = new UnsupportedMarshallingFactory(); + generatorFactory = new MarshalAsMarshallingGeneratorFactory(options, generatorFactory); IMarshallingGeneratorFactory elementFactory = new AttributedMarshallingModelGeneratorFactory(generatorFactory, new AttributedMarshallingModelOptions(runtimeMarshallingDisabled)); // We don't need to include the later generator factories for collection elements // as the later generator factories only apply to parameters. From 794c4cf77a15028effbbfa9abd6985dbbaf20ef2 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Thu, 14 Jul 2022 10:33:17 -0700 Subject: [PATCH 18/30] Get the generator up to date with our newer designs and increase the test battery by sharing some code snippets with LibraryImportGenerator. --- .../MethodSignatureDiagnosticLocations.cs | 28 - .../ComInterfaceGenerator.csproj | 4 + .../ManagedToNativeVTableMethodGenerator.cs | 14 +- .../VirtualMethodIndexData.cs | 3 +- .../VtableIndexStubGenerator.cs | 18 +- .../ContainingSyntaxContext.cs | 2 +- .../TypeNames.cs | 2 +- .../Ancillary.Interop.csproj | 2 +- .../Ancillary.Interop/MarshalDirection.cs | 18 + .../VirtualMethodIndexAttribute.cs | 4 +- .../ImplicitThisTests.cs | 10 +- .../NoImplicitThisTests.cs | 10 +- .../CallingConventionForwarding.cs | 144 +-- .../CodeSnippets.cs | 278 +++-- .../ComInterfaceGenerator.Unit.Tests.csproj | 4 + .../Compiles.cs | 266 ++++- .../NativeInterfaceShape.cs | 3 + ...odeSnippets.CustomCollectionMarshalling.cs | 423 +++++++ .../CodeSnippets.CustomStructMarshalling.cs | 507 ++++++++ .../CodeSnippets.cs | 1019 +---------------- .../CompileFails.cs | 2 + .../Compiles.cs | 4 +- .../LibraryImportGenerator.Unit.Tests.csproj | 4 + 23 files changed, 1548 insertions(+), 1221 deletions(-) delete mode 100644 src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/MethodSignatureDiagnosticLocations.cs create mode 100644 src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/MarshalDirection.cs create mode 100644 src/libraries/System.Runtime.InteropServices/tests/Common/CodeSnippets.CustomCollectionMarshalling.cs create mode 100644 src/libraries/System.Runtime.InteropServices/tests/Common/CodeSnippets.CustomStructMarshalling.cs diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/MethodSignatureDiagnosticLocations.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/MethodSignatureDiagnosticLocations.cs deleted file mode 100644 index 80607c5668722..0000000000000 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/MethodSignatureDiagnosticLocations.cs +++ /dev/null @@ -1,28 +0,0 @@ -// 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.Immutable; -using System.Linq; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp.Syntax; - -namespace Microsoft.Interop -{ - public sealed record MethodSignatureDiagnosticLocations(string MethodIdentifier, ImmutableArray ManagedParameterLocations, Location FallbackLocation) - { - public MethodSignatureDiagnosticLocations(MethodDeclarationSyntax syntax) - : this(syntax.Identifier.Text, syntax.ParameterList.Parameters.Select(p => p.Identifier.GetLocation()).ToImmutableArray(), syntax.Identifier.GetLocation()) - { - } - - public bool Equals(MethodSignatureDiagnosticLocations other) - { - return MethodIdentifier == other.MethodIdentifier - && ManagedParameterLocations.SequenceEqual(other.ManagedParameterLocations) - && FallbackLocation.Equals(other.FallbackLocation); - } - - public override int GetHashCode() => throw new UnreachableException(); - } -} diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.csproj b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.csproj index bc4311cae8137..97b1fed188f2b 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.csproj +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.csproj @@ -28,6 +28,10 @@ + + + + diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedToNativeVTableMethodGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedToNativeVTableMethodGenerator.cs index 40586f01ba62b..645af622c4c6d 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedToNativeVTableMethodGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedToNativeVTableMethodGenerator.cs @@ -186,18 +186,22 @@ public BlockSyntax GenerateStubBody(int index, ImmutableArray(); tryStatements.AddRange(statements.Marshal); - var invokeStatement = statements.InvokeStatement; + + BlockSyntax fixedBlock = Block(statements.PinnedMarshal); if (_setLastError) { StatementSyntax clearLastError = MarshallerHelpers.CreateClearLastSystemErrorStatement(SuccessErrorCode); StatementSyntax getLastError = MarshallerHelpers.CreateGetLastSystemErrorStatement(LastErrorIdentifier); - invokeStatement = Block(clearLastError, invokeStatement, getLastError); + fixedBlock = fixedBlock.AddStatements(clearLastError, statements.InvokeStatement, getLastError); + } + else + { + fixedBlock = fixedBlock.AddStatements(statements.InvokeStatement); } - invokeStatement = statements.Pin.CastArray().NestFixedStatements(invokeStatement); + tryStatements.Add(statements.Pin.CastArray().NestFixedStatements(fixedBlock)); - tryStatements.Add(invokeStatement); // = true; if (!statements.GuaranteedUnmarshal.IsEmpty) { @@ -206,7 +210,7 @@ public BlockSyntax GenerateStubBody(int index, ImmutableArray allStatements = setupStatements; diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VirtualMethodIndexData.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VirtualMethodIndexData.cs index 54b63e3665bf6..c46ce9b92e987 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VirtualMethodIndexData.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VirtualMethodIndexData.cs @@ -3,6 +3,7 @@ using System; using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; using Microsoft.CodeAnalysis; namespace Microsoft.Interop @@ -14,6 +15,6 @@ internal sealed record VirtualMethodIndexData(int Index) : InteropAttributeData { public bool ImplicitThisParameter { get; init; } - public CustomTypeMarshallerDirection Direction { get; init; } + public MarshalDirection Direction { get; init; } } } diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs index 1c121872d0317..f5e5d5db08855 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs @@ -7,6 +7,7 @@ using System.Diagnostics; using System.Linq; using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; using System.Text; using System.Threading; using Microsoft.CodeAnalysis; @@ -104,7 +105,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) .WithTrackingName(StepNames.CalculateStubInformation); IncrementalValuesProvider<(MemberDeclarationSyntax, ImmutableArray)> generateManagedToNativeStub = generateStubInformation - .Where(data => data.VtableIndexData.Direction.HasFlag(CustomTypeMarshallerDirection.In)) + .Where(data => data.VtableIndexData.Direction is MarshalDirection.ManagedToUnmanaged or MarshalDirection.Bidirectional) .Select( static (data, ct) => GenerateManagedToNativeStub(data) ) @@ -194,7 +195,7 @@ private static MemberDeclarationSyntax PrintGeneratedSource( return null; } - CustomTypeMarshallerDirection direction = CustomTypeMarshallerDirection.Ref; + MarshalDirection direction = MarshalDirection.Bidirectional; bool implicitThis = true; if (namedArguments.TryGetValue(nameof(VirtualMethodIndexData.Direction), out TypedConstant directionValue)) { @@ -204,7 +205,7 @@ private static MemberDeclarationSyntax PrintGeneratedSource( return null; } // A boxed primitive can be unboxed to an enum with the same underlying type. - direction = (CustomTypeMarshallerDirection)directionValue.Value!; + direction = (MarshalDirection)directionValue.Value!; } if (namedArguments.TryGetValue(nameof(VirtualMethodIndexData.ImplicitThisParameter), out TypedConstant implicitThisValue)) { @@ -287,7 +288,7 @@ private static IncrementalStubGenerationContext CalculateStubInformation(MethodD } } - if (!virtualMethodIndexData.ImplicitThisParameter && virtualMethodIndexData.Direction.HasFlag(CustomTypeMarshallerDirection.Out)) + if (!virtualMethodIndexData.ImplicitThisParameter && virtualMethodIndexData.Direction is MarshalDirection.UnmanagedToManaged or MarshalDirection.Bidirectional) { // Report invalid configuration } @@ -340,15 +341,18 @@ private static IMarshallingGeneratorFactory GetMarshallingGeneratorFactory(StubE ITypeSymbol? disabledRuntimeMarshallingAttributeType = coreLibraryAssembly.GetTypeByMetadataName(TypeNames.System_Runtime_CompilerServices_DisableRuntimeMarshallingAttribute); bool runtimeMarshallingDisabled = disabledRuntimeMarshallingAttributeType is not null && env.Compilation.Assembly.GetAttributes().Any(attr => SymbolEqualityComparer.Default.Equals(attr.AttributeClass, disabledRuntimeMarshallingAttributeType)); - InteropGenerationOptions options = new(UseMarshalType: true, RuntimeMarshallingDisabled: runtimeMarshallingDisabled); + InteropGenerationOptions options = new(UseMarshalType: true); IMarshallingGeneratorFactory generatorFactory; generatorFactory = new UnsupportedMarshallingFactory(); + generatorFactory = new NoMarshallingInfoErrorMarshallingFactory(generatorFactory); generatorFactory = new MarshalAsMarshallingGeneratorFactory(options, generatorFactory); - IMarshallingGeneratorFactory elementFactory = new AttributedMarshallingModelGeneratorFactory(generatorFactory, new AttributedMarshallingModelOptions(runtimeMarshallingDisabled)); + + IMarshallingGeneratorFactory elementFactory = new AttributedMarshallingModelGeneratorFactory( + new CharMarshallingGeneratorFactory(generatorFactory, useBlittableMarshallerForUtf16: true), new AttributedMarshallingModelOptions(runtimeMarshallingDisabled, MarshalMode.ElementIn, MarshalMode.ElementRef, MarshalMode.ElementOut)); // We don't need to include the later generator factories for collection elements // as the later generator factories only apply to parameters. - generatorFactory = new AttributedMarshallingModelGeneratorFactory(generatorFactory, elementFactory, new AttributedMarshallingModelOptions(runtimeMarshallingDisabled)); + generatorFactory = new AttributedMarshallingModelGeneratorFactory(generatorFactory, elementFactory, new AttributedMarshallingModelOptions(runtimeMarshallingDisabled, MarshalMode.ManagedToUnmanagedIn, MarshalMode.ManagedToUnmanagedRef, MarshalMode.ManagedToUnmanagedOut)); generatorFactory = new ByValueContentsMarshalKindValidator(generatorFactory); return generatorFactory; diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ContainingSyntaxContext.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ContainingSyntaxContext.cs index 3dc261df0c749..c5316b50fd730 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ContainingSyntaxContext.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ContainingSyntaxContext.cs @@ -76,7 +76,7 @@ public bool Equals(ContainingSyntaxContext other) public override int GetHashCode() { - int code = ContainingNamespace.GetHashCode(); + int code = ContainingNamespace?.GetHashCode() ?? 0; foreach (ContainingSyntax containingSyntax in ContainingSyntax) { code ^= containingSyntax.Identifier.Value.GetHashCode(); diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeNames.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeNames.cs index 919b13b1cfbf9..9fb72bdb94c02 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeNames.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeNames.cs @@ -28,7 +28,7 @@ public static class TypeNames public const string UnmanagedCallConvAttribute = "System.Runtime.InteropServices.UnmanagedCallConvAttribute"; - public const string VirtualMethodIndexAttribute = "System.Runtime.InteropServices.VirtualMethodIndexAttribute"; + public const string VirtualMethodIndexAttribute = "System.Runtime.InteropServices.Marshalling.VirtualMethodIndexAttribute"; public const string IUnmanagedVirtualMethodTableProvider = "System.Runtime.InteropServices.IUnmanagedVirtualMethodTableProvider"; diff --git a/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/Ancillary.Interop.csproj b/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/Ancillary.Interop.csproj index 629c77c4b3493..526532b35bc1a 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/Ancillary.Interop.csproj +++ b/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/Ancillary.Interop.csproj @@ -3,7 +3,7 @@ Microsoft.Interop.Ancillary $(NetCoreAppCurrent) - System.Runtime.InteropServices + System.Runtime.InteropServices.Marshalling enable true APIs required for usage of the LibraryImportGenerator and related tools. diff --git a/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/MarshalDirection.cs b/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/MarshalDirection.cs new file mode 100644 index 0000000000000..28aa98bce7410 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/MarshalDirection.cs @@ -0,0 +1,18 @@ +// 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.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace System.Runtime.InteropServices.Marshalling +{ + public enum MarshalDirection + { + ManagedToUnmanaged = 0, + UnmanagedToManaged = 1, + Bidirectional = 2 + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/VirtualMethodIndexAttribute.cs b/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/VirtualMethodIndexAttribute.cs index 1cada51d6dede..52f1341427211 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/VirtualMethodIndexAttribute.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/VirtualMethodIndexAttribute.cs @@ -8,7 +8,7 @@ using System.Text; using System.Threading.Tasks; -namespace System.Runtime.InteropServices +namespace System.Runtime.InteropServices.Marshalling { [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] public class VirtualMethodIndexAttribute : Attribute @@ -22,7 +22,7 @@ public VirtualMethodIndexAttribute(int index) public bool ImplicitThisParameter { get; set; } = true; - public CustomTypeMarshallerDirection Direction { get; set; } = CustomTypeMarshallerDirection.Ref; + public MarshalDirection Direction { get; set; } = MarshalDirection.Bidirectional; /// /// Gets or sets how to marshal string arguments to the method. diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/ImplicitThisTests.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/ImplicitThisTests.cs index 6344a8a3e9037..0c88984c9fec5 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/ImplicitThisTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/ImplicitThisTests.cs @@ -46,14 +46,10 @@ public void Dispose() } } - [CustomTypeMarshaller(typeof(NativeObject), CustomTypeMarshallerKind.Value, Direction = CustomTypeMarshallerDirection.Out, Features = CustomTypeMarshallerFeatures.TwoStageMarshalling)] - struct NativeObjectMarshaller + [CustomMarshaller(typeof(NativeObject), MarshalMode.ManagedToUnmanagedOut, typeof(NativeObjectMarshaller))] + static class NativeObjectMarshaller { - private void* _nativeValue; - - public void FromNativeValue(void* value) => _nativeValue = value; - - public NativeObject ToManaged() => new NativeObject(_nativeValue); + public static NativeObject ConvertToManaged(void* value) => new NativeObject(value); } [LibraryImport(NativeExportsNE_Binary, EntryPoint = "new_native_object")] diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/NoImplicitThisTests.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/NoImplicitThisTests.cs index dd1e984eca8df..c24892b62c7e8 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/NoImplicitThisTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/NoImplicitThisTests.cs @@ -41,14 +41,10 @@ public StaticMethodTable(void* vtableStart) public VirtualMethodTableInfo GetVirtualMethodTableInfoForKey(NoCasting typeKey) => new VirtualMethodTableInfo(IntPtr.Zero, new ReadOnlySpan(_vtableStart, 2)); } - [CustomTypeMarshaller(typeof(StaticMethodTable), CustomTypeMarshallerKind.Value, Direction = CustomTypeMarshallerDirection.Out, Features = CustomTypeMarshallerFeatures.TwoStageMarshalling)] - struct StaticMethodTableMarshaller + [CustomMarshaller(typeof(StaticMethodTable), MarshalMode.ManagedToUnmanagedOut, typeof(StaticMethodTableMarshaller))] + static class StaticMethodTableMarshaller { - private void* _nativeValue; - - public void FromNativeValue(void* value) => _nativeValue = value; - - public StaticMethodTable ToManaged() => new StaticMethodTable(_nativeValue); + public static StaticMethodTable ConvertToManaged(void* value) => new StaticMethodTable(value); } [LibraryImport(NativeExportsNE_Binary, EntryPoint = "get_static_function_table")] diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CallingConventionForwarding.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CallingConventionForwarding.cs index 9ec1ecc2a5870..606f432617fea 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CallingConventionForwarding.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CallingConventionForwarding.cs @@ -19,16 +19,18 @@ public class CallingConventionForwarding [Fact] public async Task NoSpecifiedCallConvForwardsDefault() { - string source = @" -using System.Runtime.InteropServices; - -readonly record struct NoCasting {} -partial interface INativeAPI -{ - public static readonly NoCasting TypeKey = default; - [VirtualMethodIndex(0)] - void Method(); -}"; + string source = """ + using System.Runtime.InteropServices; + using System.Runtime.InteropServices.Marshalling; + + readonly record struct NoCasting {} + partial interface INativeAPI + { + public static readonly NoCasting TypeKey = default; + [VirtualMethodIndex(0)] + void Method(); + } + """; Compilation comp = await TestUtils.CreateCompilation(source); // Allow the Native nested type name to be missing in the pre-source-generator compilation TestUtils.AssertPreSourceGeneratorCompilation(comp); @@ -44,17 +46,19 @@ partial interface INativeAPI [Fact] public async Task SuppressGCTransitionAttributeForwarded() { - string source = @" -using System.Runtime.InteropServices; - -readonly record struct NoCasting {} -partial interface INativeAPI -{ - public static readonly NoCasting TypeKey = default; - [SuppressGCTransitionAttribute] - [VirtualMethodIndex(0)] - void Method(); -}"; + string source = """ + using System.Runtime.InteropServices; + using System.Runtime.InteropServices.Marshalling; + + readonly record struct NoCasting {} + partial interface INativeAPI + { + public static readonly NoCasting TypeKey = default; + [SuppressGCTransitionAttribute] + [VirtualMethodIndex(0)] + void Method(); + } + """; Compilation comp = await TestUtils.CreateCompilation(source); // Allow the Native nested type name to be missing in the pre-source-generator compilation TestUtils.AssertPreSourceGeneratorCompilation(comp); @@ -70,17 +74,19 @@ partial interface INativeAPI [Fact] public async Task EmptyUnmanagedCallConvAttributeForwarded() { - string source = @" -using System.Runtime.InteropServices; - -readonly record struct NoCasting {} -partial interface INativeAPI -{ - public static readonly NoCasting TypeKey = default; - [UnmanagedCallConv] - [VirtualMethodIndex(0)] - void Method(); -}"; + string source = """ + using System.Runtime.InteropServices; + using System.Runtime.InteropServices.Marshalling; + + readonly record struct NoCasting {} + partial interface INativeAPI + { + public static readonly NoCasting TypeKey = default; + [UnmanagedCallConv] + [VirtualMethodIndex(0)] + void Method(); + } + """; Compilation comp = await TestUtils.CreateCompilation(source); // Allow the Native nested type name to be missing in the pre-source-generator compilation TestUtils.AssertPreSourceGeneratorCompilation(comp); @@ -96,17 +102,19 @@ partial interface INativeAPI [Fact] public async Task SimpleUnmanagedCallConvAttributeForwarded() { - string source = @" -using System.Runtime.InteropServices; - -readonly record struct NoCasting {} -partial interface INativeAPI -{ - public static readonly NoCasting TypeKey = default; - [UnmanagedCallConv(CallConvs = new[] { typeof(CallConvCdecl) })] - [VirtualMethodIndex(0)] - void Method(); -}"; + string source = """ + using System.Runtime.InteropServices; + using System.Runtime.InteropServices.Marshalling; + + readonly record struct NoCasting {} + partial interface INativeAPI + { + public static readonly NoCasting TypeKey = default; + [UnmanagedCallConv(CallConvs = new[] { typeof(CallConvCdecl) })] + [VirtualMethodIndex(0)] + void Method(); + } + """; Compilation comp = await TestUtils.CreateCompilation(source); // Allow the Native nested type name to be missing in the pre-source-generator compilation TestUtils.AssertPreSourceGeneratorCompilation(comp); @@ -122,17 +130,19 @@ partial interface INativeAPI [Fact] public async Task ComplexUnmanagedCallConvAttributeForwarded() { - string source = @" -using System.Runtime.InteropServices; - -readonly record struct NoCasting {} -partial interface INativeAPI -{ - public static readonly NoCasting TypeKey = default; - [UnmanagedCallConv(CallConvs = new[] { typeof(CallConvCdecl), typeof(CallConvMemberFunction) })] - [VirtualMethodIndex(0)] - void Method(); -}"; + string source = """ + using System.Runtime.InteropServices; + using System.Runtime.InteropServices.Marshalling; + + readonly record struct NoCasting {} + partial interface INativeAPI + { + public static readonly NoCasting TypeKey = default; + [UnmanagedCallConv(CallConvs = new[] { typeof(CallConvCdecl), typeof(CallConvMemberFunction) })] + [VirtualMethodIndex(0)] + void Method(); + } + """; Compilation comp = await TestUtils.CreateCompilation(source); // Allow the Native nested type name to be missing in the pre-source-generator compilation TestUtils.AssertPreSourceGeneratorCompilation(comp); @@ -154,18 +164,20 @@ partial interface INativeAPI [Fact] public async Task ComplexUnmanagedCallConvAttributeWithSuppressGCTransitionForwarded() { - string source = @" -using System.Runtime.InteropServices; - -readonly record struct NoCasting {} -partial interface INativeAPI -{ - public static readonly NoCasting TypeKey = default; - [SuppressGCTransition] - [UnmanagedCallConv(CallConvs = new[] { typeof(CallConvCdecl), typeof(CallConvMemberFunction) })] - [VirtualMethodIndex(0)] - void Method(); -}"; + string source = """ + using System.Runtime.InteropServices; + using System.Runtime.InteropServices.Marshalling; + + readonly record struct NoCasting {} + partial interface INativeAPI + { + public static readonly NoCasting TypeKey = default; + [SuppressGCTransition] + [UnmanagedCallConv(CallConvs = new[] { typeof(CallConvCdecl), typeof(CallConvMemberFunction) })] + [VirtualMethodIndex(0)] + void Method(); + } + """; Compilation comp = await TestUtils.CreateCompilation(source); // Allow the Native nested type name to be missing in the pre-source-generator compilation TestUtils.AssertPreSourceGeneratorCompilation(comp); 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 35ade46c6e2b1..a2a14d091154e 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 @@ -7,12 +7,24 @@ using System.Text; using System.Threading.Tasks; -namespace ComInterfaceGenerator.Unit.Tests +namespace Microsoft.Interop.UnitTests { - internal static class CodeSnippets + internal static partial class CodeSnippets { + public static readonly string DisableRuntimeMarshalling = "[assembly:System.Runtime.CompilerServices.DisableRuntimeMarshalling]"; + public static readonly string UsingSystemRuntimeInteropServicesMarshalling = "using System.Runtime.InteropServices.Marshalling;"; + + public static string NativeInterfaceUsage() => @" +// Try using the generated native interface +sealed class NativeAPI : IUnmanagedVirtualMethodTableProvider, INativeAPI.Native +{ + public VirtualMethodTableInfo GetVirtualMethodTableInfoForKey(NoCasting typeKey) => throw null; +} +"; + public static readonly string SpecifiedMethodIndexNoExplicitParameters = @" using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; readonly record struct NoCasting {} partial interface INativeAPI @@ -20,17 +32,11 @@ partial interface INativeAPI public static readonly NoCasting TypeKey = default; [VirtualMethodIndex(0)] void Method(); -} - -// Try using the generated native interface -sealed class NativeAPI : IUnmanagedVirtualMethodTableProvider, INativeAPI.Native -{ - public VirtualMethodTableInfo GetVirtualMethodTableInfoForKey(NoCasting typeKey) => throw null; -} -"; +}" + NativeInterfaceUsage(); public static readonly string SpecifiedMethodIndexNoExplicitParametersNoImplicitThis = @" using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; readonly record struct NoCasting {} partial interface INativeAPI @@ -38,18 +44,12 @@ partial interface INativeAPI public static readonly NoCasting TypeKey = default; [VirtualMethodIndex(0, ImplicitThisParameter = false)] void Method(); -} - -// Try using the generated native interface -sealed class NativeAPI : IUnmanagedVirtualMethodTableProvider, INativeAPI.Native -{ - public VirtualMethodTableInfo GetVirtualMethodTableInfoForKey(NoCasting typeKey) => throw null; -} -"; +}" + NativeInterfaceUsage(); public static readonly string SpecifiedMethodIndexNoExplicitParametersCallConvWithCallingConventions = @" using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; readonly record struct NoCasting {} partial interface INativeAPI @@ -76,19 +76,28 @@ partial interface INativeAPI [SuppressGCTransition] [VirtualMethodIndex(4)] void Method4(); -} +}" + NativeInterfaceUsage(); + public static string BasicParametersAndModifiers(string typeName, string preDeclaration = "") => $@" +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; +{preDeclaration} -// Try using the generated native interface -sealed class NativeAPI : IUnmanagedVirtualMethodTableProvider, INativeAPI.Native -{ - public VirtualMethodTableInfo GetVirtualMethodTableInfoForKey(NoCasting typeKey) => throw null; -} -"; +[assembly:DisableRuntimeMarshalling] - public static string BasicParametersAndModifiers(string typeName) => $@" +readonly record struct NoCasting {{}} +partial interface INativeAPI +{{ + public static readonly NoCasting TypeKey = default; + [VirtualMethodIndex(0)] + {typeName} Method({typeName} value, in {typeName} inValue, ref {typeName} refValue, out {typeName} outValue); +}}" + NativeInterfaceUsage(); + public static string BasicParametersAndModifiers() => BasicParametersAndModifiers(typeof(T).FullName!); + public static string BasicParametersAndModifiersNoRef(string typeName, string preDeclaration = "") => $@" using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.InteropServices.Marshalling; +{preDeclaration} [assembly:DisableRuntimeMarshalling] @@ -97,20 +106,41 @@ partial interface INativeAPI {{ public static readonly NoCasting TypeKey = default; [VirtualMethodIndex(0)] + {typeName} Method({typeName} value, in {typeName} inValue, out {typeName} outValue); +}}" + NativeInterfaceUsage(); + public static string BasicParametersAndModifiersNoImplicitThis(string typeName) => $@" +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; + +readonly record struct NoCasting {{}} +partial interface INativeAPI +{{ + public static readonly NoCasting TypeKey = default; + [VirtualMethodIndex(0, ImplicitThisParameter = false)] {typeName} Method({typeName} value, in {typeName} inValue, ref {typeName} refValue, out {typeName} outValue); -}} +}}" + NativeInterfaceUsage(); -// Try using the generated native interface -sealed class NativeAPI : IUnmanagedVirtualMethodTableProvider, INativeAPI.Native + public static string BasicParametersAndModifiersNoImplicitThis() => BasicParametersAndModifiersNoImplicitThis(typeof(T).FullName!); + + public static string BasicParameterByValue(string typeName, string preDeclaration = "") => $@" +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; +{preDeclaration} + +readonly record struct NoCasting {{}} +partial interface INativeAPI {{ - public VirtualMethodTableInfo GetVirtualMethodTableInfoForKey(NoCasting typeKey) => throw null; -}} -"; - public static string BasicParametersAndModifiers() => BasicParametersAndModifiers(typeof(T).FullName!); - public static string BasicParametersAndModifiersNoImplicitThis(string typeName) => $@" + public static readonly NoCasting TypeKey = default; + [VirtualMethodIndex(0, ImplicitThisParameter = false)] + void Method({typeName} value); +}}" + NativeInterfaceUsage(); + public static string BasicParameterWithByRefModifier(string modifier, string typeName, string preDeclaration = "") => $@" using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.InteropServices.Marshalling; +{preDeclaration} [assembly:DisableRuntimeMarshalling] @@ -119,78 +149,160 @@ partial interface INativeAPI {{ public static readonly NoCasting TypeKey = default; [VirtualMethodIndex(0, ImplicitThisParameter = false)] - {typeName} Method({typeName} value, in {typeName} inValue, ref {typeName} refValue, out {typeName} outValue); -}} + void Method({modifier} {typeName} value); +}}" + NativeInterfaceUsage(); + public static string BasicReturnType(string typeName) => $@" +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; -// Try using the generated native interface -sealed class NativeAPI : IUnmanagedVirtualMethodTableProvider, INativeAPI.Native +readonly record struct NoCasting {{}} +partial interface INativeAPI {{ - public VirtualMethodTableInfo GetVirtualMethodTableInfoForKey(NoCasting typeKey) => throw null; -}} -"; - - public static string BasicParametersAndModifiersNoImplicitThis() => BasicParametersAndModifiersNoImplicitThis(typeof(T).FullName!); + public static readonly NoCasting TypeKey = default; + [VirtualMethodIndex(0, ImplicitThisParameter = false)] + {typeName} Method(); +}}" + NativeInterfaceUsage(); + public static string MarshalUsingParametersAndModifiers(string typeName, string marshallerTypeName, string preDeclaration = "") => $@" +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; +{preDeclaration} - public const string CustomTypeMarshallingTestsTypeName = "S"; +readonly record struct NoCasting {{}} +partial interface INativeAPI +{{ + public static readonly NoCasting TypeKey = default; + [VirtualMethodIndex(0)] + [return: MarshalUsing(typeof({marshallerTypeName}))] + {typeName} Method( + [MarshalUsing(typeof({marshallerTypeName}))] {typeName} p, + [MarshalUsing(typeof({marshallerTypeName}))] in {typeName} pIn, + [MarshalUsing(typeof({marshallerTypeName}))] ref {typeName} pRef, + [MarshalUsing(typeof({marshallerTypeName}))] out {typeName} pOut); +}}" + NativeInterfaceUsage(); + public static string MarshalUsingCollectionCountInfoParametersAndModifiers() => MarshalUsingCollectionCountInfoParametersAndModifiers(typeof(T).ToString()); + public static string MarshalUsingCollectionCountInfoParametersAndModifiers(string collectionType, string preDeclaration = "") => $@" +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; +{preDeclaration} - public static string SimpleCustomTypeMarshallingDeclaration = $@" -[NativeMarshalling(typeof(Marshaller))] -struct {CustomTypeMarshallingTestsTypeName} {{}} +[assembly:DisableRuntimeMarshalling] -[CustomTypeMarshaller(typeof({CustomTypeMarshallingTestsTypeName}))] -struct Marshaller +readonly record struct NoCasting {{}} +partial interface INativeAPI {{ - public Marshaller({CustomTypeMarshallingTestsTypeName} managed) {{}} + public static readonly NoCasting TypeKey = default; + [VirtualMethodIndex(0)] + [return:MarshalUsing(ConstantElementCount=10)] + {collectionType} Method( + {collectionType} p, + in {collectionType} pIn, + int pRefSize, + [MarshalUsing(CountElementName = ""pRefSize"")] ref {collectionType} pRef, + [MarshalUsing(CountElementName = ""pOutSize"")] out {collectionType} pOut, + out int pOutSize); +}}" + NativeInterfaceUsage(); + public static string MarshalUsingCollectionParametersAndModifiers(string collectionType, string marshallerType, string preDeclaration = "") => $@" +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; +{preDeclaration} - public {CustomTypeMarshallingTestsTypeName} ToManaged() => throw null; -}} -"; +[assembly:DisableRuntimeMarshalling] - public static string TwoStageCustomTypeMarshallingDeclaration = $@" -[NativeMarshalling(typeof(Marshaller))] -struct {CustomTypeMarshallingTestsTypeName} {{}} +readonly record struct NoCasting {{}} +partial interface INativeAPI +{{ + public static readonly NoCasting TypeKey = default; + [VirtualMethodIndex(0)] + [return:MarshalUsing(typeof({marshallerType}), ConstantElementCount=10)] + {collectionType} Method( + [MarshalUsing(typeof({marshallerType}))] {collectionType} p, + [MarshalUsing(typeof({marshallerType}))] in {collectionType} pIn, + int pRefSize, + [MarshalUsing(typeof({marshallerType}), CountElementName = ""pRefSize"")] ref {collectionType} pRef, + [MarshalUsing(typeof({marshallerType}), CountElementName = ""pOutSize"")] out {collectionType} pOut, + out int pOutSize + ); +}}" + NativeInterfaceUsage(); + public static string MarshalUsingCollectionReturnValueLength(string collectionType, string marshallerType, string preDeclaration = "") => $@" +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; +{preDeclaration} -[CustomTypeMarshaller(typeof({CustomTypeMarshallingTestsTypeName}), Features = CustomTypeMarshallerFeatures.TwoStageMarshalling)] -struct Marshaller +[assembly:DisableRuntimeMarshalling] + +readonly record struct NoCasting {{}} +partial interface INativeAPI {{ - public Marshaller({CustomTypeMarshallingTestsTypeName} managed) {{}} + public static readonly NoCasting TypeKey = default; + [VirtualMethodIndex(0)] + int Method( + [MarshalUsing(typeof({marshallerType}), CountElementName = MarshalUsingAttribute.ReturnsCountValue)] out {collectionType} pOut + ); +}}" + NativeInterfaceUsage(); - public {CustomTypeMarshallingTestsTypeName} ToManaged() => throw null; + public static string MarshalUsingCollectionOutConstantLength(string collectionType, string predeclaration = "") => $@" +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; +{predeclaration} - public int ToNativeValue() => throw null; +[assembly:DisableRuntimeMarshalling] - public void FromNativeValue(int i) => throw null; +readonly record struct NoCasting {{}} +partial interface INativeAPI +{{ + public static readonly NoCasting TypeKey = default; + [VirtualMethodIndex(0)] + int Method( + [MarshalUsing(ConstantElementCount = 10)] out {collectionType} pOut + ); }} "; + public static string MarshalUsingCollectionReturnConstantLength(string collectionType, string predeclaration = "") => $@" +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; +{predeclaration} - public static string OptionalCallerAllocatedBufferMarshallingDeclaration = $@" -[NativeMarshalling(typeof(Marshaller))] -struct {CustomTypeMarshallingTestsTypeName} -{{ -}} +[assembly:DisableRuntimeMarshalling] -[CustomTypeMarshaller(typeof({CustomTypeMarshallingTestsTypeName}), Features = CustomTypeMarshallerFeatures.CallerAllocatedBuffer, BufferSize = 1)] -struct Marshaller +readonly record struct NoCasting {{}} +partial interface INativeAPI {{ - public Marshaller({CustomTypeMarshallingTestsTypeName} s, System.Span b) {{}} - public Marshaller({CustomTypeMarshallingTestsTypeName} managed) {{}} - - public {CustomTypeMarshallingTestsTypeName} ToManaged() => throw null; + public static readonly NoCasting TypeKey = default; + [VirtualMethodIndex(0)] + [return:MarshalUsing(ConstantElementCount = 10)] + {collectionType} Method(); }} "; + public static string CustomElementMarshalling(string collectionType, string elementMarshaller, string predeclaration = "") => $@" +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; +{predeclaration} - public static string UnmanagedResourcesCustomTypeMarshallingDeclaration = $@" -[NativeMarshalling(typeof(Marshaller))] -struct {CustomTypeMarshallingTestsTypeName} {{}} +[assembly:DisableRuntimeMarshalling] -[CustomTypeMarshaller(typeof({CustomTypeMarshallingTestsTypeName}), Features = CustomTypeMarshallerFeatures.UnmanagedResources)] -struct Marshaller +readonly record struct NoCasting {{}} +partial interface INativeAPI {{ - public Marshaller({CustomTypeMarshallingTestsTypeName} managed) {{}} - - public {CustomTypeMarshallingTestsTypeName} ToManaged() => throw null; - - public void FreeNative() {{}} + public static readonly NoCasting TypeKey = default; + [VirtualMethodIndex(0)] + [return:MarshalUsing(ConstantElementCount=10)] + [return:MarshalUsing(typeof({elementMarshaller}), ElementIndirectionDepth = 1)] + TestCollection Method( + [MarshalUsing(typeof({elementMarshaller}), ElementIndirectionDepth = 1)] {collectionType} p, + [MarshalUsing(typeof({elementMarshaller}), ElementIndirectionDepth = 1)] in {collectionType} pIn, + int pRefSize, + [MarshalUsing(CountElementName = ""pRefSize""), MarshalUsing(typeof({elementMarshaller}), ElementIndirectionDepth = 1)] ref {collectionType} pRef, + [MarshalUsing(CountElementName = ""pOutSize"")][MarshalUsing(typeof({elementMarshaller}), ElementIndirectionDepth = 1)] out {collectionType} pOut, + out int pOutSize + ); }} "; } diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/ComInterfaceGenerator.Unit.Tests.csproj b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/ComInterfaceGenerator.Unit.Tests.csproj index ea25b2b4edb6d..273dd713a02b5 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/ComInterfaceGenerator.Unit.Tests.csproj +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/ComInterfaceGenerator.Unit.Tests.csproj @@ -13,6 +13,10 @@ Link="Common\SourceGenerators\LiveReferencePack.cs" /> + + 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 53ebacea6ba70..7a41e72e5fabd 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 @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Runtime.CompilerServices; using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.Interop.UnitTests; @@ -12,60 +13,249 @@ namespace ComInterfaceGenerator.Unit.Tests { public class Compiles { - public static IEnumerable VTableIndexCodeSnippetsToCompile() + private static string ID( + [CallerLineNumber] int lineNumber = 0, + [CallerFilePath] string? filePath = null) + => TestUtils.GetFileLineName(lineNumber, filePath); + + public static IEnumerable CodeSnippetsToCompile() { - yield return new[] { CodeSnippets.SpecifiedMethodIndexNoExplicitParameters }; - yield return new[] { CodeSnippets.SpecifiedMethodIndexNoExplicitParametersNoImplicitThis }; - yield return new[] { CodeSnippets.SpecifiedMethodIndexNoExplicitParametersCallConvWithCallingConventions }; + yield return new[] { ID(), CodeSnippets.SpecifiedMethodIndexNoExplicitParameters }; + yield return new[] { ID(), CodeSnippets.SpecifiedMethodIndexNoExplicitParametersNoImplicitThis }; + yield return new[] { ID(), CodeSnippets.SpecifiedMethodIndexNoExplicitParametersCallConvWithCallingConventions }; // Basic marshalling validation - yield return new[] { CodeSnippets.BasicParametersAndModifiers() }; - yield return new[] { CodeSnippets.BasicParametersAndModifiers() }; - yield return new[] { CodeSnippets.BasicParametersAndModifiers() }; - yield return new[] { CodeSnippets.BasicParametersAndModifiers() }; - yield return new[] { CodeSnippets.BasicParametersAndModifiers() }; - yield return new[] { CodeSnippets.BasicParametersAndModifiers() }; - yield return new[] { CodeSnippets.BasicParametersAndModifiers() }; - yield return new[] { CodeSnippets.BasicParametersAndModifiers() }; - yield return new[] { CodeSnippets.BasicParametersAndModifiers() }; - yield return new[] { CodeSnippets.BasicParametersAndModifiers() }; - yield return new[] { CodeSnippets.BasicParametersAndModifiers() }; - yield return new[] { CodeSnippets.BasicParametersAndModifiers() }; - yield return new[] { CodeSnippets.BasicParametersAndModifiersNoImplicitThis() }; - yield return new[] { CodeSnippets.BasicParametersAndModifiersNoImplicitThis() }; - yield return new[] { CodeSnippets.BasicParametersAndModifiersNoImplicitThis() }; - yield return new[] { CodeSnippets.BasicParametersAndModifiersNoImplicitThis() }; - yield return new[] { CodeSnippets.BasicParametersAndModifiersNoImplicitThis() }; - yield return new[] { CodeSnippets.BasicParametersAndModifiersNoImplicitThis() }; - yield return new[] { CodeSnippets.BasicParametersAndModifiersNoImplicitThis() }; - yield return new[] { CodeSnippets.BasicParametersAndModifiersNoImplicitThis() }; - yield return new[] { CodeSnippets.BasicParametersAndModifiersNoImplicitThis() }; - yield return new[] { CodeSnippets.BasicParametersAndModifiersNoImplicitThis() }; - yield return new[] { CodeSnippets.BasicParametersAndModifiersNoImplicitThis() }; - yield return new[] { CodeSnippets.BasicParametersAndModifiersNoImplicitThis() }; + yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiersNoImplicitThis() }; + yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiersNoImplicitThis() }; + yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiersNoImplicitThis() }; + yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiersNoImplicitThis() }; + yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiersNoImplicitThis() }; + yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiersNoImplicitThis() }; + yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiersNoImplicitThis() }; + yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiersNoImplicitThis() }; + yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiersNoImplicitThis() }; + yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiersNoImplicitThis() }; + yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiersNoImplicitThis() }; + yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiersNoImplicitThis() }; - // Attributed marshalling model validation - yield return new[] { CodeSnippets.BasicParametersAndModifiers(CodeSnippets.CustomTypeMarshallingTestsTypeName) + CodeSnippets.SimpleCustomTypeMarshallingDeclaration }; - yield return new[] { CodeSnippets.BasicParametersAndModifiers(CodeSnippets.CustomTypeMarshallingTestsTypeName) + CodeSnippets.TwoStageCustomTypeMarshallingDeclaration }; - yield return new[] { CodeSnippets.BasicParametersAndModifiers(CodeSnippets.CustomTypeMarshallingTestsTypeName) + CodeSnippets.OptionalCallerAllocatedBufferMarshallingDeclaration }; - yield return new[] { CodeSnippets.BasicParametersAndModifiers(CodeSnippets.CustomTypeMarshallingTestsTypeName) + CodeSnippets.UnmanagedResourcesCustomTypeMarshallingDeclaration }; + // Custom type marshalling + yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.ParametersAndModifiers }; + yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.MarshalUsingParametersAndModifiers }; + yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.NativeToManagedOnlyOutParameter }; + yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.NativeToManagedFinallyOnlyOutParameter }; + yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.NativeToManagedOnlyReturnValue }; + yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.NativeToManagedFinallyOnlyReturnValue }; + yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.ByValueInParameter }; + yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.PinByValueInParameter }; + yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.StackallocByValueInParameter }; + yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.RefParameter }; + yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.StackallocParametersAndModifiersNoRef }; + yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.OptionalStackallocParametersAndModifiers }; + yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.DefaultModeByValueInParameter }; + yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.DefaultModeReturnValue }; + yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.ParametersAndModifiers }; + yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.ParametersAndModifiersWithFree }; + yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.ParametersAndModifiersWithOnInvoked }; + yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.MarshalUsingParametersAndModifiers }; + yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.NativeToManagedOnlyOutParameter }; + yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.NativeToManagedFinallyOnlyOutParameter }; + yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.NativeToManagedOnlyReturnValue }; + yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.NativeToManagedFinallyOnlyReturnValue }; + yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.ByValueInParameter }; + yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.StackallocByValueInParameter }; + yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.PinByValueInParameter }; + yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.MarshallerPinByValueInParameter }; + yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.RefParameter }; + yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.StackallocParametersAndModifiersNoRef }; + yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.OptionalStackallocParametersAndModifiers }; + yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.DefaultModeByValueInParameter }; + yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.DefaultModeReturnValue }; // SafeHandles - yield return new[] { CodeSnippets.BasicParametersAndModifiers("Microsoft.Win32.SafeHandles.SafeFileHandle") }; + yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiers("Microsoft.Win32.SafeHandles.SafeFileHandle") }; + } + + public static IEnumerable CustomCollections() + { + // Custom collection marshalling + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValue() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValue() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValue() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValue() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValue() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValue() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValue() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValue() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValue() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValue() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValue() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValue() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueWithPinning() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueWithPinning() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueWithPinning() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueWithPinning() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueWithPinning() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueWithPinning() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueWithPinning() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueWithPinning() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueWithPinning() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueWithPinning() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueWithPinning() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueWithPinning() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValue() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValue() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValue() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValue() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValue() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValue() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValue() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValue() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValue() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValue() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValue() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValue() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithPinning() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithPinning() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithPinning() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithPinning() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithPinning() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithPinning() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithPinning() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithPinning() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithPinning() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithPinning() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithPinning() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithPinning() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithStaticPinning() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithStaticPinning() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithStaticPinning() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithStaticPinning() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithStaticPinning() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithStaticPinning() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithStaticPinning() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithStaticPinning() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithStaticPinning() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithStaticPinning() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithStaticPinning() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithStaticPinning() }; + yield return new[] { ID(), CodeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomMarshallerReturnValueLength() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.NativeToManagedOnlyOutParameter() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.NativeToManagedOnlyReturnValue() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.NestedMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.NonBlittableElementByValue }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.NonBlittableElementParametersAndModifiers }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.NonBlittableElementNativeToManagedOnlyOutParameter }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.NonBlittableElementNativeToManagedOnlyReturnValue }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomElementMarshalling }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.CustomMarshallerReturnValueLength() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.NativeToManagedOnlyOutParameter() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.NativeToManagedOnlyReturnValue() }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.NonBlittableElementByValue }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.NonBlittableElementParametersAndModifiers }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.NonBlittableElementNativeToManagedOnlyOutParameter }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.NonBlittableElementNativeToManagedOnlyReturnValue }; + yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.CustomElementMarshalling }; } [Theory] - [MemberData(nameof(VTableIndexCodeSnippetsToCompile))] - public async Task ValidateVTableIndexSnippets(string source) + [MemberData(nameof(CodeSnippetsToCompile))] + [MemberData(nameof(CustomCollections))] + public async Task ValidateVTableIndexSnippets(string id, string source) { + _ = id; Compilation comp = await TestUtils.CreateCompilation(source); // Allow the Native nested type name to be missing in the pre-source-generator compilation - TestUtils.AssertPreSourceGeneratorCompilation(comp, "CS0426"); + // We allow duplicate usings here since some of the shared snippets add a using for System.Runtime.InteropServices.Marshalling when we already have one in our base snippets. + TestUtils.AssertPreSourceGeneratorCompilation(comp, "CS0426", "CS0105"); var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.VtableIndexStubGenerator()); Assert.Empty(generatorDiags); - TestUtils.AssertPostSourceGeneratorCompilation(newComp); + TestUtils.AssertPostSourceGeneratorCompilation(newComp, "CS0105"); } } } diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/NativeInterfaceShape.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/NativeInterfaceShape.cs index 643fe93630031..26305c41b2276 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/NativeInterfaceShape.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/NativeInterfaceShape.cs @@ -21,6 +21,7 @@ public async Task NativeInterfaceNestedInUserInterface() { string source = @" using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; readonly record struct NoCasting {} partial interface INativeAPI @@ -46,6 +47,7 @@ public async Task NativeInterfaceInheritsFromUserInterface() { string source = @" using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; readonly record struct NoCasting {} partial interface INativeAPI @@ -71,6 +73,7 @@ public async Task NativeInterfaceHasDynamicInterfaceCastableImplementationAttrib { string source = @" using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; readonly record struct NoCasting {} partial interface INativeAPI diff --git a/src/libraries/System.Runtime.InteropServices/tests/Common/CodeSnippets.CustomCollectionMarshalling.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/CodeSnippets.CustomCollectionMarshalling.cs new file mode 100644 index 0000000000000..089de31b65a98 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/Common/CodeSnippets.CustomCollectionMarshalling.cs @@ -0,0 +1,423 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.Interop.UnitTests +{ + internal static partial class CodeSnippets + { + public static class CustomCollectionMarshalling + { + public static string TestCollection(bool defineNativeMarshalling = true) => $@" +{(defineNativeMarshalling ? "[NativeMarshalling(typeof(Marshaller<,>))]" : string.Empty)} +class TestCollection {{}} +"; + + public static string CollectionOutParameter(string collectionType, string predeclaration = "") => MarshalUsingCollectionOutConstantLength(collectionType, predeclaration); + public static string CollectionReturnType(string collectionType, string predeclaration = "") => MarshalUsingCollectionReturnConstantLength(collectionType, predeclaration); + public const string NonBlittableElement = @" +[NativeMarshalling(typeof(ElementMarshaller))] +struct Element +{ +#pragma warning disable CS0649 // Field is never assigned to, and will always have its default value + public bool b; +#pragma warning restore CS0649 +} +"; + public const string ElementMarshaller = @" +[CustomMarshaller(typeof(Element), MarshalMode.ElementIn, typeof(ElementMarshaller))] +[CustomMarshaller(typeof(Element), MarshalMode.ElementRef, typeof(ElementMarshaller))] +[CustomMarshaller(typeof(Element), MarshalMode.ElementOut, typeof(ElementMarshaller))] +static class ElementMarshaller +{ + public struct Native { } + public static Native ConvertToUnmanaged(Element e) => throw null; + public static Element ConvertToManaged(Native n) => throw null; +} +"; + public const string ElementIn = @" +[CustomMarshaller(typeof(Element), MarshalMode.ElementIn, typeof(ElementMarshaller))] +static class ElementMarshaller +{ + public struct Native { } + public static Native ConvertToUnmanaged(Element e) => throw null; + public static Element ConvertToManaged(Native n) => throw null; +} +"; + public const string ElementOut = @" +[CustomMarshaller(typeof(Element), MarshalMode.ElementOut, typeof(ElementMarshaller))] +static class ElementMarshaller +{ + public struct Native { } + public static Native ConvertToUnmanaged(Element e) => throw null; + public static Element ConvertToManaged(Native n) => throw null; +} +"; + public const string CustomIntMarshaller = @" +[CustomMarshaller(typeof(int), MarshalMode.ElementIn, typeof(CustomIntMarshaller))] +[CustomMarshaller(typeof(int), MarshalMode.ElementRef, typeof(CustomIntMarshaller))] +[CustomMarshaller(typeof(int), MarshalMode.ElementOut, typeof(CustomIntMarshaller))] +static class CustomIntMarshaller +{ + public struct Native { } + public static Native ConvertToUnmanaged(int e) => throw null; + public static int ConvertToManaged(Native n) => throw null; +} +"; + public static class Stateless + { + public const string In = @" +[CustomMarshaller(typeof(TestCollection<>), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller<,>))] +[ContiguousCollectionMarshaller] +static unsafe class Marshaller where TUnmanagedElement : unmanaged +{ + public static byte* AllocateContainerForUnmanagedElements(TestCollection managed, out int numElements) => throw null; + public static System.ReadOnlySpan GetManagedValuesSource(TestCollection managed) => throw null; + public static System.Span GetUnmanagedValuesDestination(byte* unmanaged, int numElements) => throw null; +} +"; + public const string InPinnable = @" +[CustomMarshaller(typeof(TestCollection<>), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller<,>))] +[ContiguousCollectionMarshaller] +static unsafe class Marshaller where TUnmanagedElement : unmanaged +{ + public static byte* AllocateContainerForUnmanagedElements(TestCollection managed, out int numElements) => throw null; + public static System.ReadOnlySpan GetManagedValuesSource(TestCollection managed) => throw null; + public static System.Span GetUnmanagedValuesDestination(byte* unmanaged, int numElements) => throw null; + + public static ref byte GetPinnableReference(TestCollection managed) => throw null; +} +"; + public const string InBuffer = @" +[CustomMarshaller(typeof(TestCollection<>), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller<,>))] +[ContiguousCollectionMarshaller] +static unsafe class Marshaller where TUnmanagedElement : unmanaged +{ + public const int BufferSize = 0x100; + public static byte* AllocateContainerForUnmanagedElements(TestCollection managed, System.Span buffer, out int numElements) => throw null; + public static System.ReadOnlySpan GetManagedValuesSource(TestCollection managed) => throw null; + public static System.Span GetUnmanagedValuesDestination(byte* unmanaged, int numElements) => throw null; +} +"; + public const string Ref = @" +[CustomMarshaller(typeof(TestCollection<>), MarshalMode.Default, typeof(Marshaller<,>))] +[ContiguousCollectionMarshaller] +static unsafe class Marshaller where TUnmanagedElement : unmanaged +{ + public static byte* AllocateContainerForUnmanagedElements(TestCollection managed, out int numElements) => throw null; + public static System.ReadOnlySpan GetManagedValuesSource(TestCollection managed) => throw null; + public static System.Span GetUnmanagedValuesDestination(byte* unmanaged, int numElements) => throw null; + + public static TestCollection AllocateContainerForManagedElements(byte* unmanaged, int length) => throw null; + public static System.Span GetManagedValuesDestination(TestCollection managed) => throw null; + public static System.ReadOnlySpan GetUnmanagedValuesSource(byte* unmanaged, int numElements) => throw null; +} +"; + public const string RefNested = @" +[CustomMarshaller(typeof(TestCollection<>), MarshalMode.Default, typeof(Marshaller<,>.Nested.Ref))] +[ContiguousCollectionMarshaller] +static unsafe class Marshaller where TUnmanagedElement : unmanaged +{ + internal static class Nested + { + internal static class Ref + { + public static byte* AllocateContainerForUnmanagedElements(TestCollection managed, out int numElements) => throw null; + public static System.ReadOnlySpan GetManagedValuesSource(TestCollection managed) => throw null; + public static System.Span GetUnmanagedValuesDestination(byte* unmanaged, int numElements) => throw null; + + public static TestCollection AllocateContainerForManagedElements(byte* unmanaged, int length) => throw null; + public static System.Span GetManagedValuesDestination(TestCollection managed) => throw null; + public static System.ReadOnlySpan GetUnmanagedValuesSource(byte* unmanaged, int numElements) => throw null; + } + } +} +"; + public const string Out = @" +[CustomMarshaller(typeof(TestCollection<>), MarshalMode.ManagedToUnmanagedOut, typeof(Marshaller<,>))] +[ContiguousCollectionMarshaller] +static unsafe class Marshaller where TUnmanagedElement : unmanaged +{ + public static TestCollection AllocateContainerForManagedElements(byte* unmanaged, int length) => throw null; + public static System.Span GetManagedValuesDestination(TestCollection managed) => throw null; + public static System.ReadOnlySpan GetUnmanagedValuesSource(byte* unmanaged, int numElements) => throw null; +} +"; + public static string ByValue() => ByValue(typeof(T).ToString()); + public static string ByValue(string elementType) => BasicParameterByValue($"TestCollection<{elementType}>", DisableRuntimeMarshalling) + + TestCollection() + + In; + + public static string ByValueWithPinning() => ByValueWithPinning(typeof(T).ToString()); + public static string ByValueWithPinning(string elementType) => BasicParameterByValue($"TestCollection<{elementType}>", DisableRuntimeMarshalling) + + TestCollection() + + InPinnable; + + public static string ByValueCallerAllocatedBuffer() => ByValueCallerAllocatedBuffer(typeof(T).ToString()); + public static string ByValueCallerAllocatedBuffer(string elementType) => BasicParameterByValue($"TestCollection<{elementType}>", DisableRuntimeMarshalling) + + TestCollection() + + InBuffer; + + public static string DefaultMarshallerParametersAndModifiers() => DefaultMarshallerParametersAndModifiers(typeof(T).ToString()); + public static string DefaultMarshallerParametersAndModifiers(string elementType) => MarshalUsingCollectionCountInfoParametersAndModifiers($"TestCollection<{elementType}>") + + TestCollection() + + Ref; + + public static string CustomMarshallerParametersAndModifiers() => CustomMarshallerParametersAndModifiers(typeof(T).ToString()); + public static string CustomMarshallerParametersAndModifiers(string elementType) => MarshalUsingCollectionParametersAndModifiers($"TestCollection<{elementType}>", $"Marshaller<,>") + + TestCollection(defineNativeMarshalling: false) + + Ref; + + public static string CustomMarshallerReturnValueLength() => CustomMarshallerReturnValueLength(typeof(T).ToString()); + public static string CustomMarshallerReturnValueLength(string elementType) => MarshalUsingCollectionReturnValueLength($"TestCollection<{elementType}>", $"Marshaller<,>") + + TestCollection(defineNativeMarshalling: false) + + Ref; + + public static string NativeToManagedOnlyOutParameter() => NativeToManagedOnlyOutParameter(typeof(T).ToString()); + public static string NativeToManagedOnlyOutParameter(string elementType) => CollectionOutParameter($"TestCollection<{elementType}>") + + TestCollection() + + Out; + + public static string NativeToManagedOnlyReturnValue() => NativeToManagedOnlyReturnValue(typeof(T).ToString()); + public static string NativeToManagedOnlyReturnValue(string elementType) => CollectionReturnType($"TestCollection<{elementType}>") + + TestCollection() + + Out; + + public static string NestedMarshallerParametersAndModifiers() => NestedMarshallerParametersAndModifiers(typeof(T).ToString()); + public static string NestedMarshallerParametersAndModifiers(string elementType) => MarshalUsingCollectionCountInfoParametersAndModifiers($"TestCollection<{elementType}>") + + TestCollection() + + RefNested; + + public static string NonBlittableElementParametersAndModifiers => DefaultMarshallerParametersAndModifiers("Element") + + NonBlittableElement + + ElementMarshaller; + + public static string NonBlittableElementByValue => ByValue("Element") + + NonBlittableElement + + ElementIn; + + public static string NonBlittableElementNativeToManagedOnlyOutParameter => NativeToManagedOnlyOutParameter("Element") + + NonBlittableElement + + ElementOut; + + public static string NonBlittableElementNativeToManagedOnlyReturnValue => NativeToManagedOnlyOutParameter("Element") + + NonBlittableElement + + ElementOut; + + public static string GenericCollectionMarshallingArityMismatch => BasicParameterByValue("TestCollection", DisableRuntimeMarshalling) + + @" +[NativeMarshalling(typeof(Marshaller<,,>))] +class TestCollection {} + +[CustomMarshaller(typeof(TestCollection<>), MarshalMode.Default, typeof(Marshaller<,,>))] +[ContiguousCollectionMarshaller] +static unsafe class Marshaller where TUnmanagedElement : unmanaged +{ + public static byte* AllocateContainerForUnmanagedElements(TestCollection managed, out int numElements) => throw null; + public static System.ReadOnlySpan GetManagedValuesSource(TestCollection managed) => throw null; + public static System.Span GetUnmanagedValuesDestination(byte* unmanaged, int numElements) => throw null; + + public static TestCollection AllocateContainerForManagedElements(byte* unmanaged, int length) => throw null; + public static System.Span GetManagedValuesDestination(TestCollection managed) => throw null; + public static System.ReadOnlySpan GetUnmanagedValuesSource(byte* unmanaged, int numElements) => throw null; +} +"; + + public static string CustomElementMarshalling => CodeSnippets.CustomElementMarshalling("TestCollection", "CustomIntMarshaller") + + TestCollection() + + Ref + + CustomIntMarshaller; + + public static string CustomElementMarshallingDuplicateElementIndirectionDepth => $@" +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; +{DisableRuntimeMarshalling} +partial class Test +{{ + [LibraryImport(""DoesNotExist"")] + public static partial void Method( + [MarshalUsing(typeof(CustomIntMarshaller), ElementIndirectionDepth = 1)] [MarshalUsing(typeof(CustomIntMarshaller), ElementIndirectionDepth = 1)] TestCollection p); +}} +" + + TestCollection() + + In + + CustomIntMarshaller; + + public static string CustomElementMarshallingUnusedElementIndirectionDepth => $@" +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; +{DisableRuntimeMarshalling} +partial class Test +{{ + [LibraryImport(""DoesNotExist"")] + public static partial void Method( + [MarshalUsing(typeof(CustomIntMarshaller), ElementIndirectionDepth = 2)] TestCollection p); +}} +" + + TestCollection() + + In + + CustomIntMarshaller; + } + + public static class Stateful + { + public const string In = @" +[ContiguousCollectionMarshaller] +[CustomMarshaller(typeof(TestCollection<>), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller<,>.In))] +static unsafe class Marshaller where TUnmanagedElement : unmanaged +{ + public ref struct In + { + public void FromManaged(TestCollection managed) => throw null; + public byte* ToUnmanaged() => throw null; + public System.ReadOnlySpan GetManagedValuesSource() => throw null; + public System.Span GetUnmanagedValuesDestination() => throw null; + } +} +"; + public const string InPinnable = @" +[ContiguousCollectionMarshaller] +[CustomMarshaller(typeof(TestCollection<>), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller<,>.In))] +static unsafe class Marshaller where TUnmanagedElement : unmanaged +{ + public ref struct In + { + public void FromManaged(TestCollection managed) => throw null; + public byte* ToUnmanaged() => throw null; + public System.ReadOnlySpan GetManagedValuesSource() => throw null; + public System.Span GetUnmanagedValuesDestination() => throw null; + public ref byte GetPinnableReference() => throw null; + } +} +"; + public const string InStaticPinnable = @" +[ContiguousCollectionMarshaller] +[CustomMarshaller(typeof(TestCollection<>), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller<,>.In))] +static unsafe class Marshaller where TUnmanagedElement : unmanaged +{ + public ref struct In + { + public void FromManaged(TestCollection managed) => throw null; + public byte* ToUnmanaged() => throw null; + public System.ReadOnlySpan GetManagedValuesSource() => throw null; + public System.Span GetUnmanagedValuesDestination() => throw null; + public static ref byte GetPinnableReference(TestCollection managed) => throw null; + } +} +"; + public const string InBuffer = @" +[ContiguousCollectionMarshaller] +[CustomMarshaller(typeof(TestCollection<>), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller<,>.In))] +static unsafe class Marshaller where TUnmanagedElement : unmanaged +{ + public ref struct In + { + public static int BufferSize { get; } + public void FromManaged(TestCollection managed, System.Span buffer) => throw null; + public byte* ToUnmanaged() => throw null; + public System.ReadOnlySpan GetManagedValuesSource() => throw null; + public System.Span GetUnmanagedValuesDestination() => throw null; + } +} +"; + public const string Ref = @" +[ContiguousCollectionMarshaller] +[CustomMarshaller(typeof(TestCollection<>), MarshalMode.Default, typeof(Marshaller<,>.Ref))] +static unsafe class Marshaller where TUnmanagedElement : unmanaged +{ + public ref struct Ref + { + public void FromManaged(TestCollection managed) => throw null; + public byte* ToUnmanaged() => throw null; + public System.ReadOnlySpan GetManagedValuesSource() => throw null; + public System.Span GetUnmanagedValuesDestination() => throw null; + + public void FromUnmanaged(byte* value) => throw null; + public TestCollection ToManaged() => throw null; + public System.Span GetManagedValuesDestination(int numElements) => throw null; + public System.ReadOnlySpan GetUnmanagedValuesSource(int numElements) => throw null; + } +} +"; + public const string Out = @" +[ContiguousCollectionMarshaller] +[CustomMarshaller(typeof(TestCollection<>), MarshalMode.ManagedToUnmanagedOut, typeof(Marshaller<,>.Out))] +static unsafe class Marshaller where TUnmanagedElement : unmanaged +{ + public ref struct Out + { + public void FromUnmanaged(byte* value) => throw null; + public TestCollection ToManaged() => throw null; + public System.Span GetManagedValuesDestination(int numElements) => throw null; + public System.ReadOnlySpan GetUnmanagedValuesSource(int numElements) => throw null; + } +} +"; + public static string ByValue() => ByValue(typeof(T).ToString()); + public static string ByValue(string elementType) => BasicParameterByValue($"TestCollection<{elementType}>", DisableRuntimeMarshalling) + + TestCollection() + + In; + + public static string ByValueWithPinning() => ByValueWithPinning(typeof(T).ToString()); + public static string ByValueWithPinning(string elementType) => BasicParameterByValue($"TestCollection<{elementType}>", DisableRuntimeMarshalling) + + TestCollection() + + InPinnable; + + public static string ByValueWithStaticPinning() => ByValueWithStaticPinning(typeof(T).ToString()); + public static string ByValueWithStaticPinning(string elementType) => BasicParameterByValue($"TestCollection<{elementType}>", DisableRuntimeMarshalling) + + TestCollection() + + InStaticPinnable; + + public static string ByValueCallerAllocatedBuffer() => ByValueCallerAllocatedBuffer(typeof(T).ToString()); + public static string ByValueCallerAllocatedBuffer(string elementType) => BasicParameterByValue($"TestCollection<{elementType}>", DisableRuntimeMarshalling) + + TestCollection() + + InBuffer; + + public static string DefaultMarshallerParametersAndModifiers() => DefaultMarshallerParametersAndModifiers(typeof(T).ToString()); + public static string DefaultMarshallerParametersAndModifiers(string elementType) => MarshalUsingCollectionCountInfoParametersAndModifiers($"TestCollection<{elementType}>") + + TestCollection() + + Ref; + + public static string CustomMarshallerParametersAndModifiers() => CustomMarshallerParametersAndModifiers(typeof(T).ToString()); + public static string CustomMarshallerParametersAndModifiers(string elementType) => MarshalUsingCollectionParametersAndModifiers($"TestCollection<{elementType}>", $"Marshaller<,>") + + TestCollection(defineNativeMarshalling: false) + + Ref; + + public static string CustomMarshallerReturnValueLength() => CustomMarshallerReturnValueLength(typeof(T).ToString()); + public static string CustomMarshallerReturnValueLength(string elementType) => MarshalUsingCollectionReturnValueLength($"TestCollection<{elementType}>", $"Marshaller<,>") + + TestCollection(defineNativeMarshalling: false) + + Ref; + + public static string NativeToManagedOnlyOutParameter() => NativeToManagedOnlyOutParameter(typeof(T).ToString()); + public static string NativeToManagedOnlyOutParameter(string elementType) => CollectionOutParameter($"TestCollection<{elementType}>") + + TestCollection() + + Out; + + public static string NativeToManagedOnlyReturnValue() => NativeToManagedOnlyReturnValue(typeof(T).ToString()); + public static string NativeToManagedOnlyReturnValue(string elementType) => CollectionReturnType($"TestCollection<{elementType}>") + + TestCollection() + + Out; + + public static string NonBlittableElementParametersAndModifiers => DefaultMarshallerParametersAndModifiers("Element") + + NonBlittableElement + + ElementMarshaller; + + public static string NonBlittableElementByValue => ByValue("Element") + + NonBlittableElement + + ElementIn; + + public static string NonBlittableElementNativeToManagedOnlyOutParameter => NativeToManagedOnlyOutParameter("Element") + + NonBlittableElement + + ElementOut; + + public static string NonBlittableElementNativeToManagedOnlyReturnValue => NativeToManagedOnlyOutParameter("Element") + + NonBlittableElement + + ElementOut; + + public static string CustomElementMarshalling => CodeSnippets.CustomElementMarshalling("TestCollection", "CustomIntMarshaller") + + TestCollection() + + Ref + + CustomIntMarshaller; + } + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/Common/CodeSnippets.CustomStructMarshalling.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/CodeSnippets.CustomStructMarshalling.cs new file mode 100644 index 0000000000000..12619bb065f7d --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/Common/CodeSnippets.CustomStructMarshalling.cs @@ -0,0 +1,507 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.Interop.UnitTests +{ + internal static partial class CodeSnippets + { + public static class CustomStructMarshalling + { + public static string NonBlittableUserDefinedType(bool defineNativeMarshalling = true) => $@" +{(defineNativeMarshalling ? "[NativeMarshalling(typeof(Marshaller))]" : string.Empty)} +public struct S +{{ +#pragma warning disable CS0649 // Field is never assigned to, and will always have its default value + public bool b; +#pragma warning restore CS0649 +}} +"; + private static string NonStatic = @" +[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller))] +public class Marshaller +{ + public struct Native { } + + public static Native ConvertToUnmanaged(S s) => default; +} +"; + public static string NonStaticMarshallerEntryPoint => BasicParameterByValue("S") + + NonBlittableUserDefinedType() + + NonStatic; + + public static class Stateless + { + private static string In = @" +[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller))] +public static class Marshaller +{ + public struct Native { } + + public static Native ConvertToUnmanaged(S s) => default; +} +"; + private static string InBuffer = @" +[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller))] +public static class Marshaller +{ + public struct Native { } + + public const int BufferSize = 0x100; + public static Native ConvertToUnmanaged(S s, System.Span buffer) => default; +} +"; + + public static string InPinnable = @" +[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller))] +public static unsafe class Marshaller +{ + public static byte* ConvertToUnmanaged(S s) => default; + public static ref byte GetPinnableReference(S s) => throw null; +} +"; + private static string Out = @" +[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedOut, typeof(Marshaller))] +public static class Marshaller +{ + public struct Native { } + + public static S ConvertToManaged(Native n) => default; +} +"; + private static string OutGuaranteed = @" +[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedOut, typeof(Marshaller))] +public static class Marshaller +{ + public struct Native { } + + public static S ConvertToManagedFinally(Native n) => default; +} +"; + public static string Ref = @" +[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedRef, typeof(Marshaller))] +public static class Marshaller +{ + public struct Native { } + + public static Native ConvertToUnmanaged(S s) => default; + public static S ConvertToManaged(Native n) => default; +} +"; + public static string Default = @" +[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(Marshaller))] +public static class Marshaller +{ + public struct Native { } + + public static Native ConvertToUnmanaged(S s) => default; + public static S ConvertToManaged(Native n) => default; +} +"; + public static string InOutBuffer = @" +[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller))] +[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedOut, typeof(Marshaller))] +public static class Marshaller +{ + public struct Native { } + + public const int BufferSize = 0x100; + public static Native ConvertToUnmanaged(S s, System.Span buffer) => default; + public static S ConvertToManaged(Native n) => default; +} +"; + public static string DefaultOptionalBuffer = @" +[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(Marshaller))] +public static class Marshaller +{ + public struct Native { } + + public const int BufferSize = 0x100; + public static Native ConvertToUnmanaged(S s) => default; + public static Native ConvertToUnmanaged(S s, System.Span buffer) => default; + public static S ConvertToManaged(Native n) => default; +} +"; + private static string DefaultIn = @" +[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(Marshaller))] +public static class Marshaller +{ + public struct Native { } + + public static Native ConvertToUnmanaged(S s) => default; +} +"; + private static string DefaultOut = @" +[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedOut, typeof(Marshaller))] +public static class Marshaller +{ + public struct Native { } + + public static S ConvertToManaged(Native n) => default; +} +"; + public static string ManagedToNativeOnlyOutParameter => BasicParameterWithByRefModifier("out", "S") + + NonBlittableUserDefinedType() + + In; + + public static string NativeToManagedOnlyOutParameter => BasicParameterWithByRefModifier("out", "S") + + NonBlittableUserDefinedType() + + Out; + + public static string NativeToManagedFinallyOnlyOutParameter => BasicParameterWithByRefModifier("out", "S") + + NonBlittableUserDefinedType() + + OutGuaranteed; + + public static string ManagedToNativeOnlyReturnValue => BasicReturnType("S") + + NonBlittableUserDefinedType() + + In; + + public static string NativeToManagedOnlyReturnValue => BasicReturnType("S") + + NonBlittableUserDefinedType() + + Out; + + public static string NativeToManagedFinallyOnlyReturnValue => BasicReturnType("S") + + NonBlittableUserDefinedType() + + Out; + + public static string NativeToManagedOnlyInParameter => BasicParameterWithByRefModifier("in", "S") + + NonBlittableUserDefinedType() + + Out; + + public static string ParametersAndModifiers = BasicParametersAndModifiers("S", UsingSystemRuntimeInteropServicesMarshalling) + + NonBlittableUserDefinedType(defineNativeMarshalling: true) + + Default; + + public static string MarshalUsingParametersAndModifiers = MarshalUsingParametersAndModifiers("S", "Marshaller") + + NonBlittableUserDefinedType(defineNativeMarshalling: false) + + Default; + + public static string ByValueInParameter => BasicParameterByValue("S") + + NonBlittableUserDefinedType() + + In; + + public static string StackallocByValueInParameter => BasicParameterByValue("S") + + NonBlittableUserDefinedType() + + InBuffer; + + public static string PinByValueInParameter => BasicParameterByValue("S") + + NonBlittableUserDefinedType() + + InPinnable; + + public static string StackallocParametersAndModifiersNoRef = BasicParametersAndModifiersNoRef("S") + + NonBlittableUserDefinedType() + + InOutBuffer; + + public static string RefParameter = BasicParameterWithByRefModifier("ref", "S") + + NonBlittableUserDefinedType() + + Ref; + + public static string StackallocOnlyRefParameter = BasicParameterWithByRefModifier("ref", "S") + + NonBlittableUserDefinedType() + + InOutBuffer; + + public static string OptionalStackallocParametersAndModifiers = BasicParametersAndModifiers("S", UsingSystemRuntimeInteropServicesMarshalling) + + NonBlittableUserDefinedType() + + DefaultOptionalBuffer; + + public static string DefaultModeByValueInParameter => BasicParameterByValue("S") + + NonBlittableUserDefinedType() + + DefaultIn; + + public static string DefaultModeReturnValue => BasicReturnType("S") + + NonBlittableUserDefinedType() + + DefaultOut; + } + + public static class Stateful + { + private static string In = @" +[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(M))] +public static class Marshaller +{ + public struct Native { } + + public struct M + { + public void FromManaged(S s) {} + public Native ToUnmanaged() => default; + } +} +"; + + public static string InStatelessPinnable = @" +[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(M))] +public static class Marshaller +{ + public unsafe struct M + { + public void FromManaged(S s) {} + public byte* ToUnmanaged() => default; + + public static ref byte GetPinnableReference(S s) => throw null; + } +} +"; + + public static string InPinnable = @" +[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(M))] +public static class Marshaller +{ + public unsafe struct M + { + public void FromManaged(S s) {} + public byte* ToUnmanaged() => default; + + public ref byte GetPinnableReference() => throw null; + } +} +"; + + private static string InBuffer = @" +[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(M))] +public static class Marshaller +{ + public struct Native { } + + public struct M + { + public const int BufferSize = 0x100; + public void FromManaged(S s, System.Span buffer) {} + public Native ToUnmanaged() => default; + } +} +"; + private static string Out = @" +[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedOut, typeof(M))] +public static class Marshaller +{ + public struct Native { } + + public struct M + { + public void FromUnmanaged(Native n) {} + public S ToManaged() => default; + } +} +"; + private static string OutGuaranteed = @" +[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedOut, typeof(M))] +public static class Marshaller +{ + public struct Native { } + + public struct M + { + public void FromUnmanaged(Native n) {} + public S ToManagedFinally() => default; + } +} +"; + public static string Ref = @" +[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedRef, typeof(M))] +public static class Marshaller +{ + public struct Native { } + + public struct M + { + public void FromManaged(S s) {} + public Native ToUnmanaged() => default; + public void FromUnmanaged(Native n) {} + public S ToManaged() => default; + } +} +"; + public static string Default = @" +[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(M))] +public static class Marshaller +{ + public struct Native { } + + public struct M + { + public void FromManaged(S s) {} + public Native ToUnmanaged() => default; + public void FromUnmanaged(Native n) {} + public S ToManaged() => default; + } +} +"; + public static string DefaultWithFree = @" +[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(M))] +public static class Marshaller +{ + public struct Native { } + + public struct M + { + public void FromManaged(S s) {} + public Native ToUnmanaged() => default; + public void FromUnmanaged(Native n) {} + public S ToManaged() => default; + public void Free() {} + } +} +"; + public static string DefaultWithOnInvoked = @" +[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(M))] +public static class Marshaller +{ + public struct Native { } + + public struct M + { + public void FromManaged(S s) {} + public Native ToUnmanaged() => default; + public void FromUnmanaged(Native n) {} + public S ToManaged() => default; + public void OnInvoked() {} + } +} +"; + public static string InOutBuffer = @" +[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(M))] +[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedOut, typeof(M))] +public static class Marshaller +{ + public struct Native { } + + public struct M + { + public const int BufferSize = 0x100; + public void FromManaged(S s, System.Span buffer) {} + public Native ToUnmanaged() => default; + public void FromUnmanaged(Native n) {} + public S ToManaged() => default; + } +} +"; + public static string DefaultOptionalBuffer = @" +[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(M))] +public static class Marshaller +{ + public struct Native { } + + public struct M + { + public const int BufferSize = 0x100; + public void FromManaged(S s) {} + public void FromManaged(S s, System.Span buffer) {} + public Native ToUnmanaged() => default; + public void FromUnmanaged(Native n) {} + public S ToManaged() => default; + } +} +"; + private static string DefaultIn = @" +[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(M))] +public static class Marshaller +{ + public struct Native { } + + public struct M + { + public void FromManaged(S s) {} + public Native ToUnmanaged() => default; + } +} +"; + private static string DefaultOut = @" +[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(M))] +public static class Marshaller +{ + public struct Native { } + + public struct M + { + public void FromUnmanaged(Native n) {} + public S ToManaged() => default; + } +} +"; + public static string ManagedToNativeOnlyOutParameter => BasicParameterWithByRefModifier("out", "S") + + NonBlittableUserDefinedType() + + In; + + public static string NativeToManagedOnlyOutParameter => BasicParameterWithByRefModifier("out", "S") + + NonBlittableUserDefinedType() + + Out; + + public static string NativeToManagedFinallyOnlyOutParameter => BasicParameterWithByRefModifier("out", "S") + + NonBlittableUserDefinedType() + + OutGuaranteed; + + public static string ManagedToNativeOnlyReturnValue => BasicReturnType("S") + + NonBlittableUserDefinedType() + + In; + + public static string NativeToManagedOnlyReturnValue => BasicReturnType("S") + + NonBlittableUserDefinedType() + + Out; + + public static string NativeToManagedFinallyOnlyReturnValue => BasicReturnType("S") + + NonBlittableUserDefinedType() + + Out; + + public static string NativeToManagedOnlyInParameter => BasicParameterWithByRefModifier("in", "S") + + NonBlittableUserDefinedType() + + Out; + + public static string ParametersAndModifiers = BasicParametersAndModifiers("S", UsingSystemRuntimeInteropServicesMarshalling) + + NonBlittableUserDefinedType(defineNativeMarshalling: true) + + Default; + + public static string ParametersAndModifiersWithFree = BasicParametersAndModifiers("S", UsingSystemRuntimeInteropServicesMarshalling) + + NonBlittableUserDefinedType(defineNativeMarshalling: true) + + DefaultWithFree; + + public static string ParametersAndModifiersWithOnInvoked = BasicParametersAndModifiers("S", UsingSystemRuntimeInteropServicesMarshalling) + + NonBlittableUserDefinedType(defineNativeMarshalling: true) + + DefaultWithOnInvoked; + + public static string MarshalUsingParametersAndModifiers = MarshalUsingParametersAndModifiers("S", "Marshaller") + + NonBlittableUserDefinedType(defineNativeMarshalling: false) + + Default; + + public static string ByValueInParameter => BasicParameterByValue("S") + + NonBlittableUserDefinedType() + + In; + + public static string StackallocByValueInParameter => BasicParameterByValue("S") + + NonBlittableUserDefinedType() + + InBuffer; + + public static string PinByValueInParameter => BasicParameterByValue("S") + + NonBlittableUserDefinedType() + + InStatelessPinnable; + + public static string MarshallerPinByValueInParameter => BasicParameterByValue("S") + + NonBlittableUserDefinedType() + + InPinnable; + + public static string StackallocParametersAndModifiersNoRef = BasicParametersAndModifiersNoRef("S") + + NonBlittableUserDefinedType() + + InOutBuffer; + + public static string RefParameter = BasicParameterWithByRefModifier("ref", "S") + + NonBlittableUserDefinedType() + + Ref; + + public static string StackallocOnlyRefParameter = BasicParameterWithByRefModifier("ref", "S") + + NonBlittableUserDefinedType() + + InOutBuffer; + + public static string OptionalStackallocParametersAndModifiers = BasicParametersAndModifiers("S", UsingSystemRuntimeInteropServicesMarshalling) + + NonBlittableUserDefinedType() + + DefaultOptionalBuffer; + + public static string DefaultModeByValueInParameter => BasicParameterByValue("S") + + NonBlittableUserDefinedType() + + DefaultIn; + + public static string DefaultModeReturnValue => BasicReturnType("S") + + NonBlittableUserDefinedType() + + DefaultOut; + } + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CodeSnippets.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CodeSnippets.cs index dcacad93c9204..b7bd132ee5483 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CodeSnippets.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CodeSnippets.cs @@ -3,9 +3,9 @@ using System.Runtime.InteropServices; -namespace LibraryImportGenerator.UnitTests +namespace Microsoft.Interop.UnitTests { - internal static class CodeSnippets + internal static partial class CodeSnippets { /// /// Partially define attribute for pre-.NET 7.0 @@ -677,506 +677,6 @@ partial class Test [LibraryImport(""DoesNotExist"")] public static partial {returnType} Method({parameterType} p); }}"; - - public static class CustomStructMarshalling - { - public static string NonBlittableUserDefinedType(bool defineNativeMarshalling = true) => $@" -{(defineNativeMarshalling ? "[NativeMarshalling(typeof(Marshaller))]" : string.Empty)} -public struct S -{{ -#pragma warning disable CS0649 // Field is never assigned to, and will always have its default value - public bool b; -#pragma warning restore CS0649 -}} -"; - private static string NonStatic = @" -[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller))] -public class Marshaller -{ - public struct Native { } - - public static Native ConvertToUnmanaged(S s) => default; -} -"; - public static string NonStaticMarshallerEntryPoint => BasicParameterByValue("S") - + NonBlittableUserDefinedType() - + NonStatic; - - public static class Stateless - { - private static string In = @" -[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller))] -public static class Marshaller -{ - public struct Native { } - - public static Native ConvertToUnmanaged(S s) => default; -} -"; - private static string InBuffer = @" -[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller))] -public static class Marshaller -{ - public struct Native { } - - public const int BufferSize = 0x100; - public static Native ConvertToUnmanaged(S s, System.Span buffer) => default; -} -"; - - public static string InPinnable = @" -[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller))] -public static unsafe class Marshaller -{ - public static byte* ConvertToUnmanaged(S s) => default; - public static ref byte GetPinnableReference(S s) => throw null; -} -"; - private static string Out = @" -[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedOut, typeof(Marshaller))] -public static class Marshaller -{ - public struct Native { } - - public static S ConvertToManaged(Native n) => default; -} -"; - private static string OutGuaranteed = @" -[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedOut, typeof(Marshaller))] -public static class Marshaller -{ - public struct Native { } - - public static S ConvertToManagedFinally(Native n) => default; -} -"; - public static string Ref = @" -[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedRef, typeof(Marshaller))] -public static class Marshaller -{ - public struct Native { } - - public static Native ConvertToUnmanaged(S s) => default; - public static S ConvertToManaged(Native n) => default; -} -"; - public static string Default = @" -[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(Marshaller))] -public static class Marshaller -{ - public struct Native { } - - public static Native ConvertToUnmanaged(S s) => default; - public static S ConvertToManaged(Native n) => default; -} -"; - public static string InOutBuffer = @" -[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller))] -[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedOut, typeof(Marshaller))] -public static class Marshaller -{ - public struct Native { } - - public const int BufferSize = 0x100; - public static Native ConvertToUnmanaged(S s, System.Span buffer) => default; - public static S ConvertToManaged(Native n) => default; -} -"; - public static string DefaultOptionalBuffer = @" -[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(Marshaller))] -public static class Marshaller -{ - public struct Native { } - - public const int BufferSize = 0x100; - public static Native ConvertToUnmanaged(S s) => default; - public static Native ConvertToUnmanaged(S s, System.Span buffer) => default; - public static S ConvertToManaged(Native n) => default; -} -"; - private static string DefaultIn = @" -[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(Marshaller))] -public static class Marshaller -{ - public struct Native { } - - public static Native ConvertToUnmanaged(S s) => default; -} -"; - private static string DefaultOut = @" -[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedOut, typeof(Marshaller))] -public static class Marshaller -{ - public struct Native { } - - public static S ConvertToManaged(Native n) => default; -} -"; - public static string ManagedToNativeOnlyOutParameter => BasicParameterWithByRefModifier("out", "S") - + NonBlittableUserDefinedType() - + In; - - public static string NativeToManagedOnlyOutParameter => BasicParameterWithByRefModifier("out", "S") - + NonBlittableUserDefinedType() - + Out; - - public static string NativeToManagedFinallyOnlyOutParameter => BasicParameterWithByRefModifier("out", "S") - + NonBlittableUserDefinedType() - + OutGuaranteed; - - public static string ManagedToNativeOnlyReturnValue => BasicReturnType("S") - + NonBlittableUserDefinedType() - + In; - - public static string NativeToManagedOnlyReturnValue => BasicReturnType("S") - + NonBlittableUserDefinedType() - + Out; - - public static string NativeToManagedFinallyOnlyReturnValue => BasicReturnType("S") - + NonBlittableUserDefinedType() - + Out; - - public static string NativeToManagedOnlyInParameter => BasicParameterWithByRefModifier("in", "S") - + NonBlittableUserDefinedType() - + Out; - - public static string ParametersAndModifiers = BasicParametersAndModifiers("S", UsingSystemRuntimeInteropServicesMarshalling) - + NonBlittableUserDefinedType(defineNativeMarshalling: true) - + Default; - - public static string MarshalUsingParametersAndModifiers = MarshalUsingParametersAndModifiers("S", "Marshaller") - + NonBlittableUserDefinedType(defineNativeMarshalling: false) - + Default; - - public static string ByValueInParameter => BasicParameterByValue("S") - + NonBlittableUserDefinedType() - + In; - - public static string StackallocByValueInParameter => BasicParameterByValue("S") - + NonBlittableUserDefinedType() - + InBuffer; - - public static string PinByValueInParameter => BasicParameterByValue("S") - + NonBlittableUserDefinedType() - + InPinnable; - - public static string StackallocParametersAndModifiersNoRef = BasicParametersAndModifiersNoRef("S") - + NonBlittableUserDefinedType() - + InOutBuffer; - - public static string RefParameter = BasicParameterWithByRefModifier("ref", "S") - + NonBlittableUserDefinedType() - + Ref; - - public static string StackallocOnlyRefParameter = BasicParameterWithByRefModifier("ref", "S") - + NonBlittableUserDefinedType() - + InOutBuffer; - - public static string OptionalStackallocParametersAndModifiers = BasicParametersAndModifiers("S", UsingSystemRuntimeInteropServicesMarshalling) - + NonBlittableUserDefinedType() - + DefaultOptionalBuffer; - - public static string DefaultModeByValueInParameter => BasicParameterByValue("S") - + NonBlittableUserDefinedType() - + DefaultIn; - - public static string DefaultModeReturnValue => BasicReturnType("S") - + NonBlittableUserDefinedType() - + DefaultOut; - } - - public static class Stateful - { - private static string In = @" -[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(M))] -public static class Marshaller -{ - public struct Native { } - - public struct M - { - public void FromManaged(S s) {} - public Native ToUnmanaged() => default; - } -} -"; - - public static string InStatelessPinnable = @" -[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(M))] -public static class Marshaller -{ - public unsafe struct M - { - public void FromManaged(S s) {} - public byte* ToUnmanaged() => default; - - public static ref byte GetPinnableReference(S s) => throw null; - } -} -"; - - public static string InPinnable = @" -[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(M))] -public static class Marshaller -{ - public unsafe struct M - { - public void FromManaged(S s) {} - public byte* ToUnmanaged() => default; - - public ref byte GetPinnableReference() => throw null; - } -} -"; - - private static string InBuffer = @" -[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(M))] -public static class Marshaller -{ - public struct Native { } - - public struct M - { - public const int BufferSize = 0x100; - public void FromManaged(S s, System.Span buffer) {} - public Native ToUnmanaged() => default; - } -} -"; - private static string Out = @" -[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedOut, typeof(M))] -public static class Marshaller -{ - public struct Native { } - - public struct M - { - public void FromUnmanaged(Native n) {} - public S ToManaged() => default; - } -} -"; - private static string OutGuaranteed = @" -[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedOut, typeof(M))] -public static class Marshaller -{ - public struct Native { } - - public struct M - { - public void FromUnmanaged(Native n) {} - public S ToManagedFinally() => default; - } -} -"; - public static string Ref = @" -[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedRef, typeof(M))] -public static class Marshaller -{ - public struct Native { } - - public struct M - { - public void FromManaged(S s) {} - public Native ToUnmanaged() => default; - public void FromUnmanaged(Native n) {} - public S ToManaged() => default; - } -} -"; - public static string Default = @" -[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(M))] -public static class Marshaller -{ - public struct Native { } - - public struct M - { - public void FromManaged(S s) {} - public Native ToUnmanaged() => default; - public void FromUnmanaged(Native n) {} - public S ToManaged() => default; - } -} -"; - public static string DefaultWithFree = @" -[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(M))] -public static class Marshaller -{ - public struct Native { } - - public struct M - { - public void FromManaged(S s) {} - public Native ToUnmanaged() => default; - public void FromUnmanaged(Native n) {} - public S ToManaged() => default; - public void Free() {} - } -} -"; - public static string DefaultWithOnInvoked = @" -[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(M))] -public static class Marshaller -{ - public struct Native { } - - public struct M - { - public void FromManaged(S s) {} - public Native ToUnmanaged() => default; - public void FromUnmanaged(Native n) {} - public S ToManaged() => default; - public void OnInvoked() {} - } -} -"; - public static string InOutBuffer = @" -[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(M))] -[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedOut, typeof(M))] -public static class Marshaller -{ - public struct Native { } - - public struct M - { - public const int BufferSize = 0x100; - public void FromManaged(S s, System.Span buffer) {} - public Native ToUnmanaged() => default; - public void FromUnmanaged(Native n) {} - public S ToManaged() => default; - } -} -"; - public static string DefaultOptionalBuffer = @" -[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(M))] -public static class Marshaller -{ - public struct Native { } - - public struct M - { - public const int BufferSize = 0x100; - public void FromManaged(S s) {} - public void FromManaged(S s, System.Span buffer) {} - public Native ToUnmanaged() => default; - public void FromUnmanaged(Native n) {} - public S ToManaged() => default; - } -} -"; - private static string DefaultIn = @" -[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(M))] -public static class Marshaller -{ - public struct Native { } - - public struct M - { - public void FromManaged(S s) {} - public Native ToUnmanaged() => default; - } -} -"; - private static string DefaultOut = @" -[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(M))] -public static class Marshaller -{ - public struct Native { } - - public struct M - { - public void FromUnmanaged(Native n) {} - public S ToManaged() => default; - } -} -"; - public static string ManagedToNativeOnlyOutParameter => BasicParameterWithByRefModifier("out", "S") - + NonBlittableUserDefinedType() - + In; - - public static string NativeToManagedOnlyOutParameter => BasicParameterWithByRefModifier("out", "S") - + NonBlittableUserDefinedType() - + Out; - - public static string NativeToManagedFinallyOnlyOutParameter => BasicParameterWithByRefModifier("out", "S") - + NonBlittableUserDefinedType() - + OutGuaranteed; - - public static string ManagedToNativeOnlyReturnValue => BasicReturnType("S") - + NonBlittableUserDefinedType() - + In; - - public static string NativeToManagedOnlyReturnValue => BasicReturnType("S") - + NonBlittableUserDefinedType() - + Out; - - public static string NativeToManagedFinallyOnlyReturnValue => BasicReturnType("S") - + NonBlittableUserDefinedType() - + Out; - - public static string NativeToManagedOnlyInParameter => BasicParameterWithByRefModifier("in", "S") - + NonBlittableUserDefinedType() - + Out; - - public static string ParametersAndModifiers = BasicParametersAndModifiers("S", UsingSystemRuntimeInteropServicesMarshalling) - + NonBlittableUserDefinedType(defineNativeMarshalling: true) - + Default; - - public static string ParametersAndModifiersWithFree = BasicParametersAndModifiers("S", UsingSystemRuntimeInteropServicesMarshalling) - + NonBlittableUserDefinedType(defineNativeMarshalling: true) - + DefaultWithFree; - - public static string ParametersAndModifiersWithOnInvoked = BasicParametersAndModifiers("S", UsingSystemRuntimeInteropServicesMarshalling) - + NonBlittableUserDefinedType(defineNativeMarshalling: true) - + DefaultWithOnInvoked; - - public static string MarshalUsingParametersAndModifiers = MarshalUsingParametersAndModifiers("S", "Marshaller") - + NonBlittableUserDefinedType(defineNativeMarshalling: false) - + Default; - - public static string ByValueInParameter => BasicParameterByValue("S") - + NonBlittableUserDefinedType() - + In; - - public static string StackallocByValueInParameter => BasicParameterByValue("S") - + NonBlittableUserDefinedType() - + InBuffer; - - public static string PinByValueInParameter => BasicParameterByValue("S") - + NonBlittableUserDefinedType() - + InStatelessPinnable; - - public static string MarshallerPinByValueInParameter => BasicParameterByValue("S") - + NonBlittableUserDefinedType() - + InPinnable; - - public static string StackallocParametersAndModifiersNoRef = BasicParametersAndModifiersNoRef("S") - + NonBlittableUserDefinedType() - + InOutBuffer; - - public static string RefParameter = BasicParameterWithByRefModifier("ref", "S") - + NonBlittableUserDefinedType() - + Ref; - - public static string StackallocOnlyRefParameter = BasicParameterWithByRefModifier("ref", "S") - + NonBlittableUserDefinedType() - + InOutBuffer; - - public static string OptionalStackallocParametersAndModifiers = BasicParametersAndModifiers("S", UsingSystemRuntimeInteropServicesMarshalling) - + NonBlittableUserDefinedType() - + DefaultOptionalBuffer; - - public static string DefaultModeByValueInParameter => BasicParameterByValue("S") - + NonBlittableUserDefinedType() - + DefaultIn; - - public static string DefaultModeReturnValue => BasicReturnType("S") - + NonBlittableUserDefinedType() - + DefaultOut; - } - } - public static string SafeHandleWithCustomDefaultConstructorAccessibility(bool privateCtor) => BasicParametersAndModifiers("MySafeHandle") + $@" class MySafeHandle : SafeHandle {{ @@ -1285,477 +785,6 @@ struct RecursiveStruct2 int i; }"; - public static class CustomCollectionMarshalling - { - public static string TestCollection(bool defineNativeMarshalling = true) => $@" -{(defineNativeMarshalling ? "[NativeMarshalling(typeof(Marshaller<,>))]" : string.Empty)} -class TestCollection {{}} -"; - - public static string CollectionOutParameter(string collectionType, string predeclaration = "") => $@" -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.Marshalling; -{predeclaration} -partial class Test -{{ - [LibraryImport(""DoesNotExist"")] - public static partial int Method( - [MarshalUsing(ConstantElementCount = 10)] out {collectionType} pOut); -}} -"; - public static string CollectionReturnType(string collectionType, string predeclaration = "") => $@" -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.Marshalling; -{predeclaration} -partial class Test -{{ - [LibraryImport(""DoesNotExist"")] - [return: MarshalUsing(ConstantElementCount = 10)] - public static partial {collectionType} Method(); -}} -"; - public const string NonBlittableElement = @" -[NativeMarshalling(typeof(ElementMarshaller))] -struct Element -{ -#pragma warning disable CS0649 // Field is never assigned to, and will always have its default value - public bool b; -#pragma warning restore CS0649 -} -"; - public const string ElementMarshaller = @" -[CustomMarshaller(typeof(Element), MarshalMode.ElementIn, typeof(ElementMarshaller))] -[CustomMarshaller(typeof(Element), MarshalMode.ElementRef, typeof(ElementMarshaller))] -[CustomMarshaller(typeof(Element), MarshalMode.ElementOut, typeof(ElementMarshaller))] -static class ElementMarshaller -{ - public struct Native { } - public static Native ConvertToUnmanaged(Element e) => throw null; - public static Element ConvertToManaged(Native n) => throw null; -} -"; - public const string ElementIn = @" -[CustomMarshaller(typeof(Element), MarshalMode.ElementIn, typeof(ElementMarshaller))] -static class ElementMarshaller -{ - public struct Native { } - public static Native ConvertToUnmanaged(Element e) => throw null; - public static Element ConvertToManaged(Native n) => throw null; -} -"; - public const string ElementOut = @" -[CustomMarshaller(typeof(Element), MarshalMode.ElementOut, typeof(ElementMarshaller))] -static class ElementMarshaller -{ - public struct Native { } - public static Native ConvertToUnmanaged(Element e) => throw null; - public static Element ConvertToManaged(Native n) => throw null; -} -"; - public const string CustomIntMarshaller = @" -[CustomMarshaller(typeof(int), MarshalMode.ElementIn, typeof(CustomIntMarshaller))] -[CustomMarshaller(typeof(int), MarshalMode.ElementRef, typeof(CustomIntMarshaller))] -[CustomMarshaller(typeof(int), MarshalMode.ElementOut, typeof(CustomIntMarshaller))] -static class CustomIntMarshaller -{ - public struct Native { } - public static Native ConvertToUnmanaged(int e) => throw null; - public static int ConvertToManaged(Native n) => throw null; -} -"; - public static class Stateless - { - public const string In = @" -[CustomMarshaller(typeof(TestCollection<>), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller<,>))] -[ContiguousCollectionMarshaller] -static unsafe class Marshaller where TUnmanagedElement : unmanaged -{ - public static byte* AllocateContainerForUnmanagedElements(TestCollection managed, out int numElements) => throw null; - public static System.ReadOnlySpan GetManagedValuesSource(TestCollection managed) => throw null; - public static System.Span GetUnmanagedValuesDestination(byte* unmanaged, int numElements) => throw null; -} -"; - public const string InPinnable = @" -[CustomMarshaller(typeof(TestCollection<>), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller<,>))] -[ContiguousCollectionMarshaller] -static unsafe class Marshaller where TUnmanagedElement : unmanaged -{ - public static byte* AllocateContainerForUnmanagedElements(TestCollection managed, out int numElements) => throw null; - public static System.ReadOnlySpan GetManagedValuesSource(TestCollection managed) => throw null; - public static System.Span GetUnmanagedValuesDestination(byte* unmanaged, int numElements) => throw null; - - public static ref byte GetPinnableReference(TestCollection managed) => throw null; -} -"; - public const string InBuffer = @" -[CustomMarshaller(typeof(TestCollection<>), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller<,>))] -[ContiguousCollectionMarshaller] -static unsafe class Marshaller where TUnmanagedElement : unmanaged -{ - public const int BufferSize = 0x100; - public static byte* AllocateContainerForUnmanagedElements(TestCollection managed, System.Span buffer, out int numElements) => throw null; - public static System.ReadOnlySpan GetManagedValuesSource(TestCollection managed) => throw null; - public static System.Span GetUnmanagedValuesDestination(byte* unmanaged, int numElements) => throw null; -} -"; - public const string Ref = @" -[CustomMarshaller(typeof(TestCollection<>), MarshalMode.Default, typeof(Marshaller<,>))] -[ContiguousCollectionMarshaller] -static unsafe class Marshaller where TUnmanagedElement : unmanaged -{ - public static byte* AllocateContainerForUnmanagedElements(TestCollection managed, out int numElements) => throw null; - public static System.ReadOnlySpan GetManagedValuesSource(TestCollection managed) => throw null; - public static System.Span GetUnmanagedValuesDestination(byte* unmanaged, int numElements) => throw null; - - public static TestCollection AllocateContainerForManagedElements(byte* unmanaged, int length) => throw null; - public static System.Span GetManagedValuesDestination(TestCollection managed) => throw null; - public static System.ReadOnlySpan GetUnmanagedValuesSource(byte* unmanaged, int numElements) => throw null; -} -"; - public const string RefNested = @" -[CustomMarshaller(typeof(TestCollection<>), MarshalMode.Default, typeof(Marshaller<,>.Nested.Ref))] -[ContiguousCollectionMarshaller] -static unsafe class Marshaller where TUnmanagedElement : unmanaged -{ - internal static class Nested - { - internal static class Ref - { - public static byte* AllocateContainerForUnmanagedElements(TestCollection managed, out int numElements) => throw null; - public static System.ReadOnlySpan GetManagedValuesSource(TestCollection managed) => throw null; - public static System.Span GetUnmanagedValuesDestination(byte* unmanaged, int numElements) => throw null; - - public static TestCollection AllocateContainerForManagedElements(byte* unmanaged, int length) => throw null; - public static System.Span GetManagedValuesDestination(TestCollection managed) => throw null; - public static System.ReadOnlySpan GetUnmanagedValuesSource(byte* unmanaged, int numElements) => throw null; - } - } -} -"; - public const string Out = @" -[CustomMarshaller(typeof(TestCollection<>), MarshalMode.ManagedToUnmanagedOut, typeof(Marshaller<,>))] -[ContiguousCollectionMarshaller] -static unsafe class Marshaller where TUnmanagedElement : unmanaged -{ - public static TestCollection AllocateContainerForManagedElements(byte* unmanaged, int length) => throw null; - public static System.Span GetManagedValuesDestination(TestCollection managed) => throw null; - public static System.ReadOnlySpan GetUnmanagedValuesSource(byte* unmanaged, int numElements) => throw null; -} -"; - public static string ByValue() => ByValue(typeof(T).ToString()); - public static string ByValue(string elementType) => BasicParameterByValue($"TestCollection<{elementType}>", DisableRuntimeMarshalling) - + TestCollection() - + In; - - public static string ByValueWithPinning() => ByValueWithPinning(typeof(T).ToString()); - public static string ByValueWithPinning(string elementType) => BasicParameterByValue($"TestCollection<{elementType}>", DisableRuntimeMarshalling) - + TestCollection() - + InPinnable; - - public static string ByValueCallerAllocatedBuffer() => ByValueCallerAllocatedBuffer(typeof(T).ToString()); - public static string ByValueCallerAllocatedBuffer(string elementType) => BasicParameterByValue($"TestCollection<{elementType}>", DisableRuntimeMarshalling) - + TestCollection() - + InBuffer; - - public static string DefaultMarshallerParametersAndModifiers() => DefaultMarshallerParametersAndModifiers(typeof(T).ToString()); - public static string DefaultMarshallerParametersAndModifiers(string elementType) => MarshalUsingCollectionCountInfoParametersAndModifiers($"TestCollection<{elementType}>") - + TestCollection() - + Ref; - - public static string CustomMarshallerParametersAndModifiers() => CustomMarshallerParametersAndModifiers(typeof(T).ToString()); - public static string CustomMarshallerParametersAndModifiers(string elementType) => MarshalUsingCollectionParametersAndModifiers($"TestCollection<{elementType}>", $"Marshaller<,>") - + TestCollection(defineNativeMarshalling: false) - + Ref; - - public static string CustomMarshallerReturnValueLength() => CustomMarshallerReturnValueLength(typeof(T).ToString()); - public static string CustomMarshallerReturnValueLength(string elementType) => MarshalUsingCollectionReturnValueLength($"TestCollection<{elementType}>", $"Marshaller<,>") - + TestCollection(defineNativeMarshalling: false) - + Ref; - - public static string NativeToManagedOnlyOutParameter() => NativeToManagedOnlyOutParameter(typeof(T).ToString()); - public static string NativeToManagedOnlyOutParameter(string elementType) => CollectionOutParameter($"TestCollection<{elementType}>") - + TestCollection() - + Out; - - public static string NativeToManagedOnlyReturnValue() => NativeToManagedOnlyReturnValue(typeof(T).ToString()); - public static string NativeToManagedOnlyReturnValue(string elementType) => CollectionReturnType($"TestCollection<{elementType}>") - + TestCollection() - + Out; - - public static string NestedMarshallerParametersAndModifiers() => NestedMarshallerParametersAndModifiers(typeof(T).ToString()); - public static string NestedMarshallerParametersAndModifiers(string elementType) => MarshalUsingCollectionCountInfoParametersAndModifiers($"TestCollection<{elementType}>") - + TestCollection() - + RefNested; - - public static string NonBlittableElementParametersAndModifiers => DefaultMarshallerParametersAndModifiers("Element") - + NonBlittableElement - + ElementMarshaller; - - public static string NonBlittableElementByValue => ByValue("Element") - + NonBlittableElement - + ElementIn; - - public static string NonBlittableElementNativeToManagedOnlyOutParameter => NativeToManagedOnlyOutParameter("Element") - + NonBlittableElement - + ElementOut; - - public static string NonBlittableElementNativeToManagedOnlyReturnValue => NativeToManagedOnlyOutParameter("Element") - + NonBlittableElement - + ElementOut; - - public static string GenericCollectionMarshallingArityMismatch => BasicParameterByValue("TestCollection", DisableRuntimeMarshalling) - + @" -[NativeMarshalling(typeof(Marshaller<,,>))] -class TestCollection {} - -[CustomMarshaller(typeof(TestCollection<>), MarshalMode.Default, typeof(Marshaller<,,>))] -[ContiguousCollectionMarshaller] -static unsafe class Marshaller where TUnmanagedElement : unmanaged -{ - public static byte* AllocateContainerForUnmanagedElements(TestCollection managed, out int numElements) => throw null; - public static System.ReadOnlySpan GetManagedValuesSource(TestCollection managed) => throw null; - public static System.Span GetUnmanagedValuesDestination(byte* unmanaged, int numElements) => throw null; - - public static TestCollection AllocateContainerForManagedElements(byte* unmanaged, int length) => throw null; - public static System.Span GetManagedValuesDestination(TestCollection managed) => throw null; - public static System.ReadOnlySpan GetUnmanagedValuesSource(byte* unmanaged, int numElements) => throw null; -} -"; - - public static string CustomElementMarshalling => $@" -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.Marshalling; -{DisableRuntimeMarshalling} -partial class Test -{{ - [LibraryImport(""DoesNotExist"")] - [return:MarshalUsing(ConstantElementCount=10)] - [return:MarshalUsing(typeof(CustomIntMarshaller), ElementIndirectionDepth = 1)] - public static partial TestCollection Method( - [MarshalUsing(typeof(CustomIntMarshaller), ElementIndirectionDepth = 1)] TestCollection p, - [MarshalUsing(typeof(CustomIntMarshaller), ElementIndirectionDepth = 1)] in TestCollection pIn, - int pRefSize, - [MarshalUsing(CountElementName = ""pRefSize""), MarshalUsing(typeof(CustomIntMarshaller), ElementIndirectionDepth = 1)] ref TestCollection pRef, - [MarshalUsing(CountElementName = ""pOutSize"")][MarshalUsing(typeof(CustomIntMarshaller), ElementIndirectionDepth = 1)] out TestCollection pOut, - out int pOutSize - ); -}} -" - + TestCollection() - + Ref - + CustomIntMarshaller; - - public static string CustomElementMarshallingDuplicateElementIndirectionDepth => $@" -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.Marshalling; -{DisableRuntimeMarshalling} -partial class Test -{{ - [LibraryImport(""DoesNotExist"")] - public static partial void Method( - [MarshalUsing(typeof(CustomIntMarshaller), ElementIndirectionDepth = 1)] [MarshalUsing(typeof(CustomIntMarshaller), ElementIndirectionDepth = 1)] TestCollection p); -}} -" - + TestCollection() - + In - + CustomIntMarshaller; - - public static string CustomElementMarshallingUnusedElementIndirectionDepth => $@" -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.Marshalling; -{DisableRuntimeMarshalling} -partial class Test -{{ - [LibraryImport(""DoesNotExist"")] - public static partial void Method( - [MarshalUsing(typeof(CustomIntMarshaller), ElementIndirectionDepth = 2)] TestCollection p); -}} -" - + TestCollection() - + In - + CustomIntMarshaller; - } - - public static class Stateful - { - public const string In = @" -[ContiguousCollectionMarshaller] -[CustomMarshaller(typeof(TestCollection<>), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller<,>.In))] -static unsafe class Marshaller where TUnmanagedElement : unmanaged -{ - public ref struct In - { - public void FromManaged(TestCollection managed) => throw null; - public byte* ToUnmanaged() => throw null; - public System.ReadOnlySpan GetManagedValuesSource() => throw null; - public System.Span GetUnmanagedValuesDestination() => throw null; - } -} -"; - public const string InPinnable = @" -[ContiguousCollectionMarshaller] -[CustomMarshaller(typeof(TestCollection<>), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller<,>.In))] -static unsafe class Marshaller where TUnmanagedElement : unmanaged -{ - public ref struct In - { - public void FromManaged(TestCollection managed) => throw null; - public byte* ToUnmanaged() => throw null; - public System.ReadOnlySpan GetManagedValuesSource() => throw null; - public System.Span GetUnmanagedValuesDestination() => throw null; - public ref byte GetPinnableReference() => throw null; - } -} -"; - public const string InStaticPinnable = @" -[ContiguousCollectionMarshaller] -[CustomMarshaller(typeof(TestCollection<>), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller<,>.In))] -static unsafe class Marshaller where TUnmanagedElement : unmanaged -{ - public ref struct In - { - public void FromManaged(TestCollection managed) => throw null; - public byte* ToUnmanaged() => throw null; - public System.ReadOnlySpan GetManagedValuesSource() => throw null; - public System.Span GetUnmanagedValuesDestination() => throw null; - public static ref byte GetPinnableReference(TestCollection managed) => throw null; - } -} -"; - public const string InBuffer = @" -[ContiguousCollectionMarshaller] -[CustomMarshaller(typeof(TestCollection<>), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller<,>.In))] -static unsafe class Marshaller where TUnmanagedElement : unmanaged -{ - public ref struct In - { - public static int BufferSize { get; } - public void FromManaged(TestCollection managed, System.Span buffer) => throw null; - public byte* ToUnmanaged() => throw null; - public System.ReadOnlySpan GetManagedValuesSource() => throw null; - public System.Span GetUnmanagedValuesDestination() => throw null; - } -} -"; - public const string Ref = @" -[ContiguousCollectionMarshaller] -[CustomMarshaller(typeof(TestCollection<>), MarshalMode.Default, typeof(Marshaller<,>.Ref))] -static unsafe class Marshaller where TUnmanagedElement : unmanaged -{ - public ref struct Ref - { - public void FromManaged(TestCollection managed) => throw null; - public byte* ToUnmanaged() => throw null; - public System.ReadOnlySpan GetManagedValuesSource() => throw null; - public System.Span GetUnmanagedValuesDestination() => throw null; - - public void FromUnmanaged(byte* value) => throw null; - public TestCollection ToManaged() => throw null; - public System.Span GetManagedValuesDestination(int numElements) => throw null; - public System.ReadOnlySpan GetUnmanagedValuesSource(int numElements) => throw null; - } -} -"; - public const string Out = @" -[ContiguousCollectionMarshaller] -[CustomMarshaller(typeof(TestCollection<>), MarshalMode.ManagedToUnmanagedOut, typeof(Marshaller<,>.Out))] -static unsafe class Marshaller where TUnmanagedElement : unmanaged -{ - public ref struct Out - { - public void FromUnmanaged(byte* value) => throw null; - public TestCollection ToManaged() => throw null; - public System.Span GetManagedValuesDestination(int numElements) => throw null; - public System.ReadOnlySpan GetUnmanagedValuesSource(int numElements) => throw null; - } -} -"; - public static string ByValue() => ByValue(typeof(T).ToString()); - public static string ByValue(string elementType) => BasicParameterByValue($"TestCollection<{elementType}>", DisableRuntimeMarshalling) - + TestCollection() - + In; - - public static string ByValueWithPinning() => ByValueWithPinning(typeof(T).ToString()); - public static string ByValueWithPinning(string elementType) => BasicParameterByValue($"TestCollection<{elementType}>", DisableRuntimeMarshalling) - + TestCollection() - + InPinnable; - - public static string ByValueWithStaticPinning() => ByValueWithStaticPinning(typeof(T).ToString()); - public static string ByValueWithStaticPinning(string elementType) => BasicParameterByValue($"TestCollection<{elementType}>", DisableRuntimeMarshalling) - + TestCollection() - + InStaticPinnable; - - public static string ByValueCallerAllocatedBuffer() => ByValueCallerAllocatedBuffer(typeof(T).ToString()); - public static string ByValueCallerAllocatedBuffer(string elementType) => BasicParameterByValue($"TestCollection<{elementType}>", DisableRuntimeMarshalling) - + TestCollection() - + InBuffer; - - public static string DefaultMarshallerParametersAndModifiers() => DefaultMarshallerParametersAndModifiers(typeof(T).ToString()); - public static string DefaultMarshallerParametersAndModifiers(string elementType) => MarshalUsingCollectionCountInfoParametersAndModifiers($"TestCollection<{elementType}>") - + TestCollection() - + Ref; - - public static string CustomMarshallerParametersAndModifiers() => CustomMarshallerParametersAndModifiers(typeof(T).ToString()); - public static string CustomMarshallerParametersAndModifiers(string elementType) => MarshalUsingCollectionParametersAndModifiers($"TestCollection<{elementType}>", $"Marshaller<,>") - + TestCollection(defineNativeMarshalling: false) - + Ref; - - public static string CustomMarshallerReturnValueLength() => CustomMarshallerReturnValueLength(typeof(T).ToString()); - public static string CustomMarshallerReturnValueLength(string elementType) => MarshalUsingCollectionReturnValueLength($"TestCollection<{elementType}>", $"Marshaller<,>") - + TestCollection(defineNativeMarshalling: false) - + Ref; - - public static string NativeToManagedOnlyOutParameter() => NativeToManagedOnlyOutParameter(typeof(T).ToString()); - public static string NativeToManagedOnlyOutParameter(string elementType) => CollectionOutParameter($"TestCollection<{elementType}>") - + TestCollection() - + Out; - - public static string NativeToManagedOnlyReturnValue() => NativeToManagedOnlyReturnValue(typeof(T).ToString()); - public static string NativeToManagedOnlyReturnValue(string elementType) => CollectionReturnType($"TestCollection<{elementType}>") - + TestCollection() - + Out; - - public static string NonBlittableElementParametersAndModifiers => DefaultMarshallerParametersAndModifiers("Element") - + NonBlittableElement - + ElementMarshaller; - - public static string NonBlittableElementByValue => ByValue("Element") - + NonBlittableElement - + ElementIn; - - public static string NonBlittableElementNativeToManagedOnlyOutParameter => NativeToManagedOnlyOutParameter("Element") - + NonBlittableElement - + ElementOut; - - public static string NonBlittableElementNativeToManagedOnlyReturnValue => NativeToManagedOnlyOutParameter("Element") - + NonBlittableElement - + ElementOut; - - public static string CustomElementMarshalling => $@" -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.Marshalling; -{DisableRuntimeMarshalling} -partial class Test -{{ - [LibraryImport(""DoesNotExist"")] - [return:MarshalUsing(ConstantElementCount=10)] - [return:MarshalUsing(typeof(CustomIntMarshaller), ElementIndirectionDepth = 1)] - public static partial TestCollection Method( - [MarshalUsing(typeof(CustomIntMarshaller), ElementIndirectionDepth = 1)] TestCollection p, - [MarshalUsing(typeof(CustomIntMarshaller), ElementIndirectionDepth = 1)] in TestCollection pIn, - int pRefSize, - [MarshalUsing(CountElementName = ""pRefSize""), MarshalUsing(typeof(CustomIntMarshaller), ElementIndirectionDepth = 1)] ref TestCollection pRef, - [MarshalUsing(CountElementName = ""pOutSize"")][MarshalUsing(typeof(CustomIntMarshaller), ElementIndirectionDepth = 1)] out TestCollection pOut, - out int pOutSize - ); -}} -" - + TestCollection() - + Ref - + CustomIntMarshaller; - } - } - public static string MarshalUsingCollectionCountInfoParametersAndModifiers(string collectionType) => $@" using System.Runtime.InteropServices; using System.Runtime.InteropServices.Marshalling; @@ -1806,6 +835,50 @@ public static partial int Method( ); }}"; + public static string MarshalUsingCollectionOutConstantLength(string collectionType, string predeclaration = "") => $@" +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; +{predeclaration} +partial class Test +{{ + [LibraryImport(""DoesNotExist"")] + public static partial int Method( + [MarshalUsing(ConstantElementCount = 10)] out {collectionType} pOut); +}} +"; + + public static string MarshalUsingCollectionReturnConstantLength(string collectionType, string predeclaration = "") => $@" +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; +{predeclaration} +partial class Test +{{ + [LibraryImport(""DoesNotExist"")] + [return:MarshalUsing(ConstantElementCount = 10)] + public static partial {collectionType} Method(); +}} +"; + public static string CustomElementMarshalling(string collectionType, string elementMarshaller, string predeclaration = "") => $@" +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; +{predeclaration} +{DisableRuntimeMarshalling} +partial class Test +{{ + [LibraryImport(""DoesNotExist"")] + [return:MarshalUsing(ConstantElementCount=10)] + [return:MarshalUsing(typeof({elementMarshaller}), ElementIndirectionDepth = 1)] + public static partial {collectionType} Method( + [MarshalUsing(typeof({elementMarshaller}), ElementIndirectionDepth = 1)] {collectionType} p, + [MarshalUsing(typeof({elementMarshaller}), ElementIndirectionDepth = 1)] in {collectionType} pIn, + int pRefSize, + [MarshalUsing(CountElementName = ""pRefSize""), MarshalUsing(typeof({elementMarshaller}), ElementIndirectionDepth = 1)] ref {collectionType} pRef, + [MarshalUsing(CountElementName = ""pOutSize"")][MarshalUsing(typeof({elementMarshaller}), ElementIndirectionDepth = 1)] out {collectionType} pOut, + out int pOutSize + ); +}} +" + public static string MarshalUsingArrayParameterWithSizeParam(string sizeParamType, bool isByRef) => $@" using System.Runtime.InteropServices; using System.Runtime.InteropServices.Marshalling; diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CompileFails.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CompileFails.cs index 7ccfa1611cdb5..58dbb14a1d147 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CompileFails.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CompileFails.cs @@ -14,6 +14,8 @@ using Microsoft.Interop.UnitTests; using Xunit; +using StringMarshalling = Microsoft.Interop.StringMarshalling; + namespace LibraryImportGenerator.UnitTests { public class CompileFails diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/Compiles.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/Compiles.cs index fab9a7752666d..1096470ec4491 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/Compiles.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/Compiles.cs @@ -1,10 +1,10 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using LibraryImportGenerator.UnitTests; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.Interop; using Microsoft.Interop.UnitTests; using System; using System.Collections.Generic; @@ -14,6 +14,8 @@ using System.Threading.Tasks; using Xunit; +using StringMarshalling = Microsoft.Interop.StringMarshalling; + namespace LibraryImportGenerator.UnitTests { public class Compiles diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/LibraryImportGenerator.Unit.Tests.csproj b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/LibraryImportGenerator.Unit.Tests.csproj index 9fe3bfb71f801..934200878bad3 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/LibraryImportGenerator.Unit.Tests.csproj +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/LibraryImportGenerator.Unit.Tests.csproj @@ -11,6 +11,10 @@ Link="Common\SourceGenerators\LiveReferencePack.cs" /> + + From a9585527239fcb8483275285788213c836ba3a0a Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Wed, 24 Aug 2022 11:55:09 -0700 Subject: [PATCH 19/30] Use static abstracts instead of partial + containing class to define a solid contract to simplify authoring our custom type marshalling tests --- .../CodeSnippets.cs | 15 +- .../ComInterfaceGenerator.Unit.Tests.csproj | 10 +- .../Compiles.cs | 336 +++++------ .../CodeSnippets.CustomStructMarshalling.cs | 522 ------------------ ...ustomCollectionMarshallingCodeSnippets.cs} | 461 ++++++++-------- .../CustomStructMarshallingCodeSnippets.cs | 522 ++++++++++++++++++ ...ICustomMarshallingSignatureTestProvider.cs | 32 ++ .../CodeSnippets.cs | 33 +- .../CompileFails.cs | 24 +- .../Compiles.cs | 394 ++++++------- .../LibraryImportGenerator.Unit.Tests.csproj | 10 +- 11 files changed, 1196 insertions(+), 1163 deletions(-) delete mode 100644 src/libraries/System.Runtime.InteropServices/tests/Common/CodeSnippets.CustomStructMarshalling.cs rename src/libraries/System.Runtime.InteropServices/tests/Common/{CodeSnippets.CustomCollectionMarshalling.cs => CustomCollectionMarshallingCodeSnippets.cs} (50%) create mode 100644 src/libraries/System.Runtime.InteropServices/tests/Common/CustomStructMarshallingCodeSnippets.cs create mode 100644 src/libraries/System.Runtime.InteropServices/tests/Common/ICustomMarshallingSignatureTestProvider.cs 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 a2a14d091154e..648bf48640168 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 @@ -9,7 +9,7 @@ namespace Microsoft.Interop.UnitTests { - internal static partial class CodeSnippets + internal partial class CodeSnippets : ICustomMarshallingSignatureTestProvider { public static readonly string DisableRuntimeMarshalling = "[assembly:System.Runtime.CompilerServices.DisableRuntimeMarshalling]"; public static readonly string UsingSystemRuntimeInteropServicesMarshalling = "using System.Runtime.InteropServices.Marshalling;"; @@ -151,10 +151,11 @@ partial interface INativeAPI [VirtualMethodIndex(0, ImplicitThisParameter = false)] void Method({modifier} {typeName} value); }}" + NativeInterfaceUsage(); - public static string BasicReturnType(string typeName) => $@" + public static string BasicReturnType(string typeName, string preDeclaration = "") => $@" using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.InteropServices.Marshalling; +{preDeclaration} readonly record struct NoCasting {{}} partial interface INativeAPI @@ -182,12 +183,10 @@ partial interface INativeAPI [MarshalUsing(typeof({marshallerTypeName}))] out {typeName} pOut); }}" + NativeInterfaceUsage(); public static string MarshalUsingCollectionCountInfoParametersAndModifiers() => MarshalUsingCollectionCountInfoParametersAndModifiers(typeof(T).ToString()); - public static string MarshalUsingCollectionCountInfoParametersAndModifiers(string collectionType, string preDeclaration = "") => $@" + public static string MarshalUsingCollectionCountInfoParametersAndModifiers(string collectionType) => $@" using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.InteropServices.Marshalling; -{preDeclaration} - [assembly:DisableRuntimeMarshalling] readonly record struct NoCasting {{}} @@ -204,11 +203,10 @@ partial interface INativeAPI [MarshalUsing(CountElementName = ""pOutSize"")] out {collectionType} pOut, out int pOutSize); }}" + NativeInterfaceUsage(); - public static string MarshalUsingCollectionParametersAndModifiers(string collectionType, string marshallerType, string preDeclaration = "") => $@" + public static string MarshalUsingCollectionParametersAndModifiers(string collectionType, string marshallerType) => $@" using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.InteropServices.Marshalling; -{preDeclaration} [assembly:DisableRuntimeMarshalling] @@ -227,11 +225,10 @@ partial interface INativeAPI out int pOutSize ); }}" + NativeInterfaceUsage(); - public static string MarshalUsingCollectionReturnValueLength(string collectionType, string marshallerType, string preDeclaration = "") => $@" + public static string MarshalUsingCollectionReturnValueLength(string collectionType, string marshallerType) => $@" using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.InteropServices.Marshalling; -{preDeclaration} [assembly:DisableRuntimeMarshalling] diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/ComInterfaceGenerator.Unit.Tests.csproj b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/ComInterfaceGenerator.Unit.Tests.csproj index 273dd713a02b5..1fd768c257647 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/ComInterfaceGenerator.Unit.Tests.csproj +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/ComInterfaceGenerator.Unit.Tests.csproj @@ -13,10 +13,12 @@ Link="Common\SourceGenerators\LiveReferencePack.cs" /> - - + + + 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 7a41e72e5fabd..65ac54d8cc64c 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 @@ -51,37 +51,37 @@ public static IEnumerable CodeSnippetsToCompile() yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiersNoImplicitThis() }; // Custom type marshalling - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.ParametersAndModifiers }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.MarshalUsingParametersAndModifiers }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.NativeToManagedOnlyOutParameter }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.NativeToManagedFinallyOnlyOutParameter }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.NativeToManagedOnlyReturnValue }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.NativeToManagedFinallyOnlyReturnValue }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.ByValueInParameter }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.PinByValueInParameter }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.StackallocByValueInParameter }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.RefParameter }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.StackallocParametersAndModifiersNoRef }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.OptionalStackallocParametersAndModifiers }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.DefaultModeByValueInParameter }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.DefaultModeReturnValue }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.ParametersAndModifiers }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.ParametersAndModifiersWithFree }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.ParametersAndModifiersWithOnInvoked }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.MarshalUsingParametersAndModifiers }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.NativeToManagedOnlyOutParameter }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.NativeToManagedFinallyOnlyOutParameter }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.NativeToManagedOnlyReturnValue }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.NativeToManagedFinallyOnlyReturnValue }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.ByValueInParameter }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.StackallocByValueInParameter }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.PinByValueInParameter }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.MarshallerPinByValueInParameter }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.RefParameter }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.StackallocParametersAndModifiersNoRef }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.OptionalStackallocParametersAndModifiers }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.DefaultModeByValueInParameter }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.DefaultModeReturnValue }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateless.ParametersAndModifiers }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateless.MarshalUsingParametersAndModifiers }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateless.NativeToManagedOnlyOutParameter }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateless.NativeToManagedFinallyOnlyOutParameter }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateless.NativeToManagedOnlyReturnValue }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateless.NativeToManagedFinallyOnlyReturnValue }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateless.ByValueInParameter }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateless.PinByValueInParameter }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateless.StackallocByValueInParameter }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateless.RefParameter }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateless.StackallocParametersAndModifiersNoRef }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateless.OptionalStackallocParametersAndModifiers }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateless.DefaultModeByValueInParameter }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateless.DefaultModeReturnValue }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateful.ParametersAndModifiers }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateful.ParametersAndModifiersWithFree }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateful.ParametersAndModifiersWithOnInvoked }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateful.MarshalUsingParametersAndModifiers }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateful.NativeToManagedOnlyOutParameter }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateful.NativeToManagedFinallyOnlyOutParameter }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateful.NativeToManagedOnlyReturnValue }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateful.NativeToManagedFinallyOnlyReturnValue }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateful.ByValueInParameter }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateful.StackallocByValueInParameter }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateful.PinByValueInParameter }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateful.MarshallerPinByValueInParameter }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateful.RefParameter }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateful.StackallocParametersAndModifiersNoRef }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateful.OptionalStackallocParametersAndModifiers }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateful.DefaultModeByValueInParameter }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateful.DefaultModeReturnValue }; // SafeHandles yield return new[] { ID(), CodeSnippets.BasicParametersAndModifiers("Microsoft.Win32.SafeHandles.SafeFileHandle") }; @@ -90,78 +90,78 @@ public static IEnumerable CodeSnippetsToCompile() public static IEnumerable CustomCollections() { // Custom collection marshalling - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueCallerAllocatedBuffer() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueCallerAllocatedBuffer() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueCallerAllocatedBuffer() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueCallerAllocatedBuffer() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueCallerAllocatedBuffer() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueCallerAllocatedBuffer() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueCallerAllocatedBuffer() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueCallerAllocatedBuffer() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueCallerAllocatedBuffer() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueCallerAllocatedBuffer() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueCallerAllocatedBuffer() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueCallerAllocatedBuffer() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithStaticPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithStaticPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithStaticPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithStaticPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithStaticPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithStaticPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithStaticPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithStaticPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithStaticPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithStaticPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithStaticPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithStaticPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithStaticPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithStaticPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithStaticPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithStaticPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithStaticPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithStaticPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithStaticPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithStaticPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithStaticPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithStaticPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithStaticPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithStaticPinning() }; yield return new[] { ID(), CodeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers() }; yield return new[] { ID(), CodeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers() }; yield return new[] { ID(), CodeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers() }; @@ -174,71 +174,71 @@ public static IEnumerable CustomCollections() yield return new[] { ID(), CodeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers() }; yield return new[] { ID(), CodeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers() }; yield return new[] { ID(), CodeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomMarshallerReturnValueLength() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.NativeToManagedOnlyOutParameter() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.NativeToManagedOnlyReturnValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.NestedMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.NonBlittableElementByValue }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.NonBlittableElementParametersAndModifiers }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.NonBlittableElementNativeToManagedOnlyOutParameter }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.NonBlittableElementNativeToManagedOnlyReturnValue }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomElementMarshalling }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.CustomMarshallerReturnValueLength() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.NativeToManagedOnlyOutParameter() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.NativeToManagedOnlyReturnValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.NonBlittableElementByValue }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.NonBlittableElementParametersAndModifiers }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.NonBlittableElementNativeToManagedOnlyOutParameter }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.NonBlittableElementNativeToManagedOnlyReturnValue }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.CustomElementMarshalling }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.CustomMarshallerReturnValueLength() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.NativeToManagedOnlyOutParameter() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.NativeToManagedOnlyReturnValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.NestedMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.NonBlittableElementByValue }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.NonBlittableElementParametersAndModifiers }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.NonBlittableElementNativeToManagedOnlyOutParameter }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.NonBlittableElementNativeToManagedOnlyReturnValue }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.CustomElementMarshalling }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.CustomMarshallerReturnValueLength() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.NativeToManagedOnlyOutParameter() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.NativeToManagedOnlyReturnValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.NonBlittableElementByValue }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.NonBlittableElementParametersAndModifiers }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.NonBlittableElementNativeToManagedOnlyOutParameter }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.NonBlittableElementNativeToManagedOnlyReturnValue }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.CustomElementMarshalling }; } [Theory] diff --git a/src/libraries/System.Runtime.InteropServices/tests/Common/CodeSnippets.CustomStructMarshalling.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/CodeSnippets.CustomStructMarshalling.cs deleted file mode 100644 index 49ca5ac353634..0000000000000 --- a/src/libraries/System.Runtime.InteropServices/tests/Common/CodeSnippets.CustomStructMarshalling.cs +++ /dev/null @@ -1,522 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace Microsoft.Interop.UnitTests -{ - internal static partial class CodeSnippets - { - public static class CustomStructMarshalling - { - public static string NonBlittableUserDefinedType(bool defineNativeMarshalling = true) => $@" -{(defineNativeMarshalling ? "[NativeMarshalling(typeof(Marshaller))]" : string.Empty)} -public struct S -{{ -#pragma warning disable CS0649 // Field is never assigned to, and will always have its default value - public bool b; -#pragma warning restore CS0649 -}} -"; - private static string NonStatic = @" -[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller))] -public class Marshaller -{ - public struct Native { } - - public static Native ConvertToUnmanaged(S s) => default; -} -"; - public static string NonStaticMarshallerEntryPoint => BasicParameterByValue("S") - + NonBlittableUserDefinedType() - + NonStatic; - - private static string Struct = @" -[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller))] -public struct Marshaller -{ - public struct Native { } - - public void FromManaged(S s) {} - public Native ToUnmanaged() => default; -} -"; - public static string StructMarshallerEntryPoint => BasicParameterByValue("S") - + NonBlittableUserDefinedType() - + Struct; - - - public static class Stateless - { - private static string In = @" -[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller))] -public static class Marshaller -{ - public struct Native { } - - public static Native ConvertToUnmanaged(S s) => default; -} -"; - private static string InBuffer = @" -[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller))] -public static class Marshaller -{ - public struct Native { } - - public const int BufferSize = 0x100; - public static Native ConvertToUnmanaged(S s, System.Span buffer) => default; -} -"; - - public static string InPinnable = @" -[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller))] -public static unsafe class Marshaller -{ - public static byte* ConvertToUnmanaged(S s) => default; - public static ref byte GetPinnableReference(S s) => throw null; -} -"; - private static string Out = @" -[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedOut, typeof(Marshaller))] -public static class Marshaller -{ - public struct Native { } - - public static S ConvertToManaged(Native n) => default; -} -"; - private static string OutGuaranteed = @" -[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedOut, typeof(Marshaller))] -public static class Marshaller -{ - public struct Native { } - - public static S ConvertToManagedFinally(Native n) => default; -} -"; - public static string Ref = @" -[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedRef, typeof(Marshaller))] -public static class Marshaller -{ - public struct Native { } - - public static Native ConvertToUnmanaged(S s) => default; - public static S ConvertToManaged(Native n) => default; -} -"; - public static string Default = @" -[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(Marshaller))] -public static class Marshaller -{ - public struct Native { } - - public static Native ConvertToUnmanaged(S s) => default; - public static S ConvertToManaged(Native n) => default; -} -"; - public static string InOutBuffer = @" -[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller))] -[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedOut, typeof(Marshaller))] -public static class Marshaller -{ - public struct Native { } - - public const int BufferSize = 0x100; - public static Native ConvertToUnmanaged(S s, System.Span buffer) => default; - public static S ConvertToManaged(Native n) => default; -} -"; - public static string DefaultOptionalBuffer = @" -[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(Marshaller))] -public static class Marshaller -{ - public struct Native { } - - public const int BufferSize = 0x100; - public static Native ConvertToUnmanaged(S s) => default; - public static Native ConvertToUnmanaged(S s, System.Span buffer) => default; - public static S ConvertToManaged(Native n) => default; -} -"; - private static string DefaultIn = @" -[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(Marshaller))] -public static class Marshaller -{ - public struct Native { } - - public static Native ConvertToUnmanaged(S s) => default; -} -"; - private static string DefaultOut = @" -[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedOut, typeof(Marshaller))] -public static class Marshaller -{ - public struct Native { } - - public static S ConvertToManaged(Native n) => default; -} -"; - public static string ManagedToNativeOnlyOutParameter => BasicParameterWithByRefModifier("out", "S") - + NonBlittableUserDefinedType() - + In; - - public static string NativeToManagedOnlyOutParameter => BasicParameterWithByRefModifier("out", "S") - + NonBlittableUserDefinedType() - + Out; - - public static string NativeToManagedFinallyOnlyOutParameter => BasicParameterWithByRefModifier("out", "S") - + NonBlittableUserDefinedType() - + OutGuaranteed; - - public static string ManagedToNativeOnlyReturnValue => BasicReturnType("S") - + NonBlittableUserDefinedType() - + In; - - public static string NativeToManagedOnlyReturnValue => BasicReturnType("S") - + NonBlittableUserDefinedType() - + Out; - - public static string NativeToManagedFinallyOnlyReturnValue => BasicReturnType("S") - + NonBlittableUserDefinedType() - + Out; - - public static string NativeToManagedOnlyInParameter => BasicParameterWithByRefModifier("in", "S") - + NonBlittableUserDefinedType() - + Out; - - public static string ParametersAndModifiers = BasicParametersAndModifiers("S", UsingSystemRuntimeInteropServicesMarshalling) - + NonBlittableUserDefinedType(defineNativeMarshalling: true) - + Default; - - public static string MarshalUsingParametersAndModifiers = MarshalUsingParametersAndModifiers("S", "Marshaller") - + NonBlittableUserDefinedType(defineNativeMarshalling: false) - + Default; - - public static string ByValueInParameter => BasicParameterByValue("S") - + NonBlittableUserDefinedType() - + In; - - public static string StackallocByValueInParameter => BasicParameterByValue("S") - + NonBlittableUserDefinedType() - + InBuffer; - - public static string PinByValueInParameter => BasicParameterByValue("S") - + NonBlittableUserDefinedType() - + InPinnable; - - public static string StackallocParametersAndModifiersNoRef = BasicParametersAndModifiersNoRef("S") - + NonBlittableUserDefinedType() - + InOutBuffer; - - public static string RefParameter = BasicParameterWithByRefModifier("ref", "S") - + NonBlittableUserDefinedType() - + Ref; - - public static string StackallocOnlyRefParameter = BasicParameterWithByRefModifier("ref", "S") - + NonBlittableUserDefinedType() - + InOutBuffer; - - public static string OptionalStackallocParametersAndModifiers = BasicParametersAndModifiers("S", UsingSystemRuntimeInteropServicesMarshalling) - + NonBlittableUserDefinedType() - + DefaultOptionalBuffer; - - public static string DefaultModeByValueInParameter => BasicParameterByValue("S") - + NonBlittableUserDefinedType() - + DefaultIn; - - public static string DefaultModeReturnValue => BasicReturnType("S") - + NonBlittableUserDefinedType() - + DefaultOut; - } - - public static class Stateful - { - private static string In = @" -[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(M))] -public static class Marshaller -{ - public struct Native { } - - public struct M - { - public void FromManaged(S s) {} - public Native ToUnmanaged() => default; - } -} -"; - - public static string InStatelessPinnable = @" -[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(M))] -public static class Marshaller -{ - public unsafe struct M - { - public void FromManaged(S s) {} - public byte* ToUnmanaged() => default; - - public static ref byte GetPinnableReference(S s) => throw null; - } -} -"; - - public static string InPinnable = @" -[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(M))] -public static class Marshaller -{ - public unsafe struct M - { - public void FromManaged(S s) {} - public byte* ToUnmanaged() => default; - - public ref byte GetPinnableReference() => throw null; - } -} -"; - - private static string InBuffer = @" -[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(M))] -public static class Marshaller -{ - public struct Native { } - - public struct M - { - public const int BufferSize = 0x100; - public void FromManaged(S s, System.Span buffer) {} - public Native ToUnmanaged() => default; - } -} -"; - private static string Out = @" -[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedOut, typeof(M))] -public static class Marshaller -{ - public struct Native { } - - public struct M - { - public void FromUnmanaged(Native n) {} - public S ToManaged() => default; - } -} -"; - private static string OutGuaranteed = @" -[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedOut, typeof(M))] -public static class Marshaller -{ - public struct Native { } - - public struct M - { - public void FromUnmanaged(Native n) {} - public S ToManagedFinally() => default; - } -} -"; - public static string Ref = @" -[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedRef, typeof(M))] -public static class Marshaller -{ - public struct Native { } - - public struct M - { - public void FromManaged(S s) {} - public Native ToUnmanaged() => default; - public void FromUnmanaged(Native n) {} - public S ToManaged() => default; - } -} -"; - public static string Default = @" -[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(M))] -public static class Marshaller -{ - public struct Native { } - - public struct M - { - public void FromManaged(S s) {} - public Native ToUnmanaged() => default; - public void FromUnmanaged(Native n) {} - public S ToManaged() => default; - } -} -"; - public static string DefaultWithFree = @" -[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(M))] -public static class Marshaller -{ - public struct Native { } - - public struct M - { - public void FromManaged(S s) {} - public Native ToUnmanaged() => default; - public void FromUnmanaged(Native n) {} - public S ToManaged() => default; - public void Free() {} - } -} -"; - public static string DefaultWithOnInvoked = @" -[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(M))] -public static class Marshaller -{ - public struct Native { } - - public struct M - { - public void FromManaged(S s) {} - public Native ToUnmanaged() => default; - public void FromUnmanaged(Native n) {} - public S ToManaged() => default; - public void OnInvoked() {} - } -} -"; - public static string InOutBuffer = @" -[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(M))] -[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedOut, typeof(M))] -public static class Marshaller -{ - public struct Native { } - - public struct M - { - public const int BufferSize = 0x100; - public void FromManaged(S s, System.Span buffer) {} - public Native ToUnmanaged() => default; - public void FromUnmanaged(Native n) {} - public S ToManaged() => default; - } -} -"; - public static string DefaultOptionalBuffer = @" -[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(M))] -public static class Marshaller -{ - public struct Native { } - - public struct M - { - public const int BufferSize = 0x100; - public void FromManaged(S s) {} - public void FromManaged(S s, System.Span buffer) {} - public Native ToUnmanaged() => default; - public void FromUnmanaged(Native n) {} - public S ToManaged() => default; - } -} -"; - private static string DefaultIn = @" -[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(M))] -public static class Marshaller -{ - public struct Native { } - - public struct M - { - public void FromManaged(S s) {} - public Native ToUnmanaged() => default; - } -} -"; - private static string DefaultOut = @" -[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(M))] -public static class Marshaller -{ - public struct Native { } - - public struct M - { - public void FromUnmanaged(Native n) {} - public S ToManaged() => default; - } -} -"; - public static string ManagedToNativeOnlyOutParameter => BasicParameterWithByRefModifier("out", "S") - + NonBlittableUserDefinedType() - + In; - - public static string NativeToManagedOnlyOutParameter => BasicParameterWithByRefModifier("out", "S") - + NonBlittableUserDefinedType() - + Out; - - public static string NativeToManagedFinallyOnlyOutParameter => BasicParameterWithByRefModifier("out", "S") - + NonBlittableUserDefinedType() - + OutGuaranteed; - - public static string ManagedToNativeOnlyReturnValue => BasicReturnType("S") - + NonBlittableUserDefinedType() - + In; - - public static string NativeToManagedOnlyReturnValue => BasicReturnType("S") - + NonBlittableUserDefinedType() - + Out; - - public static string NativeToManagedFinallyOnlyReturnValue => BasicReturnType("S") - + NonBlittableUserDefinedType() - + Out; - - public static string NativeToManagedOnlyInParameter => BasicParameterWithByRefModifier("in", "S") - + NonBlittableUserDefinedType() - + Out; - - public static string ParametersAndModifiers = BasicParametersAndModifiers("S", UsingSystemRuntimeInteropServicesMarshalling) - + NonBlittableUserDefinedType(defineNativeMarshalling: true) - + Default; - - public static string ParametersAndModifiersWithFree = BasicParametersAndModifiers("S", UsingSystemRuntimeInteropServicesMarshalling) - + NonBlittableUserDefinedType(defineNativeMarshalling: true) - + DefaultWithFree; - - public static string ParametersAndModifiersWithOnInvoked = BasicParametersAndModifiers("S", UsingSystemRuntimeInteropServicesMarshalling) - + NonBlittableUserDefinedType(defineNativeMarshalling: true) - + DefaultWithOnInvoked; - - public static string MarshalUsingParametersAndModifiers = MarshalUsingParametersAndModifiers("S", "Marshaller") - + NonBlittableUserDefinedType(defineNativeMarshalling: false) - + Default; - - public static string ByValueInParameter => BasicParameterByValue("S") - + NonBlittableUserDefinedType() - + In; - - public static string StackallocByValueInParameter => BasicParameterByValue("S") - + NonBlittableUserDefinedType() - + InBuffer; - - public static string PinByValueInParameter => BasicParameterByValue("S") - + NonBlittableUserDefinedType() - + InStatelessPinnable; - - public static string MarshallerPinByValueInParameter => BasicParameterByValue("S") - + NonBlittableUserDefinedType() - + InPinnable; - - public static string StackallocParametersAndModifiersNoRef = BasicParametersAndModifiersNoRef("S") - + NonBlittableUserDefinedType() - + InOutBuffer; - - public static string RefParameter = BasicParameterWithByRefModifier("ref", "S") - + NonBlittableUserDefinedType() - + Ref; - - public static string StackallocOnlyRefParameter = BasicParameterWithByRefModifier("ref", "S") - + NonBlittableUserDefinedType() - + InOutBuffer; - - public static string OptionalStackallocParametersAndModifiers = BasicParametersAndModifiers("S", UsingSystemRuntimeInteropServicesMarshalling) - + NonBlittableUserDefinedType() - + DefaultOptionalBuffer; - - public static string DefaultModeByValueInParameter => BasicParameterByValue("S") - + NonBlittableUserDefinedType() - + DefaultIn; - - public static string DefaultModeReturnValue => BasicReturnType("S") - + NonBlittableUserDefinedType() - + DefaultOut; - } - } - } -} diff --git a/src/libraries/System.Runtime.InteropServices/tests/Common/CodeSnippets.CustomCollectionMarshalling.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/CustomCollectionMarshallingCodeSnippets.cs similarity index 50% rename from src/libraries/System.Runtime.InteropServices/tests/Common/CodeSnippets.CustomCollectionMarshalling.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/CustomCollectionMarshallingCodeSnippets.cs index 2a0f9dac56cc3..e5a92ce40f84c 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/Common/CodeSnippets.CustomCollectionMarshalling.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/Common/CustomCollectionMarshallingCodeSnippets.cs @@ -3,18 +3,20 @@ namespace Microsoft.Interop.UnitTests { - internal static partial class CodeSnippets + public static class CustomCollectionMarshallingCodeSnippets + where TSignatureTestProvider : ICustomMarshallingSignatureTestProvider { - public static class CustomCollectionMarshalling - { - public static string TestCollection(bool defineNativeMarshalling = true) => $@" + public static readonly string DisableRuntimeMarshalling = "[assembly:System.Runtime.CompilerServices.DisableRuntimeMarshalling]"; + public static readonly string UsingSystemRuntimeInteropServicesMarshalling = "using System.Runtime.InteropServices.Marshalling;"; + + public static string TestCollection(bool defineNativeMarshalling = true) => $@" {(defineNativeMarshalling ? "[NativeMarshalling(typeof(Marshaller<,>))]" : string.Empty)} class TestCollection {{}} "; - public static string CollectionOutParameter(string collectionType, string predeclaration = "") => MarshalUsingCollectionOutConstantLength(collectionType, predeclaration); - public static string CollectionReturnType(string collectionType, string predeclaration = "") => MarshalUsingCollectionReturnConstantLength(collectionType, predeclaration); - public const string NonBlittableElement = @" + public static string CollectionOutParameter(string collectionType, string predeclaration = "") => TSignatureTestProvider.MarshalUsingCollectionOutConstantLength(collectionType, predeclaration); + public static string CollectionReturnType(string collectionType, string predeclaration = "") => TSignatureTestProvider.MarshalUsingCollectionReturnConstantLength(collectionType, predeclaration); + public const string NonBlittableElement = @" [NativeMarshalling(typeof(ElementMarshaller))] struct Element { @@ -23,7 +25,7 @@ struct Element #pragma warning restore CS0649 } "; - public const string ElementMarshaller = @" + public const string ElementMarshaller = @" [CustomMarshaller(typeof(Element), MarshalMode.ElementIn, typeof(ElementMarshaller))] [CustomMarshaller(typeof(Element), MarshalMode.ElementRef, typeof(ElementMarshaller))] [CustomMarshaller(typeof(Element), MarshalMode.ElementOut, typeof(ElementMarshaller))] @@ -34,7 +36,7 @@ public struct Native { } public static Element ConvertToManaged(Native n) => throw null; } "; - public const string ElementIn = @" + public const string ElementIn = @" [CustomMarshaller(typeof(Element), MarshalMode.ElementIn, typeof(ElementMarshaller))] static class ElementMarshaller { @@ -43,7 +45,7 @@ public struct Native { } public static Element ConvertToManaged(Native n) => throw null; } "; - public const string ElementOut = @" + public const string ElementOut = @" [CustomMarshaller(typeof(Element), MarshalMode.ElementOut, typeof(ElementMarshaller))] static class ElementMarshaller { @@ -52,7 +54,7 @@ public struct Native { } public static Element ConvertToManaged(Native n) => throw null; } "; - public const string CustomIntMarshaller = @" + public const string CustomIntMarshaller = @" [CustomMarshaller(typeof(int), MarshalMode.ElementIn, typeof(CustomIntMarshaller))] [CustomMarshaller(typeof(int), MarshalMode.ElementRef, typeof(CustomIntMarshaller))] [CustomMarshaller(typeof(int), MarshalMode.ElementOut, typeof(CustomIntMarshaller))] @@ -63,9 +65,9 @@ public struct Native { } public static int ConvertToManaged(Native n) => throw null; } "; - public static class Stateless - { - public const string In = @" + public static class Stateless + { + public const string In = @" [CustomMarshaller(typeof(TestCollection<>), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller<,>))] [ContiguousCollectionMarshaller] static unsafe class Marshaller where TUnmanagedElement : unmanaged @@ -75,7 +77,7 @@ static unsafe class Marshaller where TUnmanagedElement : u public static System.Span GetUnmanagedValuesDestination(byte* unmanaged, int numElements) => throw null; } "; - public const string InPinnable = @" + public const string InPinnable = @" [CustomMarshaller(typeof(TestCollection<>), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller<,>))] [ContiguousCollectionMarshaller] static unsafe class Marshaller where TUnmanagedElement : unmanaged @@ -87,7 +89,7 @@ static unsafe class Marshaller where TUnmanagedElement : u public static ref byte GetPinnableReference(TestCollection managed) => throw null; } "; - public const string InBuffer = @" + public const string InBuffer = @" [CustomMarshaller(typeof(TestCollection<>), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller<,>))] [ContiguousCollectionMarshaller] static unsafe class Marshaller where TUnmanagedElement : unmanaged @@ -98,7 +100,7 @@ static unsafe class Marshaller where TUnmanagedElement : u public static System.Span GetUnmanagedValuesDestination(byte* unmanaged, int numElements) => throw null; } "; - public const string Default = @" + public const string Default = @" [CustomMarshaller(typeof(TestCollection<>), MarshalMode.Default, typeof(Marshaller<,>))] [ContiguousCollectionMarshaller] static unsafe class Marshaller where TUnmanagedElement : unmanaged @@ -112,7 +114,7 @@ static unsafe class Marshaller where TUnmanagedElement : u public static System.ReadOnlySpan GetUnmanagedValuesSource(byte* unmanaged, int numElements) => throw null; } "; - public const string DefaultNested = @" + public const string DefaultNested = @" [CustomMarshaller(typeof(TestCollection<>), MarshalMode.Default, typeof(Marshaller<,>.Nested.Ref))] [ContiguousCollectionMarshaller] static unsafe class Marshaller where TUnmanagedElement : unmanaged @@ -132,7 +134,7 @@ internal static class Ref } } "; - public const string Out = @" + public const string Out = @" [CustomMarshaller(typeof(TestCollection<>), MarshalMode.ManagedToUnmanagedOut, typeof(Marshaller<,>))] [ContiguousCollectionMarshaller] static unsafe class Marshaller where TUnmanagedElement : unmanaged @@ -152,7 +154,7 @@ static unsafe class Marshaller where TUnmanagedElement : u public static System.ReadOnlySpan GetUnmanagedValuesSource(byte* unmanaged, int numElements) => throw null; } "; - public const string DefaultIn = @" + public const string DefaultIn = @" [CustomMarshaller(typeof(TestCollection<>), MarshalMode.Default, typeof(Marshaller<,>))] [ContiguousCollectionMarshaller] static unsafe class Marshaller where TUnmanagedElement : unmanaged @@ -162,7 +164,7 @@ static unsafe class Marshaller where TUnmanagedElement : u public static System.Span GetUnmanagedValuesDestination(byte* unmanaged, int numElements) => throw null; } "; - public const string DefaultOut = @" + public const string DefaultOut = @" [CustomMarshaller(typeof(TestCollection<>), MarshalMode.Default, typeof(Marshaller<,>))] [ContiguousCollectionMarshaller] static unsafe class Marshaller where TUnmanagedElement : unmanaged @@ -172,93 +174,93 @@ static unsafe class Marshaller where TUnmanagedElement : u public static System.ReadOnlySpan GetUnmanagedValuesSource(byte* unmanaged, int numElements) => throw null; } "; - public static string ByValue() => ByValue(typeof(T).ToString()); - public static string ByValue(string elementType) => BasicParameterByValue($"TestCollection<{elementType}>", DisableRuntimeMarshalling) - + TestCollection() - + In; - - public static string ByValueWithPinning() => ByValueWithPinning(typeof(T).ToString()); - public static string ByValueWithPinning(string elementType) => BasicParameterByValue($"TestCollection<{elementType}>", DisableRuntimeMarshalling) - + TestCollection() - + InPinnable; - - public static string ByValueCallerAllocatedBuffer() => ByValueCallerAllocatedBuffer(typeof(T).ToString()); - public static string ByValueCallerAllocatedBuffer(string elementType) => BasicParameterByValue($"TestCollection<{elementType}>", DisableRuntimeMarshalling) - + TestCollection() - + InBuffer; - - public static string DefaultMarshallerParametersAndModifiers() => DefaultMarshallerParametersAndModifiers(typeof(T).ToString()); - public static string DefaultMarshallerParametersAndModifiers(string elementType) => MarshalUsingCollectionCountInfoParametersAndModifiers($"TestCollection<{elementType}>") - + TestCollection() - + Default; - - public static string CustomMarshallerParametersAndModifiers() => CustomMarshallerParametersAndModifiers(typeof(T).ToString()); - public static string CustomMarshallerParametersAndModifiers(string elementType) => MarshalUsingCollectionParametersAndModifiers($"TestCollection<{elementType}>", $"Marshaller<,>") - + TestCollection(defineNativeMarshalling: false) - + Default; - - public static string CustomMarshallerReturnValueLength() => CustomMarshallerReturnValueLength(typeof(T).ToString()); - public static string CustomMarshallerReturnValueLength(string elementType) => MarshalUsingCollectionReturnValueLength($"TestCollection<{elementType}>", $"Marshaller<,>") - + TestCollection(defineNativeMarshalling: false) - + Default; - - public static string NativeToManagedOnlyOutParameter() => NativeToManagedOnlyOutParameter(typeof(T).ToString()); - public static string NativeToManagedOnlyOutParameter(string elementType) => CollectionOutParameter($"TestCollection<{elementType}>") - + TestCollection() - + Out; - - public static string NativeToManagedFinallyOnlyOutParameter() => NativeToManagedFinallyOnlyOutParameter(typeof(T).ToString()); - public static string NativeToManagedFinallyOnlyOutParameter(string elementType) => CollectionOutParameter($"TestCollection<{elementType}>") - + TestCollection() - + OutGuaranteed; - public static string NativeToManagedOnlyReturnValue() => NativeToManagedOnlyReturnValue(typeof(T).ToString()); - public static string NativeToManagedOnlyReturnValue(string elementType) => CollectionReturnType($"TestCollection<{elementType}>") - + TestCollection() - + Out; - - public static string NativeToManagedFinallyOnlyReturnValue() => NativeToManagedFinallyOnlyReturnValue(typeof(T).ToString()); - public static string NativeToManagedFinallyOnlyReturnValue(string elementType) => CollectionReturnType($"TestCollection<{elementType}>") - + TestCollection() - + OutGuaranteed; - public static string NestedMarshallerParametersAndModifiers() => NestedMarshallerParametersAndModifiers(typeof(T).ToString()); - public static string NestedMarshallerParametersAndModifiers(string elementType) => MarshalUsingCollectionCountInfoParametersAndModifiers($"TestCollection<{elementType}>") - + TestCollection() - + DefaultNested; - - public static string NonBlittableElementParametersAndModifiers => DefaultMarshallerParametersAndModifiers("Element") - + NonBlittableElement - + ElementMarshaller; - - public static string NonBlittableElementByValue => ByValue("Element") - + NonBlittableElement - + ElementIn; - - public static string NonBlittableElementNativeToManagedOnlyOutParameter => NativeToManagedOnlyOutParameter("Element") - + NonBlittableElement - + ElementOut; - - public static string NonBlittableElementNativeToManagedFinallyOnlyOutParameter => NativeToManagedFinallyOnlyOutParameter("Element") - + NonBlittableElement - + ElementOut; - - public static string NonBlittableElementNativeToManagedOnlyReturnValue => NativeToManagedOnlyOutParameter("Element") - + NonBlittableElement - + ElementOut; - - public static string NonBlittableElementNativeToManagedFinallyOnlyReturnValue => NativeToManagedFinallyOnlyOutParameter("Element") - + NonBlittableElement - + ElementOut; - - public static string DefaultModeByValueInParameter => BasicParameterByValue($"TestCollection", DisableRuntimeMarshalling) - + TestCollection() - + DefaultIn; - - public static string DefaultModeReturnValue => CollectionOutParameter($"TestCollection") - + TestCollection() - + DefaultOut; - - public static string GenericCollectionMarshallingArityMismatch => BasicParameterByValue("TestCollection", DisableRuntimeMarshalling) - + @" + public static string ByValue() => ByValue(typeof(T).ToString()); + public static string ByValue(string elementType) => TSignatureTestProvider.BasicParameterByValue($"TestCollection<{elementType}>", DisableRuntimeMarshalling) + + TestCollection() + + In; + + public static string ByValueWithPinning() => ByValueWithPinning(typeof(T).ToString()); + public static string ByValueWithPinning(string elementType) => TSignatureTestProvider.BasicParameterByValue($"TestCollection<{elementType}>", DisableRuntimeMarshalling) + + TestCollection() + + InPinnable; + + public static string ByValueCallerAllocatedBuffer() => ByValueCallerAllocatedBuffer(typeof(T).ToString()); + public static string ByValueCallerAllocatedBuffer(string elementType) => TSignatureTestProvider.BasicParameterByValue($"TestCollection<{elementType}>", DisableRuntimeMarshalling) + + TestCollection() + + InBuffer; + + public static string DefaultMarshallerParametersAndModifiers() => DefaultMarshallerParametersAndModifiers(typeof(T).ToString()); + public static string DefaultMarshallerParametersAndModifiers(string elementType) => TSignatureTestProvider.MarshalUsingCollectionCountInfoParametersAndModifiers($"TestCollection<{elementType}>") + + TestCollection() + + Default; + + public static string CustomMarshallerParametersAndModifiers() => CustomMarshallerParametersAndModifiers(typeof(T).ToString()); + public static string CustomMarshallerParametersAndModifiers(string elementType) => TSignatureTestProvider.MarshalUsingCollectionParametersAndModifiers($"TestCollection<{elementType}>", $"Marshaller<,>") + + TestCollection(defineNativeMarshalling: false) + + Default; + + public static string CustomMarshallerReturnValueLength() => CustomMarshallerReturnValueLength(typeof(T).ToString()); + public static string CustomMarshallerReturnValueLength(string elementType) => TSignatureTestProvider.MarshalUsingCollectionReturnValueLength($"TestCollection<{elementType}>", $"Marshaller<,>") + + TestCollection(defineNativeMarshalling: false) + + Default; + + public static string NativeToManagedOnlyOutParameter() => NativeToManagedOnlyOutParameter(typeof(T).ToString()); + public static string NativeToManagedOnlyOutParameter(string elementType) => CollectionOutParameter($"TestCollection<{elementType}>") + + TestCollection() + + Out; + + public static string NativeToManagedFinallyOnlyOutParameter() => NativeToManagedFinallyOnlyOutParameter(typeof(T).ToString()); + public static string NativeToManagedFinallyOnlyOutParameter(string elementType) => CollectionOutParameter($"TestCollection<{elementType}>") + + TestCollection() + + OutGuaranteed; + public static string NativeToManagedOnlyReturnValue() => NativeToManagedOnlyReturnValue(typeof(T).ToString()); + public static string NativeToManagedOnlyReturnValue(string elementType) => CollectionReturnType($"TestCollection<{elementType}>") + + TestCollection() + + Out; + + public static string NativeToManagedFinallyOnlyReturnValue() => NativeToManagedFinallyOnlyReturnValue(typeof(T).ToString()); + public static string NativeToManagedFinallyOnlyReturnValue(string elementType) => CollectionReturnType($"TestCollection<{elementType}>") + + TestCollection() + + OutGuaranteed; + public static string NestedMarshallerParametersAndModifiers() => NestedMarshallerParametersAndModifiers(typeof(T).ToString()); + public static string NestedMarshallerParametersAndModifiers(string elementType) => TSignatureTestProvider.MarshalUsingCollectionCountInfoParametersAndModifiers($"TestCollection<{elementType}>") + + TestCollection() + + DefaultNested; + + public static string NonBlittableElementParametersAndModifiers => DefaultMarshallerParametersAndModifiers("Element") + + NonBlittableElement + + ElementMarshaller; + + public static string NonBlittableElementByValue => ByValue("Element") + + NonBlittableElement + + ElementIn; + + public static string NonBlittableElementNativeToManagedOnlyOutParameter => NativeToManagedOnlyOutParameter("Element") + + NonBlittableElement + + ElementOut; + + public static string NonBlittableElementNativeToManagedFinallyOnlyOutParameter => NativeToManagedFinallyOnlyOutParameter("Element") + + NonBlittableElement + + ElementOut; + + public static string NonBlittableElementNativeToManagedOnlyReturnValue => NativeToManagedOnlyOutParameter("Element") + + NonBlittableElement + + ElementOut; + + public static string NonBlittableElementNativeToManagedFinallyOnlyReturnValue => NativeToManagedFinallyOnlyOutParameter("Element") + + NonBlittableElement + + ElementOut; + + public static string DefaultModeByValueInParameter => TSignatureTestProvider.BasicParameterByValue($"TestCollection", DisableRuntimeMarshalling) + + TestCollection() + + DefaultIn; + + public static string DefaultModeReturnValue => CollectionOutParameter($"TestCollection") + + TestCollection() + + DefaultOut; + + public static string GenericCollectionMarshallingArityMismatch => TSignatureTestProvider.BasicParameterByValue("TestCollection", DisableRuntimeMarshalling) + + @" [NativeMarshalling(typeof(Marshaller<,,>))] class TestCollection {} @@ -276,45 +278,15 @@ static unsafe class Marshaller where TUnmanagedElement } "; - public static string CustomElementMarshalling => CodeSnippets.CustomElementMarshalling("TestCollection", "CustomIntMarshaller") - + TestCollection() - + Default - + CustomIntMarshaller; - - public static string CustomElementMarshallingDuplicateElementIndirectionDepth => $@" -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.Marshalling; -{DisableRuntimeMarshalling} -partial class Test -{{ - [LibraryImport(""DoesNotExist"")] - public static partial void Method( - [MarshalUsing(typeof(CustomIntMarshaller), ElementIndirectionDepth = 1)] [MarshalUsing(typeof(CustomIntMarshaller), ElementIndirectionDepth = 1)] TestCollection p); -}} -" - + TestCollection() - + In - + CustomIntMarshaller; - - public static string CustomElementMarshallingUnusedElementIndirectionDepth => $@" -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.Marshalling; -{DisableRuntimeMarshalling} -partial class Test -{{ - [LibraryImport(""DoesNotExist"")] - public static partial void Method( - [MarshalUsing(typeof(CustomIntMarshaller), ElementIndirectionDepth = 2)] TestCollection p); -}} -" - + TestCollection() - + In - + CustomIntMarshaller; - } - - public static class Stateful - { - public const string In = @" + public static string CustomElementMarshalling => TSignatureTestProvider.CustomElementMarshalling("TestCollection", "CustomIntMarshaller") + + TestCollection() + + Default + + CustomIntMarshaller; + } + + public static class Stateful + { + public const string In = @" [ContiguousCollectionMarshaller] [CustomMarshaller(typeof(TestCollection<>), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller<,>.In))] static unsafe class Marshaller where TUnmanagedElement : unmanaged @@ -328,7 +300,7 @@ public ref struct In } } "; - public const string InPinnable = @" + public const string InPinnable = @" [ContiguousCollectionMarshaller] [CustomMarshaller(typeof(TestCollection<>), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller<,>.In))] static unsafe class Marshaller where TUnmanagedElement : unmanaged @@ -343,7 +315,7 @@ public ref struct In } } "; - public const string InStaticPinnable = @" + public const string InStaticPinnable = @" [ContiguousCollectionMarshaller] [CustomMarshaller(typeof(TestCollection<>), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller<,>.In))] static unsafe class Marshaller where TUnmanagedElement : unmanaged @@ -358,7 +330,7 @@ public ref struct In } } "; - public const string InBuffer = @" + public const string InBuffer = @" [ContiguousCollectionMarshaller] [CustomMarshaller(typeof(TestCollection<>), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller<,>.In))] static unsafe class Marshaller where TUnmanagedElement : unmanaged @@ -373,7 +345,7 @@ public ref struct In } } "; - public const string Ref = @" + public const string Ref = @" [ContiguousCollectionMarshaller] [CustomMarshaller(typeof(TestCollection<>), MarshalMode.Default, typeof(Marshaller<,>.Ref))] static unsafe class Marshaller where TUnmanagedElement : unmanaged @@ -392,7 +364,7 @@ public ref struct Ref } } "; - public const string Out = @" + public const string Out = @" [ContiguousCollectionMarshaller] [CustomMarshaller(typeof(TestCollection<>), MarshalMode.ManagedToUnmanagedOut, typeof(Marshaller<,>.Out))] static unsafe class Marshaller where TUnmanagedElement : unmanaged @@ -420,7 +392,7 @@ public ref struct Out } } "; - public const string DefaultIn = @" + public const string DefaultIn = @" [ContiguousCollectionMarshaller] [CustomMarshaller(typeof(TestCollection<>), MarshalMode.Default, typeof(Marshaller<,>.In))] static unsafe class Marshaller where TUnmanagedElement : unmanaged @@ -434,7 +406,7 @@ public ref struct In } } "; - public const string DefaultOut = @" + public const string DefaultOut = @" [ContiguousCollectionMarshaller] [CustomMarshaller(typeof(TestCollection<>), MarshalMode.Default, typeof(Marshaller<,>.Out))] static unsafe class Marshaller where TUnmanagedElement : unmanaged @@ -448,97 +420,96 @@ public ref struct Out } } "; - public static string ByValue() => ByValue(typeof(T).ToString()); - public static string ByValue(string elementType) => BasicParameterByValue($"TestCollection<{elementType}>", DisableRuntimeMarshalling) - + TestCollection() - + In; - - public static string ByValueWithPinning() => ByValueWithPinning(typeof(T).ToString()); - public static string ByValueWithPinning(string elementType) => BasicParameterByValue($"TestCollection<{elementType}>", DisableRuntimeMarshalling) - + TestCollection() - + InPinnable; - - public static string ByValueWithStaticPinning() => ByValueWithStaticPinning(typeof(T).ToString()); - public static string ByValueWithStaticPinning(string elementType) => BasicParameterByValue($"TestCollection<{elementType}>", DisableRuntimeMarshalling) - + TestCollection() - + InStaticPinnable; - - public static string ByValueCallerAllocatedBuffer() => ByValueCallerAllocatedBuffer(typeof(T).ToString()); - public static string ByValueCallerAllocatedBuffer(string elementType) => BasicParameterByValue($"TestCollection<{elementType}>", DisableRuntimeMarshalling) - + TestCollection() - + InBuffer; - - public static string DefaultMarshallerParametersAndModifiers() => DefaultMarshallerParametersAndModifiers(typeof(T).ToString()); - public static string DefaultMarshallerParametersAndModifiers(string elementType) => MarshalUsingCollectionCountInfoParametersAndModifiers($"TestCollection<{elementType}>") - + TestCollection() - + Ref; - - public static string CustomMarshallerParametersAndModifiers() => CustomMarshallerParametersAndModifiers(typeof(T).ToString()); - public static string CustomMarshallerParametersAndModifiers(string elementType) => MarshalUsingCollectionParametersAndModifiers($"TestCollection<{elementType}>", $"Marshaller<,>") - + TestCollection(defineNativeMarshalling: false) - + Ref; - - public static string CustomMarshallerReturnValueLength() => CustomMarshallerReturnValueLength(typeof(T).ToString()); - public static string CustomMarshallerReturnValueLength(string elementType) => MarshalUsingCollectionReturnValueLength($"TestCollection<{elementType}>", $"Marshaller<,>") - + TestCollection(defineNativeMarshalling: false) - + Ref; - - public static string NativeToManagedOnlyOutParameter() => NativeToManagedOnlyOutParameter(typeof(T).ToString()); - public static string NativeToManagedOnlyOutParameter(string elementType) => CollectionOutParameter($"TestCollection<{elementType}>") - + TestCollection() - + Out; - - public static string NativeToManagedFinallyOnlyOutParameter() => NativeToManagedFinallyOnlyOutParameter(typeof(T).ToString()); - public static string NativeToManagedFinallyOnlyOutParameter(string elementType) => CollectionOutParameter($"TestCollection<{elementType}>") - + TestCollection() - + OutGuaranteed; - - public static string NativeToManagedOnlyReturnValue() => NativeToManagedOnlyReturnValue(typeof(T).ToString()); - public static string NativeToManagedOnlyReturnValue(string elementType) => CollectionReturnType($"TestCollection<{elementType}>") - + TestCollection() - + Out; - - public static string NativeToManagedFinallyOnlyReturnValue() => NativeToManagedFinallyOnlyReturnValue(typeof(T).ToString()); - public static string NativeToManagedFinallyOnlyReturnValue(string elementType) => CollectionReturnType($"TestCollection<{elementType}>") - + TestCollection() - + OutGuaranteed; - - public static string NonBlittableElementParametersAndModifiers => DefaultMarshallerParametersAndModifiers("Element") - + NonBlittableElement - + ElementMarshaller; - - public static string NonBlittableElementByValue => ByValue("Element") - + NonBlittableElement - + ElementIn; - - public static string NonBlittableElementNativeToManagedOnlyOutParameter => NativeToManagedOnlyOutParameter("Element") - + NonBlittableElement - + ElementOut; - - public static string NonBlittableElementNativeToManagedFinallyOnlyOutParameter => NativeToManagedOnlyOutParameter("Element") - + NonBlittableElement - + ElementOut; - public static string NonBlittableElementNativeToManagedOnlyReturnValue => NativeToManagedOnlyOutParameter("Element") - + NonBlittableElement - + ElementOut; - - public static string NonBlittableElementNativeToManagedFinallyOnlyReturnValue => NativeToManagedOnlyOutParameter("Element") - + NonBlittableElement - + ElementOut; - - public static string DefaultModeByValueInParameter => BasicParameterByValue($"TestCollection", DisableRuntimeMarshalling) - + TestCollection() - + DefaultIn; - - public static string DefaultModeReturnValue => CollectionOutParameter($"TestCollection") - + TestCollection() - + DefaultOut; - - public static string CustomElementMarshalling => CodeSnippets.CustomElementMarshalling("TestCollection", "CustomIntMarshaller") - + TestCollection() - + Ref - + CustomIntMarshaller; - } + public static string ByValue() => ByValue(typeof(T).ToString()); + public static string ByValue(string elementType) => TSignatureTestProvider.BasicParameterByValue($"TestCollection<{elementType}>", DisableRuntimeMarshalling) + + TestCollection() + + In; + + public static string ByValueWithPinning() => ByValueWithPinning(typeof(T).ToString()); + public static string ByValueWithPinning(string elementType) => TSignatureTestProvider.BasicParameterByValue($"TestCollection<{elementType}>", DisableRuntimeMarshalling) + + TestCollection() + + InPinnable; + + public static string ByValueWithStaticPinning() => ByValueWithStaticPinning(typeof(T).ToString()); + public static string ByValueWithStaticPinning(string elementType) => TSignatureTestProvider.BasicParameterByValue($"TestCollection<{elementType}>", DisableRuntimeMarshalling) + + TestCollection() + + InStaticPinnable; + + public static string ByValueCallerAllocatedBuffer() => ByValueCallerAllocatedBuffer(typeof(T).ToString()); + public static string ByValueCallerAllocatedBuffer(string elementType) => TSignatureTestProvider.BasicParameterByValue($"TestCollection<{elementType}>", DisableRuntimeMarshalling) + + TestCollection() + + InBuffer; + + public static string DefaultMarshallerParametersAndModifiers() => DefaultMarshallerParametersAndModifiers(typeof(T).ToString()); + public static string DefaultMarshallerParametersAndModifiers(string elementType) => TSignatureTestProvider.MarshalUsingCollectionCountInfoParametersAndModifiers($"TestCollection<{elementType}>") + + TestCollection() + + Ref; + + public static string CustomMarshallerParametersAndModifiers() => CustomMarshallerParametersAndModifiers(typeof(T).ToString()); + public static string CustomMarshallerParametersAndModifiers(string elementType) => TSignatureTestProvider.MarshalUsingCollectionParametersAndModifiers($"TestCollection<{elementType}>", $"Marshaller<,>") + + TestCollection(defineNativeMarshalling: false) + + Ref; + + public static string CustomMarshallerReturnValueLength() => CustomMarshallerReturnValueLength(typeof(T).ToString()); + public static string CustomMarshallerReturnValueLength(string elementType) => TSignatureTestProvider.MarshalUsingCollectionReturnValueLength($"TestCollection<{elementType}>", $"Marshaller<,>") + + TestCollection(defineNativeMarshalling: false) + + Ref; + + public static string NativeToManagedOnlyOutParameter() => NativeToManagedOnlyOutParameter(typeof(T).ToString()); + public static string NativeToManagedOnlyOutParameter(string elementType) => CollectionOutParameter($"TestCollection<{elementType}>") + + TestCollection() + + Out; + + public static string NativeToManagedFinallyOnlyOutParameter() => NativeToManagedFinallyOnlyOutParameter(typeof(T).ToString()); + public static string NativeToManagedFinallyOnlyOutParameter(string elementType) => CollectionOutParameter($"TestCollection<{elementType}>") + + TestCollection() + + OutGuaranteed; + + public static string NativeToManagedOnlyReturnValue() => NativeToManagedOnlyReturnValue(typeof(T).ToString()); + public static string NativeToManagedOnlyReturnValue(string elementType) => CollectionReturnType($"TestCollection<{elementType}>") + + TestCollection() + + Out; + + public static string NativeToManagedFinallyOnlyReturnValue() => NativeToManagedFinallyOnlyReturnValue(typeof(T).ToString()); + public static string NativeToManagedFinallyOnlyReturnValue(string elementType) => CollectionReturnType($"TestCollection<{elementType}>") + + TestCollection() + + OutGuaranteed; + + public static string NonBlittableElementParametersAndModifiers => DefaultMarshallerParametersAndModifiers("Element") + + NonBlittableElement + + ElementMarshaller; + + public static string NonBlittableElementByValue => ByValue("Element") + + NonBlittableElement + + ElementIn; + + public static string NonBlittableElementNativeToManagedOnlyOutParameter => NativeToManagedOnlyOutParameter("Element") + + NonBlittableElement + + ElementOut; + + public static string NonBlittableElementNativeToManagedFinallyOnlyOutParameter => NativeToManagedOnlyOutParameter("Element") + + NonBlittableElement + + ElementOut; + public static string NonBlittableElementNativeToManagedOnlyReturnValue => NativeToManagedOnlyOutParameter("Element") + + NonBlittableElement + + ElementOut; + + public static string NonBlittableElementNativeToManagedFinallyOnlyReturnValue => NativeToManagedOnlyOutParameter("Element") + + NonBlittableElement + + ElementOut; + + public static string DefaultModeByValueInParameter => TSignatureTestProvider.BasicParameterByValue($"TestCollection", DisableRuntimeMarshalling) + + TestCollection() + + DefaultIn; + + public static string DefaultModeReturnValue => CollectionOutParameter($"TestCollection") + + TestCollection() + + DefaultOut; + + public static string CustomElementMarshalling => TSignatureTestProvider.CustomElementMarshalling("TestCollection", "CustomIntMarshaller") + + TestCollection() + + Ref + + CustomIntMarshaller; } } } diff --git a/src/libraries/System.Runtime.InteropServices/tests/Common/CustomStructMarshallingCodeSnippets.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/CustomStructMarshallingCodeSnippets.cs new file mode 100644 index 0000000000000..49adea842278b --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/Common/CustomStructMarshallingCodeSnippets.cs @@ -0,0 +1,522 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.Interop.UnitTests +{ + public static class CustomStructMarshallingCodeSnippets + where TSignatureTestProvider : ICustomMarshallingSignatureTestProvider + { + private static readonly string UsingSystemRuntimeInteropServicesMarshalling = "using System.Runtime.InteropServices.Marshalling;"; + + public static string NonBlittableUserDefinedType(bool defineNativeMarshalling = true) => $@" +{(defineNativeMarshalling ? "[NativeMarshalling(typeof(Marshaller))]" : string.Empty)} +public struct S +{{ +#pragma warning disable CS0649 // Field is never assigned to, and will always have its default value + public bool b; +#pragma warning restore CS0649 +}} +"; + private static string NonStatic = @" +[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller))] +public class Marshaller +{ + public struct Native { } + + public static Native ConvertToUnmanaged(S s) => default; +} +"; + public static string NonStaticMarshallerEntryPoint => TSignatureTestProvider.BasicParameterByValue("S") + + NonBlittableUserDefinedType() + + NonStatic; + + private static string Struct = @" +[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller))] +public struct Marshaller +{ + public struct Native { } + + public void FromManaged(S s) {} + public Native ToUnmanaged() => default; +} +"; + public static string StructMarshallerEntryPoint => TSignatureTestProvider.BasicParameterByValue("S") + + NonBlittableUserDefinedType() + + Struct; + + + public static class Stateless + { + private static string In = @" +[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller))] +public static class Marshaller +{ + public struct Native { } + + public static Native ConvertToUnmanaged(S s) => default; +} +"; + private static string InBuffer = @" +[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller))] +public static class Marshaller +{ + public struct Native { } + + public const int BufferSize = 0x100; + public static Native ConvertToUnmanaged(S s, System.Span buffer) => default; +} +"; + + public static string InPinnable = @" +[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller))] +public static unsafe class Marshaller +{ + public static byte* ConvertToUnmanaged(S s) => default; + public static ref byte GetPinnableReference(S s) => throw null; +} +"; + private static string Out = @" +[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedOut, typeof(Marshaller))] +public static class Marshaller +{ + public struct Native { } + + public static S ConvertToManaged(Native n) => default; +} +"; + private static string OutGuaranteed = @" +[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedOut, typeof(Marshaller))] +public static class Marshaller +{ + public struct Native { } + + public static S ConvertToManagedFinally(Native n) => default; +} +"; + public static string Ref = @" +[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedRef, typeof(Marshaller))] +public static class Marshaller +{ + public struct Native { } + + public static Native ConvertToUnmanaged(S s) => default; + public static S ConvertToManaged(Native n) => default; +} +"; + public static string Default = @" +[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(Marshaller))] +public static class Marshaller +{ + public struct Native { } + + public static Native ConvertToUnmanaged(S s) => default; + public static S ConvertToManaged(Native n) => default; +} +"; + public static string InOutBuffer = @" +[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller))] +[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedOut, typeof(Marshaller))] +public static class Marshaller +{ + public struct Native { } + + public const int BufferSize = 0x100; + public static Native ConvertToUnmanaged(S s, System.Span buffer) => default; + public static S ConvertToManaged(Native n) => default; +} +"; + public static string DefaultOptionalBuffer = @" +[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(Marshaller))] +public static class Marshaller +{ + public struct Native { } + + public const int BufferSize = 0x100; + public static Native ConvertToUnmanaged(S s) => default; + public static Native ConvertToUnmanaged(S s, System.Span buffer) => default; + public static S ConvertToManaged(Native n) => default; +} +"; + private static string DefaultIn = @" +[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(Marshaller))] +public static class Marshaller +{ + public struct Native { } + + public static Native ConvertToUnmanaged(S s) => default; +} +"; + private static string DefaultOut = @" +[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedOut, typeof(Marshaller))] +public static class Marshaller +{ + public struct Native { } + + public static S ConvertToManaged(Native n) => default; +} +"; + public static string ManagedToNativeOnlyOutParameter => TSignatureTestProvider.BasicParameterWithByRefModifier("out", "S") + + NonBlittableUserDefinedType() + + In; + + public static string NativeToManagedOnlyOutParameter => TSignatureTestProvider.BasicParameterWithByRefModifier("out", "S") + + NonBlittableUserDefinedType() + + Out; + + public static string NativeToManagedFinallyOnlyOutParameter => TSignatureTestProvider.BasicParameterWithByRefModifier("out", "S") + + NonBlittableUserDefinedType() + + OutGuaranteed; + + public static string ManagedToNativeOnlyReturnValue => TSignatureTestProvider.BasicReturnType("S") + + NonBlittableUserDefinedType() + + In; + + public static string NativeToManagedOnlyReturnValue => TSignatureTestProvider.BasicReturnType("S") + + NonBlittableUserDefinedType() + + Out; + + public static string NativeToManagedFinallyOnlyReturnValue => TSignatureTestProvider.BasicReturnType("S") + + NonBlittableUserDefinedType() + + Out; + + public static string NativeToManagedOnlyInParameter => TSignatureTestProvider.BasicParameterWithByRefModifier("in", "S") + + NonBlittableUserDefinedType() + + Out; + + public static string ParametersAndModifiers = TSignatureTestProvider.BasicParametersAndModifiers("S", UsingSystemRuntimeInteropServicesMarshalling) + + NonBlittableUserDefinedType(defineNativeMarshalling: true) + + Default; + + public static string MarshalUsingParametersAndModifiers = TSignatureTestProvider.MarshalUsingParametersAndModifiers("S", "Marshaller") + + NonBlittableUserDefinedType(defineNativeMarshalling: false) + + Default; + + public static string ByValueInParameter => TSignatureTestProvider.BasicParameterByValue("S") + + NonBlittableUserDefinedType() + + In; + + public static string StackallocByValueInParameter => TSignatureTestProvider.BasicParameterByValue("S") + + NonBlittableUserDefinedType() + + InBuffer; + + public static string PinByValueInParameter => TSignatureTestProvider.BasicParameterByValue("S") + + NonBlittableUserDefinedType() + + InPinnable; + + public static string StackallocParametersAndModifiersNoRef = TSignatureTestProvider.BasicParametersAndModifiersNoRef("S") + + NonBlittableUserDefinedType() + + InOutBuffer; + + public static string RefParameter = TSignatureTestProvider.BasicParameterWithByRefModifier("ref", "S") + + NonBlittableUserDefinedType() + + Ref; + + public static string StackallocOnlyRefParameter = TSignatureTestProvider.BasicParameterWithByRefModifier("ref", "S") + + NonBlittableUserDefinedType() + + InOutBuffer; + + public static string OptionalStackallocParametersAndModifiers = TSignatureTestProvider.BasicParametersAndModifiers("S", UsingSystemRuntimeInteropServicesMarshalling) + + NonBlittableUserDefinedType() + + DefaultOptionalBuffer; + + public static string DefaultModeByValueInParameter => TSignatureTestProvider.BasicParameterByValue("S") + + NonBlittableUserDefinedType() + + DefaultIn; + + public static string DefaultModeReturnValue => TSignatureTestProvider.BasicReturnType("S") + + NonBlittableUserDefinedType() + + DefaultOut; + } + + public static class Stateful + { + private static string In = @" +[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(M))] +public static class Marshaller +{ + public struct Native { } + + public struct M + { + public void FromManaged(S s) {} + public Native ToUnmanaged() => default; + } +} +"; + + public static string InStatelessPinnable = @" +[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(M))] +public static class Marshaller +{ + public unsafe struct M + { + public void FromManaged(S s) {} + public byte* ToUnmanaged() => default; + + public static ref byte GetPinnableReference(S s) => throw null; + } +} +"; + + public static string InPinnable = @" +[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(M))] +public static class Marshaller +{ + public unsafe struct M + { + public void FromManaged(S s) {} + public byte* ToUnmanaged() => default; + + public ref byte GetPinnableReference() => throw null; + } +} +"; + + private static string InBuffer = @" +[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(M))] +public static class Marshaller +{ + public struct Native { } + + public struct M + { + public const int BufferSize = 0x100; + public void FromManaged(S s, System.Span buffer) {} + public Native ToUnmanaged() => default; + } +} +"; + private static string Out = @" +[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedOut, typeof(M))] +public static class Marshaller +{ + public struct Native { } + + public struct M + { + public void FromUnmanaged(Native n) {} + public S ToManaged() => default; + } +} +"; + private static string OutGuaranteed = @" +[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedOut, typeof(M))] +public static class Marshaller +{ + public struct Native { } + + public struct M + { + public void FromUnmanaged(Native n) {} + public S ToManagedFinally() => default; + } +} +"; + public static string Ref = @" +[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedRef, typeof(M))] +public static class Marshaller +{ + public struct Native { } + + public struct M + { + public void FromManaged(S s) {} + public Native ToUnmanaged() => default; + public void FromUnmanaged(Native n) {} + public S ToManaged() => default; + } +} +"; + public static string Default = @" +[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(M))] +public static class Marshaller +{ + public struct Native { } + + public struct M + { + public void FromManaged(S s) {} + public Native ToUnmanaged() => default; + public void FromUnmanaged(Native n) {} + public S ToManaged() => default; + } +} +"; + public static string DefaultWithFree = @" +[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(M))] +public static class Marshaller +{ + public struct Native { } + + public struct M + { + public void FromManaged(S s) {} + public Native ToUnmanaged() => default; + public void FromUnmanaged(Native n) {} + public S ToManaged() => default; + public void Free() {} + } +} +"; + public static string DefaultWithOnInvoked = @" +[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(M))] +public static class Marshaller +{ + public struct Native { } + + public struct M + { + public void FromManaged(S s) {} + public Native ToUnmanaged() => default; + public void FromUnmanaged(Native n) {} + public S ToManaged() => default; + public void OnInvoked() {} + } +} +"; + public static string InOutBuffer = @" +[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedIn, typeof(M))] +[CustomMarshaller(typeof(S), MarshalMode.ManagedToUnmanagedOut, typeof(M))] +public static class Marshaller +{ + public struct Native { } + + public struct M + { + public const int BufferSize = 0x100; + public void FromManaged(S s, System.Span buffer) {} + public Native ToUnmanaged() => default; + public void FromUnmanaged(Native n) {} + public S ToManaged() => default; + } +} +"; + public static string DefaultOptionalBuffer = @" +[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(M))] +public static class Marshaller +{ + public struct Native { } + + public struct M + { + public const int BufferSize = 0x100; + public void FromManaged(S s) {} + public void FromManaged(S s, System.Span buffer) {} + public Native ToUnmanaged() => default; + public void FromUnmanaged(Native n) {} + public S ToManaged() => default; + } +} +"; + private static string DefaultIn = @" +[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(M))] +public static class Marshaller +{ + public struct Native { } + + public struct M + { + public void FromManaged(S s) {} + public Native ToUnmanaged() => default; + } +} +"; + private static string DefaultOut = @" +[CustomMarshaller(typeof(S), MarshalMode.Default, typeof(M))] +public static class Marshaller +{ + public struct Native { } + + public struct M + { + public void FromUnmanaged(Native n) {} + public S ToManaged() => default; + } +} +"; + public static string ManagedToNativeOnlyOutParameter => TSignatureTestProvider.BasicParameterWithByRefModifier("out", "S") + + NonBlittableUserDefinedType() + + In; + + public static string NativeToManagedOnlyOutParameter => TSignatureTestProvider.BasicParameterWithByRefModifier("out", "S") + + NonBlittableUserDefinedType() + + Out; + + public static string NativeToManagedFinallyOnlyOutParameter => TSignatureTestProvider.BasicParameterWithByRefModifier("out", "S") + + NonBlittableUserDefinedType() + + OutGuaranteed; + + public static string ManagedToNativeOnlyReturnValue => TSignatureTestProvider.BasicReturnType("S") + + NonBlittableUserDefinedType() + + In; + + public static string NativeToManagedOnlyReturnValue => TSignatureTestProvider.BasicReturnType("S") + + NonBlittableUserDefinedType() + + Out; + + public static string NativeToManagedFinallyOnlyReturnValue => TSignatureTestProvider.BasicReturnType("S") + + NonBlittableUserDefinedType() + + Out; + + public static string NativeToManagedOnlyInParameter => TSignatureTestProvider.BasicParameterWithByRefModifier("in", "S") + + NonBlittableUserDefinedType() + + Out; + + public static string ParametersAndModifiers = TSignatureTestProvider.BasicParametersAndModifiers("S", UsingSystemRuntimeInteropServicesMarshalling) + + NonBlittableUserDefinedType(defineNativeMarshalling: true) + + Default; + + public static string ParametersAndModifiersWithFree = TSignatureTestProvider.BasicParametersAndModifiers("S", UsingSystemRuntimeInteropServicesMarshalling) + + NonBlittableUserDefinedType(defineNativeMarshalling: true) + + DefaultWithFree; + + public static string ParametersAndModifiersWithOnInvoked = TSignatureTestProvider.BasicParametersAndModifiers("S", UsingSystemRuntimeInteropServicesMarshalling) + + NonBlittableUserDefinedType(defineNativeMarshalling: true) + + DefaultWithOnInvoked; + + public static string MarshalUsingParametersAndModifiers = TSignatureTestProvider.MarshalUsingParametersAndModifiers("S", "Marshaller") + + NonBlittableUserDefinedType(defineNativeMarshalling: false) + + Default; + + public static string ByValueInParameter => TSignatureTestProvider.BasicParameterByValue("S") + + NonBlittableUserDefinedType() + + In; + + public static string StackallocByValueInParameter => TSignatureTestProvider.BasicParameterByValue("S") + + NonBlittableUserDefinedType() + + InBuffer; + + public static string PinByValueInParameter => TSignatureTestProvider.BasicParameterByValue("S") + + NonBlittableUserDefinedType() + + InStatelessPinnable; + + public static string MarshallerPinByValueInParameter => TSignatureTestProvider.BasicParameterByValue("S") + + NonBlittableUserDefinedType() + + InPinnable; + + public static string StackallocParametersAndModifiersNoRef = TSignatureTestProvider.BasicParametersAndModifiersNoRef("S") + + NonBlittableUserDefinedType() + + InOutBuffer; + + public static string RefParameter = TSignatureTestProvider.BasicParameterWithByRefModifier("ref", "S") + + NonBlittableUserDefinedType() + + Ref; + + public static string StackallocOnlyRefParameter = TSignatureTestProvider.BasicParameterWithByRefModifier("ref", "S") + + NonBlittableUserDefinedType() + + InOutBuffer; + + public static string OptionalStackallocParametersAndModifiers = TSignatureTestProvider.BasicParametersAndModifiers("S", UsingSystemRuntimeInteropServicesMarshalling) + + NonBlittableUserDefinedType() + + DefaultOptionalBuffer; + + public static string DefaultModeByValueInParameter => TSignatureTestProvider.BasicParameterByValue("S") + + NonBlittableUserDefinedType() + + DefaultIn; + + public static string DefaultModeReturnValue => TSignatureTestProvider.BasicReturnType("S") + + NonBlittableUserDefinedType() + + DefaultOut; + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/Common/ICustomMarshallingSignatureTestProvider.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ICustomMarshallingSignatureTestProvider.cs new file mode 100644 index 0000000000000..5dc04645ebc8f --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/Common/ICustomMarshallingSignatureTestProvider.cs @@ -0,0 +1,32 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.Interop.UnitTests +{ + public interface ICustomMarshallingSignatureTestProvider + { + public abstract static string BasicParameterByValue(string type, string preDeclaration = ""); + + public abstract static string BasicParameterWithByRefModifier(string byRefModifier, string type, string preDeclaration = ""); + + public abstract static string BasicReturnType(string type, string preDeclaration = ""); + + public abstract static string BasicParametersAndModifiers(string typeName, string preDeclaration = ""); + + public abstract static string BasicParametersAndModifiersNoRef(string typeName, string preDeclaration = ""); + + public abstract static string MarshalUsingParametersAndModifiers(string type, string marshallerType, string preDeclaration = ""); + + public abstract static string MarshalUsingCollectionCountInfoParametersAndModifiers(string collectionType); + + public abstract static string MarshalUsingCollectionParametersAndModifiers(string type, string marshallerType); + + public abstract static string MarshalUsingCollectionOutConstantLength(string type, string predeclaration); + + public abstract static string MarshalUsingCollectionReturnConstantLength(string type, string predeclaration); + + public abstract static string MarshalUsingCollectionReturnValueLength(string type, string marshallerType); + + public abstract static string CustomElementMarshalling(string type, string marshallerType, string preDeclaration = ""); + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CodeSnippets.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CodeSnippets.cs index 13bad4ed49554..6b0c7ecb74fcd 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CodeSnippets.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CodeSnippets.cs @@ -5,7 +5,7 @@ namespace Microsoft.Interop.UnitTests { - internal static partial class CodeSnippets + internal partial class CodeSnippets : ICustomMarshallingSignatureTestProvider { /// /// Partially define attribute for pre-.NET 7.0 @@ -933,8 +933,37 @@ partial class Test public static partial int[] Method(); }} "; + public static string CustomElementMarshallingDuplicateElementIndirectionDepth => $@" +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; +{DisableRuntimeMarshalling} +partial class Test +{{ + [LibraryImport(""DoesNotExist"")] + public static partial void Method( + [MarshalUsing(typeof(CustomIntMarshaller), ElementIndirectionDepth = 1)] [MarshalUsing(typeof(CustomIntMarshaller), ElementIndirectionDepth = 1)] TestCollection p); +}} +" + + CustomCollectionMarshallingCodeSnippets.TestCollection() + + CustomCollectionMarshallingCodeSnippets.Stateless.In + + CustomCollectionMarshallingCodeSnippets.CustomIntMarshaller; + + public static string CustomElementMarshallingUnusedElementIndirectionDepth => $@" +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; +{DisableRuntimeMarshalling} +partial class Test +{{ + [LibraryImport(""DoesNotExist"")] + public static partial void Method( + [MarshalUsing(typeof(CustomIntMarshaller), ElementIndirectionDepth = 2)] TestCollection p); +}} +" + + CustomCollectionMarshallingCodeSnippets.TestCollection() + + CustomCollectionMarshallingCodeSnippets.Stateless.In + + CustomCollectionMarshallingCodeSnippets.CustomIntMarshaller; - public static string RecursiveCountElementNameOnReturnValue => $@" + public static string RecursiveCountElementNameOnReturnValue => $@" using System.Runtime.InteropServices; using System.Runtime.InteropServices.Marshalling; {DisableRuntimeMarshalling} diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CompileFails.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CompileFails.cs index 509856220e9f9..c8ff8cd4642f9 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CompileFails.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CompileFails.cs @@ -101,15 +101,15 @@ public static IEnumerable CodeSnippetsToCompile() yield return new object[] { ID(), CodeSnippets.MarshalUsingArrayParameterWithSizeParam(isByRef: false), 2, 0 }; // Custom type marshalling with invalid members - yield return new object[] { ID(), CodeSnippets.CustomStructMarshalling.NonStaticMarshallerEntryPoint, 2, 0 }; - yield return new object[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.ManagedToNativeOnlyOutParameter, 1, 0 }; - yield return new object[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.ManagedToNativeOnlyReturnValue, 1, 0 }; - yield return new object[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.NativeToManagedOnlyInParameter, 1, 0 }; - yield return new object[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.StackallocOnlyRefParameter, 1, 0 }; - yield return new object[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.ManagedToNativeOnlyOutParameter, 1, 0 }; - yield return new object[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.ManagedToNativeOnlyReturnValue, 1, 0 }; - yield return new object[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.NativeToManagedOnlyInParameter, 1, 0 }; - yield return new object[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.StackallocOnlyRefParameter, 1, 0 }; + yield return new object[] { ID(), CustomStructMarshallingCodeSnippets.NonStaticMarshallerEntryPoint, 2, 0 }; + yield return new object[] { ID(), CustomStructMarshallingCodeSnippets.Stateless.ManagedToNativeOnlyOutParameter, 1, 0 }; + yield return new object[] { ID(), CustomStructMarshallingCodeSnippets.Stateless.ManagedToNativeOnlyReturnValue, 1, 0 }; + yield return new object[] { ID(), CustomStructMarshallingCodeSnippets.Stateless.NativeToManagedOnlyInParameter, 1, 0 }; + yield return new object[] { ID(), CustomStructMarshallingCodeSnippets.Stateless.StackallocOnlyRefParameter, 1, 0 }; + yield return new object[] { ID(), CustomStructMarshallingCodeSnippets.Stateful.ManagedToNativeOnlyOutParameter, 1, 0 }; + yield return new object[] { ID(), CustomStructMarshallingCodeSnippets.Stateful.ManagedToNativeOnlyReturnValue, 1, 0 }; + yield return new object[] { ID(), CustomStructMarshallingCodeSnippets.Stateful.NativeToManagedOnlyInParameter, 1, 0 }; + yield return new object[] { ID(), CustomStructMarshallingCodeSnippets.Stateful.StackallocOnlyRefParameter, 1, 0 }; // Abstract SafeHandle type by reference yield return new object[] { ID(), CodeSnippets.BasicParameterWithByRefModifier("ref", "System.Runtime.InteropServices.SafeHandle"), 1, 0 }; @@ -121,11 +121,11 @@ public static IEnumerable CodeSnippetsToCompile() yield return new object[] { ID(), CodeSnippets.MarshalUsingCollectionWithNullElementName, 2, 0 }; // Generic collection marshaller has different arity than collection. - yield return new object[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.GenericCollectionMarshallingArityMismatch, 2, 0 }; + yield return new object[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.GenericCollectionMarshallingArityMismatch, 2, 0 }; yield return new object[] { ID(), CodeSnippets.MarshalAsAndMarshalUsingOnReturnValue, 2, 0 }; - yield return new object[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomElementMarshallingDuplicateElementIndirectionDepth, 2, 0 }; - yield return new object[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomElementMarshallingUnusedElementIndirectionDepth, 1, 0 }; + yield return new object[] { ID(), CodeSnippets.CustomElementMarshallingDuplicateElementIndirectionDepth, 2, 0 }; + yield return new object[] { ID(), CodeSnippets.CustomElementMarshallingUnusedElementIndirectionDepth, 1, 0 }; yield return new object[] { ID(), CodeSnippets.RecursiveCountElementNameOnReturnValue, 2, 0 }; yield return new object[] { ID(), CodeSnippets.RecursiveCountElementNameOnParameter, 2, 0 }; yield return new object[] { ID(), CodeSnippets.MutuallyRecursiveCountElementNameOnParameter, 4, 0 }; diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/Compiles.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/Compiles.cs index e1af5a13df3ab..92414ba4fd67e 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/Compiles.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/Compiles.cs @@ -127,11 +127,11 @@ public static IEnumerable CodeSnippetsToCompile() // [In, Out] attributes // By value non-blittable array yield return new[] { ID(), CodeSnippets.ByValueParameterWithModifier("S[]", "Out") - + CodeSnippets.CustomStructMarshalling.NonBlittableUserDefinedType() - + CodeSnippets.CustomStructMarshalling.Stateless.Default }; + + CustomStructMarshallingCodeSnippets.NonBlittableUserDefinedType() + + CustomStructMarshallingCodeSnippets.Stateless.Default }; yield return new[] { ID(), CodeSnippets.ByValueParameterWithModifier("S[]", "In, Out") - + CodeSnippets.CustomStructMarshalling.NonBlittableUserDefinedType() - + CodeSnippets.CustomStructMarshalling.Stateless.Default }; + + CustomStructMarshallingCodeSnippets.NonBlittableUserDefinedType() + + CustomStructMarshallingCodeSnippets.Stateless.Default }; // Enums yield return new[] { ID(), CodeSnippets.EnumParameters }; @@ -179,38 +179,38 @@ public static IEnumerable CodeSnippetsToCompile() yield return new[] { ID(), CodeSnippets.SafeHandleWithCustomDefaultConstructorAccessibility(privateCtor: true) }; // Custom type marshalling - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.StructMarshallerEntryPoint }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.ParametersAndModifiers }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.MarshalUsingParametersAndModifiers }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.NativeToManagedOnlyOutParameter }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.NativeToManagedFinallyOnlyOutParameter }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.NativeToManagedOnlyReturnValue }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.NativeToManagedFinallyOnlyReturnValue }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.ByValueInParameter }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.PinByValueInParameter }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.StackallocByValueInParameter }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.RefParameter }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.StackallocParametersAndModifiersNoRef }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.OptionalStackallocParametersAndModifiers }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.DefaultModeByValueInParameter }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateless.DefaultModeReturnValue }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.ParametersAndModifiers }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.ParametersAndModifiersWithFree }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.ParametersAndModifiersWithOnInvoked }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.MarshalUsingParametersAndModifiers }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.NativeToManagedOnlyOutParameter }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.NativeToManagedFinallyOnlyOutParameter }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.NativeToManagedOnlyReturnValue }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.NativeToManagedFinallyOnlyReturnValue }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.ByValueInParameter }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.StackallocByValueInParameter }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.PinByValueInParameter }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.MarshallerPinByValueInParameter }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.RefParameter }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.StackallocParametersAndModifiersNoRef }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.OptionalStackallocParametersAndModifiers }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.DefaultModeByValueInParameter }; - yield return new[] { ID(), CodeSnippets.CustomStructMarshalling.Stateful.DefaultModeReturnValue }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.StructMarshallerEntryPoint }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateless.ParametersAndModifiers }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateless.MarshalUsingParametersAndModifiers }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateless.NativeToManagedOnlyOutParameter }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateless.NativeToManagedFinallyOnlyOutParameter }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateless.NativeToManagedOnlyReturnValue }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateless.NativeToManagedFinallyOnlyReturnValue }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateless.ByValueInParameter }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateless.PinByValueInParameter }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateless.StackallocByValueInParameter }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateless.RefParameter }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateless.StackallocParametersAndModifiersNoRef }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateless.OptionalStackallocParametersAndModifiers }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateless.DefaultModeByValueInParameter }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateless.DefaultModeReturnValue }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateful.ParametersAndModifiers }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateful.ParametersAndModifiersWithFree }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateful.ParametersAndModifiersWithOnInvoked }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateful.MarshalUsingParametersAndModifiers }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateful.NativeToManagedOnlyOutParameter }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateful.NativeToManagedFinallyOnlyOutParameter }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateful.NativeToManagedOnlyReturnValue }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateful.NativeToManagedFinallyOnlyReturnValue }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateful.ByValueInParameter }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateful.StackallocByValueInParameter }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateful.PinByValueInParameter }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateful.MarshallerPinByValueInParameter }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateful.RefParameter }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateful.StackallocParametersAndModifiersNoRef }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateful.OptionalStackallocParametersAndModifiers }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateful.DefaultModeByValueInParameter }; + yield return new[] { ID(), CustomStructMarshallingCodeSnippets.Stateful.DefaultModeReturnValue }; // Escaped C# keyword identifiers yield return new[] { ID(), CodeSnippets.ByValueParameterWithName("Method", "@event") }; @@ -236,90 +236,90 @@ public static IEnumerable CodeSnippetsToCompile() public static IEnumerable CustomCollections() { // Custom collection marshalling - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueCallerAllocatedBuffer() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueCallerAllocatedBuffer() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueCallerAllocatedBuffer() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueCallerAllocatedBuffer() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueCallerAllocatedBuffer() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueCallerAllocatedBuffer() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueCallerAllocatedBuffer() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueCallerAllocatedBuffer() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueCallerAllocatedBuffer() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueCallerAllocatedBuffer() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueCallerAllocatedBuffer() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueCallerAllocatedBuffer() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueCallerAllocatedBuffer() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueCallerAllocatedBuffer() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueCallerAllocatedBuffer() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueCallerAllocatedBuffer() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueCallerAllocatedBuffer() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueCallerAllocatedBuffer() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueCallerAllocatedBuffer() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueCallerAllocatedBuffer() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueCallerAllocatedBuffer() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueCallerAllocatedBuffer() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueCallerAllocatedBuffer() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueCallerAllocatedBuffer() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithStaticPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithStaticPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithStaticPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithStaticPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithStaticPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithStaticPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithStaticPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithStaticPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithStaticPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithStaticPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithStaticPinning() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.ByValueWithStaticPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueCallerAllocatedBuffer() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithStaticPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithStaticPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithStaticPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithStaticPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithStaticPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithStaticPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithStaticPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithStaticPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithStaticPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithStaticPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithStaticPinning() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.ByValueWithStaticPinning() }; yield return new[] { ID(), CodeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers() }; yield return new[] { ID(), CodeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers() }; yield return new[] { ID(), CodeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers() }; @@ -332,83 +332,83 @@ public static IEnumerable CustomCollections() yield return new[] { ID(), CodeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers() }; yield return new[] { ID(), CodeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers() }; yield return new[] { ID(), CodeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomMarshallerReturnValueLength() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.NativeToManagedOnlyOutParameter() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.NativeToManagedFinallyOnlyOutParameter() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.NativeToManagedOnlyReturnValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.NativeToManagedFinallyOnlyReturnValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.NestedMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.NonBlittableElementByValue }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.NonBlittableElementParametersAndModifiers }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.NonBlittableElementNativeToManagedOnlyOutParameter }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.NonBlittableElementNativeToManagedFinallyOnlyOutParameter }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.NonBlittableElementNativeToManagedOnlyReturnValue }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.NonBlittableElementNativeToManagedFinallyOnlyReturnValue }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.DefaultModeByValueInParameter }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.DefaultModeReturnValue }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateless.CustomElementMarshalling }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.DefaultMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.CustomMarshallerParametersAndModifiers() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.CustomMarshallerReturnValueLength() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.NativeToManagedOnlyOutParameter() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.NativeToManagedFinallyOnlyOutParameter() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.NativeToManagedOnlyReturnValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.NativeToManagedFinallyOnlyReturnValue() }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.NonBlittableElementByValue }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.NonBlittableElementParametersAndModifiers }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.NonBlittableElementNativeToManagedOnlyOutParameter }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.NonBlittableElementNativeToManagedFinallyOnlyOutParameter }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.NonBlittableElementNativeToManagedOnlyReturnValue }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.NonBlittableElementNativeToManagedFinallyOnlyReturnValue }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.DefaultModeByValueInParameter }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.DefaultModeReturnValue }; - yield return new[] { ID(), CodeSnippets.CustomCollectionMarshalling.Stateful.CustomElementMarshalling }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.CustomMarshallerReturnValueLength() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.NativeToManagedOnlyOutParameter() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.NativeToManagedFinallyOnlyOutParameter() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.NativeToManagedOnlyReturnValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.NativeToManagedFinallyOnlyReturnValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.NestedMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.NonBlittableElementByValue }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.NonBlittableElementParametersAndModifiers }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.NonBlittableElementNativeToManagedOnlyOutParameter }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.NonBlittableElementNativeToManagedFinallyOnlyOutParameter }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.NonBlittableElementNativeToManagedOnlyReturnValue }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.NonBlittableElementNativeToManagedFinallyOnlyReturnValue }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.DefaultModeByValueInParameter }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.DefaultModeReturnValue }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateless.CustomElementMarshalling }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.DefaultMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.CustomMarshallerParametersAndModifiers() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.CustomMarshallerReturnValueLength() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.NativeToManagedOnlyOutParameter() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.NativeToManagedFinallyOnlyOutParameter() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.NativeToManagedOnlyReturnValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.NativeToManagedFinallyOnlyReturnValue() }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.NonBlittableElementByValue }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.NonBlittableElementParametersAndModifiers }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.NonBlittableElementNativeToManagedOnlyOutParameter }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.NonBlittableElementNativeToManagedFinallyOnlyOutParameter }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.NonBlittableElementNativeToManagedOnlyReturnValue }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.NonBlittableElementNativeToManagedFinallyOnlyReturnValue }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.DefaultModeByValueInParameter }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.DefaultModeReturnValue }; + yield return new[] { ID(), CustomCollectionMarshallingCodeSnippets.Stateful.CustomElementMarshalling }; yield return new[] { ID(), CodeSnippets.CollectionsOfCollectionsStress }; } diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/LibraryImportGenerator.Unit.Tests.csproj b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/LibraryImportGenerator.Unit.Tests.csproj index b3f1ca2be2d98..4158ee4011344 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/LibraryImportGenerator.Unit.Tests.csproj +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/LibraryImportGenerator.Unit.Tests.csproj @@ -11,10 +11,12 @@ Link="Common\SourceGenerators\LiveReferencePack.cs" /> - - + + + From 7182f4bfff0bebbe74dcf8db85a9bacafd95c945 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Thu, 25 Aug 2022 11:17:41 -0700 Subject: [PATCH 20/30] Use MarshalDirection type in generators and update design doc --- .../ComInterfaceGenerator/VTableStubs.md | 2 +- .../JSImportGenerator/JSStubCodeContext.cs | 4 +-- .../Marshaling/FuncJSGenerator.cs | 8 ++--- .../Marshaling/PrimitiveJSGenerator.cs | 8 ++--- .../Marshaling/TaskJSGenerator.cs | 8 ++--- .../JSImportGenerator.Unit.Tests.csproj | 4 +-- .../ComInterfaceGenerator.csproj | 4 --- .../VirtualMethodIndexData.cs | 5 --- .../VtableIndexStubGenerator.cs | 1 - .../CustomTypeMarshallingDirection.cs | 33 ------------------- .../Microsoft.Interop.SourceGeneration.csproj | 4 +++ .../StubCodeContext.cs | 6 +--- .../Ancillary.Interop.csproj | 5 ++- .../MarshalDirection.cs | 10 +++--- 14 files changed, 30 insertions(+), 72 deletions(-) delete mode 100644 src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/CustomTypeMarshallingDirection.cs rename src/libraries/System.Runtime.InteropServices/tests/{Ancillary.Interop => Common}/MarshalDirection.cs (74%) diff --git a/docs/design/libraries/ComInterfaceGenerator/VTableStubs.md b/docs/design/libraries/ComInterfaceGenerator/VTableStubs.md index 310552c24d4b1..d11034770609c 100644 --- a/docs/design/libraries/ComInterfaceGenerator/VTableStubs.md +++ b/docs/design/libraries/ComInterfaceGenerator/VTableStubs.md @@ -28,7 +28,7 @@ public class VirtualMethodIndexAttribute : Attribute public bool ImplicitThisParameter { get; set; } = true; - public CustomTypeMarshallerDirection Direction { get; set; } = CustomTypeMarshallerDirection.Ref; + public MarshalDirection Direction { get; set; } = MarshalDirection.Bidirectional; /// /// Gets or sets how to marshal string arguments to the method. diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSStubCodeContext.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSStubCodeContext.cs index abd0e3da24e97..cc4cca298fa5f 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSStubCodeContext.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSStubCodeContext.cs @@ -25,7 +25,7 @@ internal sealed record JSImportCodeContext : JSStubCodeContext public JSImportCodeContext(JSImportData attributeData, StubCodeContext inner) { _inner = inner; - Direction = CustomTypeMarshallingDirection.In; + Direction = MarshalDirection.ManagedToUnmanaged; AttributeData = attributeData; } @@ -37,7 +37,7 @@ internal sealed record JSExportCodeContext : JSStubCodeContext public JSExportCodeContext(JSExportData attributeData, StubCodeContext inner) { _inner = inner; - Direction = CustomTypeMarshallingDirection.Out; + Direction = MarshalDirection.UnmanagedToManaged; AttributeData = attributeData; } diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/FuncJSGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/FuncJSGenerator.cs index fed51dde6d6f6..79ff1efe30aaa 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/FuncJSGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/FuncJSGenerator.cs @@ -53,12 +53,12 @@ public override IEnumerable Generate(TypePositionInfo info, Stu .Select(a => ParseTypeName(a.FullTypeName)) .ToArray(); - if (context.CurrentStage == StubCodeContext.Stage.Unmarshal && context.Direction == CustomTypeMarshallingDirection.In && info.IsManagedReturnPosition) + if (context.CurrentStage == StubCodeContext.Stage.Unmarshal && context.Direction == MarshalDirection.ManagedToUnmanaged && info.IsManagedReturnPosition) { yield return ToManagedMethod(target, source, jsty); } - if (context.CurrentStage == StubCodeContext.Stage.Marshal && context.Direction == CustomTypeMarshallingDirection.Out && info.IsManagedReturnPosition) + if (context.CurrentStage == StubCodeContext.Stage.Marshal && context.Direction == MarshalDirection.UnmanagedToManaged && info.IsManagedReturnPosition) { yield return ToJSMethod(target, source, jsty); } @@ -68,12 +68,12 @@ public override IEnumerable Generate(TypePositionInfo info, Stu yield return x; } - if (context.CurrentStage == StubCodeContext.Stage.Invoke && context.Direction == CustomTypeMarshallingDirection.In && !info.IsManagedReturnPosition) + if (context.CurrentStage == StubCodeContext.Stage.Invoke && context.Direction == MarshalDirection.ManagedToUnmanaged && !info.IsManagedReturnPosition) { yield return ToJSMethod(target, source, jsty); } - if (context.CurrentStage == StubCodeContext.Stage.Unmarshal && context.Direction == CustomTypeMarshallingDirection.Out && !info.IsManagedReturnPosition) + if (context.CurrentStage == StubCodeContext.Stage.Unmarshal && context.Direction == MarshalDirection.UnmanagedToManaged && !info.IsManagedReturnPosition) { yield return ToManagedMethod(target, source, jsty); } diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/PrimitiveJSGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/PrimitiveJSGenerator.cs index e3920e46765fb..131721475fc48 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/PrimitiveJSGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/PrimitiveJSGenerator.cs @@ -32,12 +32,12 @@ public override IEnumerable Generate(TypePositionInfo info, Stu ? Argument(IdentifierName(context.GetIdentifiers(info).native)) : _inner.AsArgument(info, context); - if (context.CurrentStage == StubCodeContext.Stage.Unmarshal && context.Direction == CustomTypeMarshallingDirection.In && info.IsManagedReturnPosition) + if (context.CurrentStage == StubCodeContext.Stage.Unmarshal && context.Direction == MarshalDirection.ManagedToUnmanaged && info.IsManagedReturnPosition) { yield return ToManagedMethod(target, source); } - if (context.CurrentStage == StubCodeContext.Stage.Marshal && context.Direction == CustomTypeMarshallingDirection.Out && info.IsManagedReturnPosition) + if (context.CurrentStage == StubCodeContext.Stage.Marshal && context.Direction == MarshalDirection.UnmanagedToManaged && info.IsManagedReturnPosition) { yield return ToJSMethod(target, source); } @@ -47,12 +47,12 @@ public override IEnumerable Generate(TypePositionInfo info, Stu yield return x; } - if (context.CurrentStage == StubCodeContext.Stage.Invoke && context.Direction == CustomTypeMarshallingDirection.In && !info.IsManagedReturnPosition) + if (context.CurrentStage == StubCodeContext.Stage.Invoke && context.Direction == MarshalDirection.ManagedToUnmanaged && !info.IsManagedReturnPosition) { yield return ToJSMethod(target, source); } - if (context.CurrentStage == StubCodeContext.Stage.Unmarshal && context.Direction == CustomTypeMarshallingDirection.Out && !info.IsManagedReturnPosition) + if (context.CurrentStage == StubCodeContext.Stage.Unmarshal && context.Direction == MarshalDirection.UnmanagedToManaged && !info.IsManagedReturnPosition) { yield return ToManagedMethod(target, source); } diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/TaskJSGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/TaskJSGenerator.cs index 86162f0e62c94..41be2d67a35f5 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/TaskJSGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Marshaling/TaskJSGenerator.cs @@ -45,14 +45,14 @@ public override IEnumerable Generate(TypePositionInfo info, Stu ? Argument(IdentifierName(context.GetIdentifiers(info).native)) : _inner.AsArgument(info, context); - if (context.CurrentStage == StubCodeContext.Stage.Unmarshal && context.Direction == CustomTypeMarshallingDirection.In && info.IsManagedReturnPosition) + if (context.CurrentStage == StubCodeContext.Stage.Unmarshal && context.Direction == MarshalDirection.ManagedToUnmanaged && info.IsManagedReturnPosition) { yield return jsty.ResultTypeInfo.FullTypeName == "void" ? ToManagedMethodVoid(target, source) : ToManagedMethod(target, source, jsty.ResultTypeInfo.Syntax); } - if (context.CurrentStage == StubCodeContext.Stage.Marshal && context.Direction == CustomTypeMarshallingDirection.Out && info.IsManagedReturnPosition) + if (context.CurrentStage == StubCodeContext.Stage.Marshal && context.Direction == MarshalDirection.UnmanagedToManaged && info.IsManagedReturnPosition) { yield return jsty.ResultTypeInfo.FullTypeName == "void" ? ToJSMethodVoid(target, source) @@ -64,14 +64,14 @@ public override IEnumerable Generate(TypePositionInfo info, Stu yield return x; } - if (context.CurrentStage == StubCodeContext.Stage.Invoke && context.Direction == CustomTypeMarshallingDirection.In && !info.IsManagedReturnPosition) + if (context.CurrentStage == StubCodeContext.Stage.Invoke && context.Direction == MarshalDirection.ManagedToUnmanaged && !info.IsManagedReturnPosition) { yield return jsty.ResultTypeInfo.FullTypeName == "void" ? ToJSMethodVoid(target, source) : ToJSMethod(target, source, jsty.ResultTypeInfo.Syntax); } - if (context.CurrentStage == StubCodeContext.Stage.Unmarshal && context.Direction == CustomTypeMarshallingDirection.Out && !info.IsManagedReturnPosition) + if (context.CurrentStage == StubCodeContext.Stage.Unmarshal && context.Direction == MarshalDirection.UnmanagedToManaged && !info.IsManagedReturnPosition) { yield return jsty.ResultTypeInfo.FullTypeName == "void" ? ToManagedMethodVoid(target, source) diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/JSImportGenerator.UnitTest/JSImportGenerator.Unit.Tests.csproj b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/JSImportGenerator.UnitTest/JSImportGenerator.Unit.Tests.csproj index 73d8ac230d715..c76fea34bdbe6 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/JSImportGenerator.UnitTest/JSImportGenerator.Unit.Tests.csproj +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/JSImportGenerator.UnitTest/JSImportGenerator.Unit.Tests.csproj @@ -6,7 +6,7 @@ - + @@ -16,7 +16,7 @@ - + diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.csproj b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.csproj index 781609f548b28..6b0fb74742372 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.csproj +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.csproj @@ -28,10 +28,6 @@ - - - - diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VirtualMethodIndexData.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VirtualMethodIndexData.cs index c46ce9b92e987..99f27201a9af3 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VirtualMethodIndexData.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VirtualMethodIndexData.cs @@ -1,11 +1,6 @@ // 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.Runtime.InteropServices; -using System.Runtime.InteropServices.Marshalling; -using Microsoft.CodeAnalysis; - namespace Microsoft.Interop { /// diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs index f5e5d5db08855..0bddd9a84d590 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs @@ -7,7 +7,6 @@ using System.Diagnostics; using System.Linq; using System.Runtime.InteropServices; -using System.Runtime.InteropServices.Marshalling; using System.Text; using System.Threading; using Microsoft.CodeAnalysis; diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/CustomTypeMarshallingDirection.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/CustomTypeMarshallingDirection.cs deleted file mode 100644 index 25dd1dd095402..0000000000000 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/CustomTypeMarshallingDirection.cs +++ /dev/null @@ -1,33 +0,0 @@ -// 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.ComponentModel; - - -namespace Microsoft.Interop -{ - /// - /// A direction of marshalling data into or out of the managed environment - /// - [Flags] - public enum CustomTypeMarshallingDirection - { - /// - /// No marshalling direction - /// - [EditorBrowsable(EditorBrowsableState.Never)] - None = 0, - /// - /// Marshalling from a managed environment to an unmanaged environment - /// - In = 0x1, - /// - /// Marshalling from an unmanaged environment to a managed environment - /// - Out = 0x2, - /// - /// Marshalling to and from managed and unmanaged environments - /// - Ref = In | Out, - } -} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj index f9304841f0b34..36c12a5546cf3 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj @@ -13,6 +13,10 @@ + + + + diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/StubCodeContext.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/StubCodeContext.cs index abf39fe458379..fe10c970d2eb3 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/StubCodeContext.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/StubCodeContext.cs @@ -80,11 +80,7 @@ public enum Stage /// public Stage CurrentStage { get; init; } = Stage.Invalid; - /// - /// CustomTypeMarshallingDirection.In means method import like [LibraryImport]. - /// CustomTypeMarshallingDirection.Out means method export like in [UnmanagedCallersOnly] or in [JSExport] - /// - public CustomTypeMarshallingDirection Direction { get; init; } = CustomTypeMarshallingDirection.In; + public MarshalDirection Direction { get; init; } = MarshalDirection.ManagedToUnmanaged; /// /// Gets the currently targeted framework and version for stub code generation. diff --git a/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/Ancillary.Interop.csproj b/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/Ancillary.Interop.csproj index 526532b35bc1a..e3404e9871a84 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/Ancillary.Interop.csproj +++ b/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/Ancillary.Interop.csproj @@ -7,7 +7,10 @@ enable true APIs required for usage of the LibraryImportGenerator and related tools. - $(DefineConstants);LIBRARYIMPORT_GENERATOR_TEST + $(DefineConstants);ANCILLARY_INTEROP + + + diff --git a/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/MarshalDirection.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/MarshalDirection.cs similarity index 74% rename from src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/MarshalDirection.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/MarshalDirection.cs index 28aa98bce7410..131506e7cc7f6 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/MarshalDirection.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/Common/MarshalDirection.cs @@ -1,13 +1,11 @@ // 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.Linq; -using System.Text; -using System.Threading.Tasks; - +#if ANCILLARY_INTEROP namespace System.Runtime.InteropServices.Marshalling +#else +namespace Microsoft.Interop +#endif { public enum MarshalDirection { From 9ca69ddf0e0c1e967da0d0898a7289aa8b3a6fa6 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Thu, 25 Aug 2022 11:57:16 -0700 Subject: [PATCH 21/30] Use static-abstracts + DIMs to remove the extra shape validation. --- .../ComInterfaceGenerator/VTableStubs.md | 37 +++++++---- .../ManagedToNativeVTableMethodGenerator.cs | 15 ++--- .../VtableIndexStubGenerator.cs | 7 +- .../TypeNames.cs | 2 + .../IUnmanagedVirtualMethodTableProvider.cs | 13 +++- .../ImplicitThisTests.cs | 4 +- .../NoImplicitThisTests.cs | 4 +- .../CodeSnippets.cs | 64 +++++++++---------- 8 files changed, 84 insertions(+), 62 deletions(-) diff --git a/docs/design/libraries/ComInterfaceGenerator/VTableStubs.md b/docs/design/libraries/ComInterfaceGenerator/VTableStubs.md index d11034770609c..21a10864759c8 100644 --- a/docs/design/libraries/ComInterfaceGenerator/VTableStubs.md +++ b/docs/design/libraries/ComInterfaceGenerator/VTableStubs.md @@ -57,7 +57,7 @@ public class VirtualMethodIndexAttribute : Attribute ``` -A new interface will be defined and used by the source generator to fetch the native `this` pointer and the vtable that the function pointer is stored in. This interface is designed to provide an API that various native platforms, like COM, WinRT, or Swift, could use to provide support for multiple managed interface wrappers from a single native object. In particular, this interface was designed to ensure it is possible support a managed gesture to do an unmanaged "type cast" (i.e., `QueryInterface` in the COM and WinRT worlds). +New interfaces will be defined and used by the source generator to fetch the native `this` pointer and the vtable that the function pointer is stored in. These interfaces are designed to provide an API that various native platforms, like COM, WinRT, or Swift, could use to provide support for multiple managed interface wrappers from a single native object. In particular, these interfaces are designed to ensure it is possible support a managed gesture to do an unmanaged "type cast" (i.e., `QueryInterface` in the COM and WinRT worlds). ```csharp namespace System.Runtime.InteropServices; @@ -82,13 +82,24 @@ public readonly ref struct VirtualMethodTableInfo public interface IUnmanagedVirtualMethodTableProvider where T : IEquatable { - VirtualMethodTableInfo GetVirtualMethodTableInfoForKey(T typeKey); + protected VirtualMethodTableInfo GetVirtualMethodTableInfoForKey(T typeKey); + + public sealed VirtualMethodTableInfo GetVirtualMethodTableInfoForKey() + where TUnmanagedInterfaceType : IUnmanagedInterfaceType + { + return GetVirtualMethodTableInfoForKey(TUnmanagedInterfaceType.TypeKey); + } +} + +public interface IUnmanagedInterfaceType where T : IEquatable +{ + public abstract static T TypeKey { get; } } ``` ## Required API Shapes -In addition to the provided APIs above, users will be required to add a `readonly static` field or `get`-able property to their user-defined interface type named `TypeKey`. The type of this member will be used as the `T` in `IUnmanagedVirtualMethodTableProvider` and the value will be passed to `GetVirtualMethodTableInfoForKey`. This mechanism is designed to enable each native API platform to provide their own casting key, for example `IID`s in COM, without interfering with each other or requiring using reflection-based types like `System.Type`. +The user will be required to implement `IUnmanagedVirtualMethodTableProvider` on the type that provides the method tables, and `IUnmanagedInterfaceType` on the type that defines the unmanaged interface. The `T` types must match between the two interfaces. This mechanism is designed to enable each native API platform to provide their own casting key, for example `IID`s in COM, without interfering with each other or requiring using reflection-based types like `System.Type`. ## Example Usage @@ -149,11 +160,11 @@ using System.Runtime.InteropServices; [assembly:DisableRuntimeMarshalling] // Define the interface of the native API -partial interface INativeAPI +partial interface INativeAPI : IUnmanagedInterfaceType { // There is no concept of casting for this API, but providing a type key is still required by the generator. // Use an empty readonly record struct to provide a type that implements IEquatable but contains no data. - readonly static NoCasting TypeKey = default; + static NoCasting IUnmanagedInterfaceType.TypeKey => default; [VirtualMethodIndex(0, ImplicitThisParameter = false, Direction = CustomTypeMarshallerDirection.In)] int GetVersion(); @@ -218,7 +229,7 @@ partial interface INativeAPI { int INativeAPI.GetVersion() { - var (_, vtable) = ((IUnmanagedVirtualMethodTableProvider)this).GetVirtualMethodTableInfoForKey(INativeAPI.TypeKey); + var (_, vtable) = ((IUnmanagedVirtualMethodTableProvider)this).GetVirtualMethodTableInfoForKey(); int retVal; retVal = ((delegate* unmanaged)vtable[0])(); return retVal; @@ -231,7 +242,7 @@ partial interface INativeAPI { int INativeAPI.Add(int x, int y) { - var (_, vtable) = ((IUnmanagedVirtualMethodTableProvider)this).GetVirtualMethodTableInfoForKey(INativeAPI.TypeKey); + var (_, vtable) = ((IUnmanagedVirtualMethodTableProvider)this).GetVirtualMethodTableInfoForKey(); int retVal; retVal = ((delegate* unmanaged)vtable[1])(x, y); return retVal; @@ -244,7 +255,7 @@ partial interface INativeAPI { int INativeAPI.Multiply(int x, int y) { - var (_, vtable) = ((IUnmanagedVirtualMethodTableProvider)this).GetVirtualMethodTableInfoForKey(INativeAPI.TypeKey); + var (_, vtable) = ((IUnmanagedVirtualMethodTableProvider)this).GetVirtualMethodTableInfoForKey(); int retVal; retVal = ((delegate* unmanaged)vtable[2])(x, y); return retVal; @@ -279,9 +290,9 @@ struct IUnknown using System; using System.Runtime.InteropServices; -interface IUnknown +interface IUnknown: IUnmanagedInterfaceType { - public static readonly Guid TypeKey = Guid.Parse("00000000-0000-0000-C000-000000000046"); + static Guid IUnmanagedTypeInterfaceType.TypeKey => Guid.Parse("00000000-0000-0000-C000-000000000046"); [UnmanagedCallConv(CallConvs = new[] { typeof(CallConvStdcall), typeof(CallConvMemberFunction) })] [VirtualMethodIndex(0)] @@ -347,7 +358,7 @@ partial interface IUnknown { int IUnknown.QueryInterface(in Guid riid, out IntPtr ppvObject) { - var (thisPtr, vtable) = ((IUnmanagedVirtualMethodTableProvider)this).GetVirtualMethodTableInfoForKey(IUnknown.TypeKey); + var (thisPtr, vtable) = ((IUnmanagedVirtualMethodTableProvider)this).GetVirtualMethodTableInfoForKey(); int retVal; fixed (Guid* riid__gen_native = &riid) fixed (IntPtr* ppvObject__gen_native = &ppvObject) @@ -364,7 +375,7 @@ partial interface IUnknown { uint IUnknown.AddRef() { - var (thisPtr, vtable) = ((IUnmanagedVirtualMethodTableProvider)this).GetVirtualMethodTableInfoForKey(IUnknown.TypeKey); + var (thisPtr, vtable) = ((IUnmanagedVirtualMethodTableProvider)this).GetVirtualMethodTableInfoForKey(); uint retVal; retVal = ((delegate* unmanaged[Stdcall, MemberFunction])vtable[1])(thisPtr); return retVal; @@ -377,7 +388,7 @@ partial interface IUnknown { uint IUnknown.Release() { - var (thisPtr, vtable) = ((IUnmanagedVirtualMethodTableProvider)this).GetVirtualMethodTableInfoForKey(IUnknown.TypeKey); + var (thisPtr, vtable) = ((IUnmanagedVirtualMethodTableProvider)this).GetVirtualMethodTableInfoForKey(); uint retVal; retVal = ((delegate* unmanaged[Stdcall, MemberFunction])vtable[2])(thisPtr); return retVal; diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedToNativeVTableMethodGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedToNativeVTableMethodGenerator.cs index 645af622c4c6d..ae784ff047d2f 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedToNativeVTableMethodGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedToNativeVTableMethodGenerator.cs @@ -117,7 +117,7 @@ public BlockSyntax GenerateStubBody(int index, ImmutableArray { - // var (, ) = ((IUnmanagedVirtualMethodTableProvider<>)this).GetVirtualMethodTableInfoForKey(.TypeKey) + // var (, ) = ((IUnmanagedVirtualMethodTableProvider<>)this).GetVirtualMethodTableInfoForKey<>(); ExpressionStatement( AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, @@ -141,15 +141,12 @@ public BlockSyntax GenerateStubBody(int index, ImmutableArray().FirstOrDefault(f => f.IsStatic); - if (typeKeyField is null) + INamedTypeSymbol? iUnmanagedInterfaceTypeInstantiation = symbol.ContainingType.AllInterfaces.FirstOrDefault(iface => SymbolEqualityComparer.Default.Equals(iface.OriginalDefinition, iUnmanagedInterfaceTypeType)); + if (iUnmanagedInterfaceTypeInstantiation is null) { // Report invalid configuration } else { - typeKeyType = ManagedTypeInfo.CreateTypeInfoForTypeSymbol(typeKeyField.Type); + typeKeyType = ManagedTypeInfo.CreateTypeInfoForTypeSymbol(iUnmanagedInterfaceTypeInstantiation.TypeArguments[0]); } return new IncrementalStubGenerationContext( diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeNames.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeNames.cs index 9fb72bdb94c02..e999aed83cdbb 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeNames.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeNames.cs @@ -32,6 +32,8 @@ public static class TypeNames public const string IUnmanagedVirtualMethodTableProvider = "System.Runtime.InteropServices.IUnmanagedVirtualMethodTableProvider"; + public const string IUnmanagedInterfaceType_Metadata = "System.Runtime.InteropServices.IUnmanagedInterfaceType`1"; + public const string System_Span_Metadata = "System.Span`1"; public const string System_Span = "System.Span"; public const string System_ReadOnlySpan_Metadata = "System.ReadOnlySpan`1"; diff --git a/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/IUnmanagedVirtualMethodTableProvider.cs b/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/IUnmanagedVirtualMethodTableProvider.cs index 29e56c729f5c2..9b77ec6493b8a 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/IUnmanagedVirtualMethodTableProvider.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/IUnmanagedVirtualMethodTableProvider.cs @@ -29,7 +29,18 @@ public void Deconstruct(out IntPtr thisPointer, out ReadOnlySpan virtual public interface IUnmanagedVirtualMethodTableProvider where T : IEquatable { - VirtualMethodTableInfo GetVirtualMethodTableInfoForKey(T typeKey); + protected VirtualMethodTableInfo GetVirtualMethodTableInfoForKey(T typeKey); + + public sealed VirtualMethodTableInfo GetVirtualMethodTableInfoForKey() + where TUnmanagedInterfaceType : IUnmanagedInterfaceType + { + return GetVirtualMethodTableInfoForKey(TUnmanagedInterfaceType.TypeKey); + } } + + public interface IUnmanagedInterfaceType where T : IEquatable + { + public abstract static T TypeKey { get; } + } } diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/ImplicitThisTests.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/ImplicitThisTests.cs index 0c88984c9fec5..fa2e70015200d 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/ImplicitThisTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/ImplicitThisTests.cs @@ -18,9 +18,9 @@ internal partial class ImplicitThis { public readonly record struct NoCasting; - internal partial interface INativeObject + internal partial interface INativeObject : IUnmanagedInterfaceType { - public static readonly NoCasting TypeKey = default; + static NoCasting IUnmanagedInterfaceType.TypeKey => default; [VirtualMethodIndex(0, ImplicitThisParameter = true)] int GetData(); diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/NoImplicitThisTests.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/NoImplicitThisTests.cs index c24892b62c7e8..4219427a4a31f 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/NoImplicitThisTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/NoImplicitThisTests.cs @@ -18,9 +18,9 @@ internal partial class NoImplicitThis { public readonly record struct NoCasting; - internal partial interface IStaticMethodTable + internal partial interface IStaticMethodTable : IUnmanagedInterfaceType { - public static readonly NoCasting TypeKey = default; + static NoCasting IUnmanagedInterfaceType.TypeKey => default; [VirtualMethodIndex(0, ImplicitThisParameter = false)] int Add(int x, int y); 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 648bf48640168..fa15018f69173 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 @@ -27,9 +27,9 @@ sealed class NativeAPI : IUnmanagedVirtualMethodTableProvider, INativ using System.Runtime.InteropServices.Marshalling; readonly record struct NoCasting {} -partial interface INativeAPI +partial interface INativeAPI : IUnmanagedInterfaceType { - public static readonly NoCasting TypeKey = default; + static NoCasting IUnmanagedInterfaceType.TypeKey => default; [VirtualMethodIndex(0)] void Method(); }" + NativeInterfaceUsage(); @@ -39,9 +39,9 @@ partial interface INativeAPI using System.Runtime.InteropServices.Marshalling; readonly record struct NoCasting {} -partial interface INativeAPI +partial interface INativeAPI : IUnmanagedInterfaceType { - public static readonly NoCasting TypeKey = default; + static NoCasting IUnmanagedInterfaceType.TypeKey => default; [VirtualMethodIndex(0, ImplicitThisParameter = false)] void Method(); }" + NativeInterfaceUsage(); @@ -52,9 +52,9 @@ partial interface INativeAPI using System.Runtime.InteropServices.Marshalling; readonly record struct NoCasting {} -partial interface INativeAPI +partial interface INativeAPI : IUnmanagedInterfaceType { - public static readonly NoCasting TypeKey = default; + static NoCasting IUnmanagedInterfaceType.TypeKey => default; [UnmanagedCallConv(CallConvs = new[] { typeof(CallConvCdecl) })] [VirtualMethodIndex(0)] @@ -86,9 +86,9 @@ public static string BasicParametersAndModifiers(string typeName, string preDecl [assembly:DisableRuntimeMarshalling] readonly record struct NoCasting {{}} -partial interface INativeAPI +partial interface INativeAPI : IUnmanagedInterfaceType {{ - public static readonly NoCasting TypeKey = default; + static NoCasting IUnmanagedInterfaceType.TypeKey => default; [VirtualMethodIndex(0)] {typeName} Method({typeName} value, in {typeName} inValue, ref {typeName} refValue, out {typeName} outValue); }}" + NativeInterfaceUsage(); @@ -102,9 +102,9 @@ public static string BasicParametersAndModifiersNoRef(string typeName, string pr [assembly:DisableRuntimeMarshalling] readonly record struct NoCasting {{}} -partial interface INativeAPI +partial interface INativeAPI : IUnmanagedInterfaceType {{ - public static readonly NoCasting TypeKey = default; + static NoCasting IUnmanagedInterfaceType.TypeKey => default; [VirtualMethodIndex(0)] {typeName} Method({typeName} value, in {typeName} inValue, out {typeName} outValue); }}" + NativeInterfaceUsage(); @@ -114,9 +114,9 @@ public static string BasicParametersAndModifiersNoImplicitThis(string typeName) using System.Runtime.InteropServices.Marshalling; readonly record struct NoCasting {{}} -partial interface INativeAPI +partial interface INativeAPI : IUnmanagedInterfaceType {{ - public static readonly NoCasting TypeKey = default; + static NoCasting IUnmanagedInterfaceType.TypeKey => default; [VirtualMethodIndex(0, ImplicitThisParameter = false)] {typeName} Method({typeName} value, in {typeName} inValue, ref {typeName} refValue, out {typeName} outValue); }}" + NativeInterfaceUsage(); @@ -130,9 +130,9 @@ public static string BasicParameterByValue(string typeName, string preDeclaratio {preDeclaration} readonly record struct NoCasting {{}} -partial interface INativeAPI +partial interface INativeAPI : IUnmanagedInterfaceType {{ - public static readonly NoCasting TypeKey = default; + static NoCasting IUnmanagedInterfaceType.TypeKey => default; [VirtualMethodIndex(0, ImplicitThisParameter = false)] void Method({typeName} value); }}" + NativeInterfaceUsage(); @@ -145,9 +145,9 @@ public static string BasicParameterWithByRefModifier(string modifier, string typ [assembly:DisableRuntimeMarshalling] readonly record struct NoCasting {{}} -partial interface INativeAPI +partial interface INativeAPI : IUnmanagedInterfaceType {{ - public static readonly NoCasting TypeKey = default; + static NoCasting IUnmanagedInterfaceType.TypeKey => default; [VirtualMethodIndex(0, ImplicitThisParameter = false)] void Method({modifier} {typeName} value); }}" + NativeInterfaceUsage(); @@ -158,9 +158,9 @@ public static string BasicReturnType(string typeName, string preDeclaration = "" {preDeclaration} readonly record struct NoCasting {{}} -partial interface INativeAPI +partial interface INativeAPI : IUnmanagedInterfaceType {{ - public static readonly NoCasting TypeKey = default; + static NoCasting IUnmanagedInterfaceType.TypeKey => default; [VirtualMethodIndex(0, ImplicitThisParameter = false)] {typeName} Method(); }}" + NativeInterfaceUsage(); @@ -171,9 +171,9 @@ public static string MarshalUsingParametersAndModifiers(string typeName, string {preDeclaration} readonly record struct NoCasting {{}} -partial interface INativeAPI +partial interface INativeAPI : IUnmanagedInterfaceType {{ - public static readonly NoCasting TypeKey = default; + static NoCasting IUnmanagedInterfaceType.TypeKey => default; [VirtualMethodIndex(0)] [return: MarshalUsing(typeof({marshallerTypeName}))] {typeName} Method( @@ -190,9 +190,9 @@ public static string MarshalUsingCollectionCountInfoParametersAndModifiers(strin [assembly:DisableRuntimeMarshalling] readonly record struct NoCasting {{}} -partial interface INativeAPI +partial interface INativeAPI : IUnmanagedInterfaceType {{ - public static readonly NoCasting TypeKey = default; + static NoCasting IUnmanagedInterfaceType.TypeKey => default; [VirtualMethodIndex(0)] [return:MarshalUsing(ConstantElementCount=10)] {collectionType} Method( @@ -211,9 +211,9 @@ public static string MarshalUsingCollectionParametersAndModifiers(string collect [assembly:DisableRuntimeMarshalling] readonly record struct NoCasting {{}} -partial interface INativeAPI +partial interface INativeAPI : IUnmanagedInterfaceType {{ - public static readonly NoCasting TypeKey = default; + static NoCasting IUnmanagedInterfaceType.TypeKey => default; [VirtualMethodIndex(0)] [return:MarshalUsing(typeof({marshallerType}), ConstantElementCount=10)] {collectionType} Method( @@ -233,9 +233,9 @@ public static string MarshalUsingCollectionReturnValueLength(string collectionTy [assembly:DisableRuntimeMarshalling] readonly record struct NoCasting {{}} -partial interface INativeAPI +partial interface INativeAPI : IUnmanagedInterfaceType {{ - public static readonly NoCasting TypeKey = default; + static NoCasting IUnmanagedInterfaceType.TypeKey => default; [VirtualMethodIndex(0)] int Method( [MarshalUsing(typeof({marshallerType}), CountElementName = MarshalUsingAttribute.ReturnsCountValue)] out {collectionType} pOut @@ -251,9 +251,9 @@ public static string MarshalUsingCollectionOutConstantLength(string collectionTy [assembly:DisableRuntimeMarshalling] readonly record struct NoCasting {{}} -partial interface INativeAPI +partial interface INativeAPI : IUnmanagedInterfaceType {{ - public static readonly NoCasting TypeKey = default; + static NoCasting IUnmanagedInterfaceType.TypeKey => default; [VirtualMethodIndex(0)] int Method( [MarshalUsing(ConstantElementCount = 10)] out {collectionType} pOut @@ -269,9 +269,9 @@ public static string MarshalUsingCollectionReturnConstantLength(string collectio [assembly:DisableRuntimeMarshalling] readonly record struct NoCasting {{}} -partial interface INativeAPI +partial interface INativeAPI : IUnmanagedInterfaceType {{ - public static readonly NoCasting TypeKey = default; + static NoCasting IUnmanagedInterfaceType.TypeKey => default; [VirtualMethodIndex(0)] [return:MarshalUsing(ConstantElementCount = 10)] {collectionType} Method(); @@ -286,9 +286,9 @@ public static string CustomElementMarshalling(string collectionType, string elem [assembly:DisableRuntimeMarshalling] readonly record struct NoCasting {{}} -partial interface INativeAPI +partial interface INativeAPI : IUnmanagedInterfaceType {{ - public static readonly NoCasting TypeKey = default; + static NoCasting IUnmanagedInterfaceType.TypeKey => default; [VirtualMethodIndex(0)] [return:MarshalUsing(ConstantElementCount=10)] [return:MarshalUsing(typeof({elementMarshaller}), ElementIndirectionDepth = 1)] From 5746f8b43b120b9a443a0fdad050c2f161b88f02 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Mon, 29 Aug 2022 15:40:37 -0700 Subject: [PATCH 22/30] Fix JS generator test build --- .../tests/JSImportGenerator.UnitTest/Compiles.cs | 2 +- .../tests/JSImportGenerator.UnitTest/Fails.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/JSImportGenerator.UnitTest/Compiles.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/JSImportGenerator.UnitTest/Compiles.cs index 46a29d20650f5..ecb257c544b3a 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/JSImportGenerator.UnitTest/Compiles.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/JSImportGenerator.UnitTest/Compiles.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; using System; using Xunit; -using LibraryImportGenerator.UnitTests; +using Microsoft.Interop.UnitTests; namespace JSImportGenerator.Unit.Tests { diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/JSImportGenerator.UnitTest/Fails.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/JSImportGenerator.UnitTest/Fails.cs index 29533c72dc60f..513af4747a4e9 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/JSImportGenerator.UnitTest/Fails.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/JSImportGenerator.UnitTest/Fails.cs @@ -5,7 +5,7 @@ using System.Collections.Generic; using System.Threading.Tasks; using Xunit; -using LibraryImportGenerator.UnitTests; +using Microsoft.Interop.UnitTests; using System.Linq; namespace JSImportGenerator.Unit.Tests From 032ebff3fd95f2bc49cb0ce9549dd7a72052ce53 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Wed, 31 Aug 2022 10:09:54 -0700 Subject: [PATCH 23/30] Fix exclusions --- src/libraries/tests.proj | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/libraries/tests.proj b/src/libraries/tests.proj index ea2fd7ac48586..9b4b36fc734e4 100644 --- a/src/libraries/tests.proj +++ b/src/libraries/tests.proj @@ -93,6 +93,7 @@ + @@ -100,23 +101,27 @@ + + + + @@ -126,6 +131,7 @@ + @@ -278,7 +284,7 @@ - @@ -286,17 +292,17 @@ - - @@ -306,7 +312,7 @@ - + @@ -424,7 +430,7 @@ - + From d964d0ce87d02d84aa40c8c11547626c907cdc60 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Fri, 2 Sep 2022 10:35:15 -0700 Subject: [PATCH 24/30] Fix exclusions of runtime tests --- src/libraries/tests.proj | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libraries/tests.proj b/src/libraries/tests.proj index 184b115fa2f1b..1391903821f2e 100644 --- a/src/libraries/tests.proj +++ b/src/libraries/tests.proj @@ -93,7 +93,7 @@ - + @@ -101,27 +101,27 @@ - + - + - + - + @@ -131,7 +131,7 @@ - + From bf8485af1d546cd8fa18795d052d22bb60ef32e4 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Fri, 2 Sep 2022 17:46:38 -0700 Subject: [PATCH 25/30] Disable runtime tests on Mono because Mono doesn't implement an API that the tests all use --- .../tests/TestAssets/NativeExports/VirtualMethodTables.cs | 2 +- src/libraries/tests.proj | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/VirtualMethodTables.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/VirtualMethodTables.cs index b0b5e019b7b8e..ac75c735f7daa 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/VirtualMethodTables.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/VirtualMethodTables.cs @@ -11,7 +11,7 @@ namespace NativeExports { - internal unsafe static class VirtualMethodTables + public unsafe static class VirtualMethodTables { struct StaticFunctionTable { diff --git a/src/libraries/tests.proj b/src/libraries/tests.proj index 1391903821f2e..48369abefdbff 100644 --- a/src/libraries/tests.proj +++ b/src/libraries/tests.proj @@ -136,6 +136,12 @@ + + + + + + From 7fc5e52d4485f6ca57910b7852023295dba1e99e Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Tue, 6 Sep 2022 13:33:27 -0700 Subject: [PATCH 26/30] Fix test disable to work in the normal runtime pipeline, albeit not particularly efficiently. --- .../tests/ComInterfaceGenerator.Tests/AssemblyInfo.cs | 7 +++++++ src/libraries/tests.proj | 6 ------ 2 files changed, 7 insertions(+), 6 deletions(-) create mode 100644 src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/AssemblyInfo.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/AssemblyInfo.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/AssemblyInfo.cs new file mode 100644 index 0000000000000..6f8836d701825 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/AssemblyInfo.cs @@ -0,0 +1,7 @@ +using Xunit; + +// Disable all tests in the assembly here. We'd prefer to disable them in src/libraries/tests.proj +// but we can't disable tests just based on RuntimeFlavor there as we build our tests once per target, not per target and runtime flavor +// in our split jobs (where we build libraries in one job and the runtime in another). +// As a result, we'll disable these tests here for now. +[assembly:SkipOnMono("All tests here use RuntimeHelpers.AllocateTypeAssociatedMemory, which is not implemented on Mono")] \ No newline at end of file diff --git a/src/libraries/tests.proj b/src/libraries/tests.proj index 48369abefdbff..1391903821f2e 100644 --- a/src/libraries/tests.proj +++ b/src/libraries/tests.proj @@ -136,12 +136,6 @@ - - - - - - From 3008cd5123a4cc5fb7762d80fec18640896d421b Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Fri, 23 Sep 2022 17:20:37 -0700 Subject: [PATCH 27/30] Directly pass along target framework kind and version instead of StubEnvironment to avoid rooting the compilation. Update all generators to follow suit and add a test in LibraryImportGenerator to validate that we don't keep the compilation alive. Also fix the build failure in ComInterfaceGenerator --- .../JSExportCodeGenerator.cs | 7 +- .../JSImportGenerator/JSExportGenerator.cs | 34 +---- .../JSImportCodeGenerator.cs | 7 +- .../JSImportGenerator/JSImportGenerator.cs | 31 +--- .../System.Runtime.InteropServices.sln | 141 +++++++++--------- .../ComInterfaceGenerator.csproj | 1 + .../ComInterfaceGeneratorHelpers.cs | 54 +++++++ .../ManagedToNativeVTableMethodGenerator.cs | 9 +- .../VtableIndexStubGenerator.cs | 46 +++--- .../DefaultMarshallingInfoParser.cs | 0 .../ConvertToLibraryImportAnalyzer.cs | 2 +- .../LibraryImportGenerator.cs | 44 ++---- .../LibraryImportGenerator.csproj | 3 +- .../PInvokeStubCodeGenerator.cs | 16 +- .../ManagedToNativeStubCodeContext.cs | 10 +- .../StubEnvironment.cs | 28 +--- .../IncrementalGenerationTests.cs | 47 ++++++ 17 files changed, 248 insertions(+), 232 deletions(-) create mode 100644 src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGeneratorHelpers.cs rename src/libraries/System.Runtime.InteropServices/gen/{LibraryImportGenerator => Common}/DefaultMarshallingInfoParser.cs (100%) diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportCodeGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportCodeGenerator.cs index 3c44d665748b5..614bad043f15a 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportCodeGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportCodeGenerator.cs @@ -20,7 +20,8 @@ internal sealed class JSExportCodeGenerator : JSCodeGenerator private readonly JSSignatureContext _signatureContext; public JSExportCodeGenerator( - StubEnvironment environment, + TargetFramework targetFramework, + Version targetFrameworkVersion, ImmutableArray argTypes, JSExportData attributeData, JSSignatureContext signatureContext, @@ -28,13 +29,13 @@ public JSExportCodeGenerator( IMarshallingGeneratorFactory generatorFactory) { _signatureContext = signatureContext; - ManagedToNativeStubCodeContext innerContext = new ManagedToNativeStubCodeContext(environment, ReturnIdentifier, ReturnIdentifier); + ManagedToNativeStubCodeContext innerContext = new ManagedToNativeStubCodeContext(targetFramework, targetFrameworkVersion, ReturnIdentifier, ReturnIdentifier); _context = new JSExportCodeContext(attributeData, innerContext); _marshallers = new BoundGenerators(argTypes, CreateGenerator); if (_marshallers.ManagedReturnMarshaller.Generator.UsesNativeIdentifier(_marshallers.ManagedReturnMarshaller.TypeInfo, null)) { // If we need a different native return identifier, then recreate the context with the correct identifier before we generate any code. - innerContext = new ManagedToNativeStubCodeContext(environment, ReturnIdentifier, ReturnNativeIdentifier); + innerContext = new ManagedToNativeStubCodeContext(targetFramework, targetFrameworkVersion, ReturnIdentifier, ReturnNativeIdentifier); _context = new JSExportCodeContext(attributeData, innerContext); _marshallers = new BoundGenerators(argTypes, CreateGenerator); } diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportGenerator.cs index c033637881673..d84440e075087 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportGenerator.cs @@ -17,33 +17,13 @@ namespace Microsoft.Interop.JavaScript public sealed class JSExportGenerator : IIncrementalGenerator { internal sealed record IncrementalStubGenerationContext( - StubEnvironment Environment, JSSignatureContext SignatureContext, ContainingSyntaxContext ContainingSyntaxContext, ContainingSyntax StubMethodSyntaxTemplate, MethodSignatureDiagnosticLocations DiagnosticLocation, JSExportData JSExportData, - MarshallingGeneratorFactoryKey<(TargetFramework, Version, JSGeneratorOptions)> GeneratorFactoryKey, - ImmutableArray Diagnostics) - { - public bool Equals(IncrementalStubGenerationContext? other) - { - return other is not null - && StubEnvironment.AreCompilationSettingsEqual(Environment, other.Environment) - && SignatureContext.Equals(other.SignatureContext) - && ContainingSyntaxContext.Equals(other.ContainingSyntaxContext) - && StubMethodSyntaxTemplate.Equals(other.StubMethodSyntaxTemplate) - && JSExportData.Equals(other.JSExportData) - && DiagnosticLocation.Equals(DiagnosticLocation) - && GeneratorFactoryKey.Equals(other.GeneratorFactoryKey) - && Diagnostics.SequenceEqual(other.Diagnostics); - } - - public override int GetHashCode() - { - throw new UnreachableException(); - } - } + MarshallingGeneratorFactoryKey<(TargetFramework TargetFramework, Version TargetFrameworkVersion, JSGeneratorOptions)> GeneratorFactoryKey, + ImmutableArray Diagnostics); public static class StepNames { @@ -119,9 +99,8 @@ public void Initialize(IncrementalGeneratorInitializationContext context) static (data, ct) => CalculateStubInformation(data.Syntax, data.Symbol, data.Environment, data.Options, ct) ) .WithTrackingName(StepNames.CalculateStubInformation) - .Combine(stubOptions) .Select( - static (data, ct) => GenerateSource(data.Left, data.Right) + static (data, ct) => GenerateSource(data) ) .WithComparer(Comparers.GeneratedSyntax) .WithTrackingName(StepNames.GenerateSingleStub); @@ -215,7 +194,6 @@ private static IncrementalStubGenerationContext CalculateStubInformation( var methodSyntaxTemplate = new ContainingSyntax(originalSyntax.Modifiers.StripTriviaFromTokens(), SyntaxKind.MethodDeclaration, originalSyntax.Identifier, originalSyntax.TypeParameterList); return new IncrementalStubGenerationContext( - environment, signatureContext, containingTypeContext, methodSyntaxTemplate, @@ -232,14 +210,14 @@ private static IncrementalStubGenerationContext CalculateStubInformation( } private static (MemberDeclarationSyntax, ImmutableArray) GenerateSource( - IncrementalStubGenerationContext incrementalContext, - JSGeneratorOptions options) + IncrementalStubGenerationContext incrementalContext) { var diagnostics = new GeneratorDiagnostics(); // Generate stub code var stubGenerator = new JSExportCodeGenerator( - incrementalContext.Environment, + incrementalContext.GeneratorFactoryKey.Key.TargetFramework, + incrementalContext.GeneratorFactoryKey.Key.TargetFrameworkVersion, incrementalContext.SignatureContext.SignatureContext.ElementTypeInformation, incrementalContext.JSExportData, incrementalContext.SignatureContext, diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportCodeGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportCodeGenerator.cs index b7c1a324b2c47..1f1ebdf81b626 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportCodeGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportCodeGenerator.cs @@ -27,7 +27,8 @@ internal sealed class JSImportCodeGenerator : JSCodeGenerator private readonly JSSignatureContext _signatureContext; public JSImportCodeGenerator( - StubEnvironment environment, + TargetFramework targetFramework, + Version targetFrameworkVersion, ImmutableArray argTypes, JSImportData attributeData, JSSignatureContext signatureContext, @@ -35,13 +36,13 @@ public JSImportCodeGenerator( IMarshallingGeneratorFactory generatorFactory) { _signatureContext = signatureContext; - ManagedToNativeStubCodeContext innerContext = new ManagedToNativeStubCodeContext(environment, ReturnIdentifier, ReturnIdentifier); + ManagedToNativeStubCodeContext innerContext = new ManagedToNativeStubCodeContext(targetFramework, targetFrameworkVersion, ReturnIdentifier, ReturnIdentifier); _context = new JSImportCodeContext(attributeData, innerContext); _marshallers = new BoundGenerators(argTypes, CreateGenerator); if (_marshallers.ManagedReturnMarshaller.Generator.UsesNativeIdentifier(_marshallers.ManagedReturnMarshaller.TypeInfo, null)) { // If we need a different native return identifier, then recreate the context with the correct identifier before we generate any code. - innerContext = new ManagedToNativeStubCodeContext(environment, ReturnIdentifier, ReturnNativeIdentifier); + innerContext = new ManagedToNativeStubCodeContext(targetFramework, targetFrameworkVersion, ReturnIdentifier, ReturnNativeIdentifier); _context = new JSImportCodeContext(attributeData, innerContext); _marshallers = new BoundGenerators(argTypes, CreateGenerator); } diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportGenerator.cs index 0ce77445a85a8..6aed61fe5dc11 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportGenerator.cs @@ -2,12 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; -using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; using System.Linq; -using System.Runtime.InteropServices; -using System.Text; using System.Threading; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; @@ -22,33 +19,13 @@ namespace Microsoft.Interop.JavaScript public sealed class JSImportGenerator : IIncrementalGenerator { internal sealed record IncrementalStubGenerationContext( - StubEnvironment Environment, JSSignatureContext SignatureContext, ContainingSyntaxContext ContainingSyntaxContext, ContainingSyntax StubMethodSyntaxTemplate, MethodSignatureDiagnosticLocations DiagnosticLocation, JSImportData JSImportData, - MarshallingGeneratorFactoryKey<(TargetFramework, Version, JSGeneratorOptions)> GeneratorFactoryKey, - ImmutableArray Diagnostics) - { - public bool Equals(IncrementalStubGenerationContext? other) - { - return other is not null - && StubEnvironment.AreCompilationSettingsEqual(Environment, other.Environment) - && SignatureContext.Equals(other.SignatureContext) - && ContainingSyntaxContext.Equals(other.ContainingSyntaxContext) - && StubMethodSyntaxTemplate.Equals(other.StubMethodSyntaxTemplate) - && JSImportData.Equals(other.JSImportData) - && DiagnosticLocation.Equals(DiagnosticLocation) - && GeneratorFactoryKey.Equals(other.GeneratorFactoryKey) - && Diagnostics.SequenceEqual(other.Diagnostics); - } - - public override int GetHashCode() - { - throw new UnreachableException(); - } - } + MarshallingGeneratorFactoryKey<(TargetFramework TargetFramework, Version TargetFrameworkVersion, JSGeneratorOptions)> GeneratorFactoryKey, + ImmutableArray Diagnostics); public static class StepNames { @@ -228,7 +205,6 @@ private static IncrementalStubGenerationContext CalculateStubInformation( var methodSyntaxTemplate = new ContainingSyntax(originalSyntax.Modifiers.StripTriviaFromTokens(), SyntaxKind.MethodDeclaration, originalSyntax.Identifier, originalSyntax.TypeParameterList); return new IncrementalStubGenerationContext( - environment, signatureContext, containingTypeContext, methodSyntaxTemplate, @@ -253,7 +229,8 @@ private static (MemberDeclarationSyntax, ImmutableArray) GenerateSou // Generate stub code var stubGenerator = new JSImportCodeGenerator( - incrementalContext.Environment, + incrementalContext.GeneratorFactoryKey.Key.TargetFramework, + incrementalContext.GeneratorFactoryKey.Key.TargetFrameworkVersion, incrementalContext.SignatureContext.SignatureContext.ElementTypeInformation, incrementalContext.JSImportData, incrementalContext.SignatureContext, diff --git a/src/libraries/System.Runtime.InteropServices/System.Runtime.InteropServices.sln b/src/libraries/System.Runtime.InteropServices/System.Runtime.InteropServices.sln index 73e3169c43435..74d9eea95a665 100644 --- a/src/libraries/System.Runtime.InteropServices/System.Runtime.InteropServices.sln +++ b/src/libraries/System.Runtime.InteropServices/System.Runtime.InteropServices.sln @@ -1,4 +1,8 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.4.32915.420 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Private.CoreLib", "..\..\coreclr\System.Private.CoreLib\System.Private.CoreLib.csproj", "{94B59BA0-491F-4B59-ADFF-A057EC3EC835}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestUtilities", "..\Common\tests\TestUtilities\TestUtilities.csproj", "{1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}" @@ -45,21 +49,27 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ComInterfaceGenerator", "ge EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ComInterfaceGenerator.Unit.Tests", "tests\ComInterfaceGenerator.Unit.Tests\ComInterfaceGenerator.Unit.Tests.csproj", "{1D771995-D475-429B-AC31-2B1F618AA45F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ComInterfaceGenerator.Tests", "tests\ComInterfaceGenerator.Tests\ComInterfaceGenerator.Tests.csproj", "{3741C833-C364-4269-9B1D-D442055DA7CE}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ComInterfaceGenerator.Tests", "tests\ComInterfaceGenerator.Tests\ComInterfaceGenerator.Tests.csproj", "{3741C833-C364-4269-9B1D-D442055DA7CE}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Checked|Any CPU = Checked|Any CPU + Checked|x64 = Checked|x64 + Checked|x86 = Checked|x86 Debug|Any CPU = Debug|Any CPU Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU Release|x64 = Release|x64 Release|x86 = Release|x86 - Checked|Any CPU = Checked|Any CPU - Checked|x64 = Checked|x64 - Checked|x86 = Checked|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|Any CPU.ActiveCfg = Checked|x64 + {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|Any CPU.Build.0 = Checked|x64 + {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|x64.ActiveCfg = Checked|x64 + {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|x64.Build.0 = Checked|x64 + {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|x86.ActiveCfg = Checked|x86 + {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|x86.Build.0 = Checked|x86 {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Debug|Any CPU.ActiveCfg = Debug|x64 {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Debug|Any CPU.Build.0 = Debug|x64 {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Debug|x64.ActiveCfg = Debug|x64 @@ -72,12 +82,9 @@ Global {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Release|x64.Build.0 = Release|x64 {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Release|x86.ActiveCfg = Release|x86 {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Release|x86.Build.0 = Release|x86 - {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|Any CPU.ActiveCfg = Checked|x64 - {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|Any CPU.Build.0 = Checked|x64 - {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|x64.ActiveCfg = Checked|x64 - {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|x64.Build.0 = Checked|x64 - {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|x86.ActiveCfg = Checked|x86 - {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|x86.Build.0 = Checked|x86 + {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|x64.ActiveCfg = Debug|Any CPU + {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|x86.ActiveCfg = Debug|Any CPU {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Debug|Any CPU.Build.0 = Debug|Any CPU {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -90,9 +97,9 @@ Global {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Release|x64.Build.0 = Release|Any CPU {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Release|x86.ActiveCfg = Release|Any CPU {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Release|x86.Build.0 = Release|Any CPU - {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|x64.ActiveCfg = Debug|Any CPU - {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|x86.ActiveCfg = Debug|Any CPU + {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Checked|x64.ActiveCfg = Debug|Any CPU + {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Checked|x86.ActiveCfg = Debug|Any CPU {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Debug|Any CPU.Build.0 = Debug|Any CPU {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -105,9 +112,9 @@ Global {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Release|x64.Build.0 = Release|Any CPU {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Release|x86.ActiveCfg = Release|Any CPU {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Release|x86.Build.0 = Release|Any CPU - {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Checked|x64.ActiveCfg = Debug|Any CPU - {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Checked|x86.ActiveCfg = Debug|Any CPU + {1B248B4C-7584-4C04-850A-A50EB592052C}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {1B248B4C-7584-4C04-850A-A50EB592052C}.Checked|x64.ActiveCfg = Debug|Any CPU + {1B248B4C-7584-4C04-850A-A50EB592052C}.Checked|x86.ActiveCfg = Debug|Any CPU {1B248B4C-7584-4C04-850A-A50EB592052C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1B248B4C-7584-4C04-850A-A50EB592052C}.Debug|Any CPU.Build.0 = Debug|Any CPU {1B248B4C-7584-4C04-850A-A50EB592052C}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -120,9 +127,9 @@ Global {1B248B4C-7584-4C04-850A-A50EB592052C}.Release|x64.Build.0 = Release|Any CPU {1B248B4C-7584-4C04-850A-A50EB592052C}.Release|x86.ActiveCfg = Release|Any CPU {1B248B4C-7584-4C04-850A-A50EB592052C}.Release|x86.Build.0 = Release|Any CPU - {1B248B4C-7584-4C04-850A-A50EB592052C}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {1B248B4C-7584-4C04-850A-A50EB592052C}.Checked|x64.ActiveCfg = Debug|Any CPU - {1B248B4C-7584-4C04-850A-A50EB592052C}.Checked|x86.ActiveCfg = Debug|Any CPU + {EF39CC5C-7A3B-40F2-82B6-C1C8BBC3F886}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {EF39CC5C-7A3B-40F2-82B6-C1C8BBC3F886}.Checked|x64.ActiveCfg = Debug|Any CPU + {EF39CC5C-7A3B-40F2-82B6-C1C8BBC3F886}.Checked|x86.ActiveCfg = Debug|Any CPU {EF39CC5C-7A3B-40F2-82B6-C1C8BBC3F886}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {EF39CC5C-7A3B-40F2-82B6-C1C8BBC3F886}.Debug|Any CPU.Build.0 = Debug|Any CPU {EF39CC5C-7A3B-40F2-82B6-C1C8BBC3F886}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -135,9 +142,9 @@ Global {EF39CC5C-7A3B-40F2-82B6-C1C8BBC3F886}.Release|x64.Build.0 = Release|Any CPU {EF39CC5C-7A3B-40F2-82B6-C1C8BBC3F886}.Release|x86.ActiveCfg = Release|Any CPU {EF39CC5C-7A3B-40F2-82B6-C1C8BBC3F886}.Release|x86.Build.0 = Release|Any CPU - {EF39CC5C-7A3B-40F2-82B6-C1C8BBC3F886}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {EF39CC5C-7A3B-40F2-82B6-C1C8BBC3F886}.Checked|x64.ActiveCfg = Debug|Any CPU - {EF39CC5C-7A3B-40F2-82B6-C1C8BBC3F886}.Checked|x86.ActiveCfg = Debug|Any CPU + {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Checked|x64.ActiveCfg = Debug|Any CPU + {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Checked|x86.ActiveCfg = Debug|Any CPU {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Debug|Any CPU.Build.0 = Debug|Any CPU {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -150,9 +157,9 @@ Global {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Release|x64.Build.0 = Release|Any CPU {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Release|x86.ActiveCfg = Release|Any CPU {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Release|x86.Build.0 = Release|Any CPU - {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Checked|x64.ActiveCfg = Debug|Any CPU - {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Checked|x86.ActiveCfg = Debug|Any CPU + {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|x64.ActiveCfg = Debug|Any CPU + {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|x86.ActiveCfg = Debug|Any CPU {768B77B0-EA45-469D-B39E-545EB72F5A43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {768B77B0-EA45-469D-B39E-545EB72F5A43}.Debug|Any CPU.Build.0 = Debug|Any CPU {768B77B0-EA45-469D-B39E-545EB72F5A43}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -165,9 +172,9 @@ Global {768B77B0-EA45-469D-B39E-545EB72F5A43}.Release|x64.Build.0 = Release|Any CPU {768B77B0-EA45-469D-B39E-545EB72F5A43}.Release|x86.ActiveCfg = Release|Any CPU {768B77B0-EA45-469D-B39E-545EB72F5A43}.Release|x86.Build.0 = Release|Any CPU - {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|x64.ActiveCfg = Debug|Any CPU - {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|x86.ActiveCfg = Debug|Any CPU + {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|x64.ActiveCfg = Debug|Any CPU + {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|x86.ActiveCfg = Debug|Any CPU {8671F164-F78C-44FA-93B7-A310F67890FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8671F164-F78C-44FA-93B7-A310F67890FE}.Debug|Any CPU.Build.0 = Debug|Any CPU {8671F164-F78C-44FA-93B7-A310F67890FE}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -180,9 +187,9 @@ Global {8671F164-F78C-44FA-93B7-A310F67890FE}.Release|x64.Build.0 = Release|Any CPU {8671F164-F78C-44FA-93B7-A310F67890FE}.Release|x86.ActiveCfg = Release|Any CPU {8671F164-F78C-44FA-93B7-A310F67890FE}.Release|x86.Build.0 = Release|Any CPU - {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|x64.ActiveCfg = Debug|Any CPU - {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|x86.ActiveCfg = Debug|Any CPU + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|x64.ActiveCfg = Debug|Any CPU + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|x86.ActiveCfg = Debug|Any CPU {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Debug|Any CPU.Build.0 = Debug|Any CPU {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -195,9 +202,9 @@ Global {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Release|x64.Build.0 = Release|Any CPU {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Release|x86.ActiveCfg = Release|Any CPU {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Release|x86.Build.0 = Release|Any CPU - {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|x64.ActiveCfg = Debug|Any CPU - {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|x86.ActiveCfg = Debug|Any CPU + {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|x64.ActiveCfg = Debug|Any CPU + {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|x86.ActiveCfg = Debug|Any CPU {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Debug|Any CPU.Build.0 = Debug|Any CPU {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -210,9 +217,9 @@ Global {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Release|x64.Build.0 = Release|Any CPU {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Release|x86.ActiveCfg = Release|Any CPU {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Release|x86.Build.0 = Release|Any CPU - {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|x64.ActiveCfg = Debug|Any CPU - {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|x86.ActiveCfg = Debug|Any CPU + {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Checked|x64.ActiveCfg = Debug|Any CPU + {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Checked|x86.ActiveCfg = Debug|Any CPU {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Debug|Any CPU.Build.0 = Debug|Any CPU {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -225,9 +232,9 @@ Global {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Release|x64.Build.0 = Release|Any CPU {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Release|x86.ActiveCfg = Release|Any CPU {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Release|x86.Build.0 = Release|Any CPU - {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Checked|x64.ActiveCfg = Debug|Any CPU - {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Checked|x86.ActiveCfg = Debug|Any CPU + {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Checked|x64.ActiveCfg = Debug|Any CPU + {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Checked|x86.ActiveCfg = Debug|Any CPU {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Debug|Any CPU.Build.0 = Debug|Any CPU {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -240,9 +247,9 @@ Global {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Release|x64.Build.0 = Release|Any CPU {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Release|x86.ActiveCfg = Release|Any CPU {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Release|x86.Build.0 = Release|Any CPU - {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Checked|x64.ActiveCfg = Debug|Any CPU - {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Checked|x86.ActiveCfg = Debug|Any CPU + {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|x64.ActiveCfg = Debug|Any CPU + {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|x86.ActiveCfg = Debug|Any CPU {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Debug|Any CPU.Build.0 = Debug|Any CPU {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -255,9 +262,9 @@ Global {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Release|x64.Build.0 = Release|Any CPU {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Release|x86.ActiveCfg = Release|Any CPU {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Release|x86.Build.0 = Release|Any CPU - {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|x64.ActiveCfg = Debug|Any CPU - {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|x86.ActiveCfg = Debug|Any CPU + {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|x64.ActiveCfg = Debug|Any CPU + {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|x86.ActiveCfg = Debug|Any CPU {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Debug|Any CPU.Build.0 = Debug|Any CPU {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -270,9 +277,9 @@ Global {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Release|x64.Build.0 = Release|Any CPU {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Release|x86.ActiveCfg = Release|Any CPU {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Release|x86.Build.0 = Release|Any CPU - {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|x64.ActiveCfg = Debug|Any CPU - {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|x86.ActiveCfg = Debug|Any CPU + {866D295E-424A-4747-9417-CD7746936138}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {866D295E-424A-4747-9417-CD7746936138}.Checked|x64.ActiveCfg = Debug|Any CPU + {866D295E-424A-4747-9417-CD7746936138}.Checked|x86.ActiveCfg = Debug|Any CPU {866D295E-424A-4747-9417-CD7746936138}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {866D295E-424A-4747-9417-CD7746936138}.Debug|Any CPU.Build.0 = Debug|Any CPU {866D295E-424A-4747-9417-CD7746936138}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -285,9 +292,9 @@ Global {866D295E-424A-4747-9417-CD7746936138}.Release|x64.Build.0 = Release|Any CPU {866D295E-424A-4747-9417-CD7746936138}.Release|x86.ActiveCfg = Release|Any CPU {866D295E-424A-4747-9417-CD7746936138}.Release|x86.Build.0 = Release|Any CPU - {866D295E-424A-4747-9417-CD7746936138}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {866D295E-424A-4747-9417-CD7746936138}.Checked|x64.ActiveCfg = Debug|Any CPU - {866D295E-424A-4747-9417-CD7746936138}.Checked|x86.ActiveCfg = Debug|Any CPU + {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|x64.ActiveCfg = Debug|Any CPU + {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|x86.ActiveCfg = Debug|Any CPU {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Debug|Any CPU.Build.0 = Debug|Any CPU {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -300,9 +307,10 @@ Global {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Release|x64.Build.0 = Release|Any CPU {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Release|x86.ActiveCfg = Release|Any CPU {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Release|x86.Build.0 = Release|Any CPU - {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|x64.ActiveCfg = Debug|Any CPU - {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|x86.ActiveCfg = Debug|Any CPU + {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|x64.ActiveCfg = Debug|Any CPU + {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|x86.ActiveCfg = Debug|Any CPU + {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|x86.Build.0 = Debug|Any CPU {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Debug|Any CPU.Build.0 = Debug|Any CPU {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -315,10 +323,6 @@ Global {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Release|x64.Build.0 = Release|Any CPU {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Release|x86.ActiveCfg = Release|Any CPU {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Release|x86.Build.0 = Release|Any CPU - {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|x64.ActiveCfg = Debug|Any CPU - {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|x86.ActiveCfg = Debug|Any CPU - {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|x86.Build.0 = Debug|Any CPU {C3EA0A28-A597-4946-9E08-EBBBFA94BFA5}.Checked|Any CPU.ActiveCfg = Debug|Any CPU {C3EA0A28-A597-4946-9E08-EBBBFA94BFA5}.Checked|Any CPU.Build.0 = Debug|Any CPU {C3EA0A28-A597-4946-9E08-EBBBFA94BFA5}.Checked|x64.ActiveCfg = Debug|Any CPU @@ -379,8 +383,14 @@ Global EndGlobalSection GlobalSection(NestedProjects) = preSolution {94B59BA0-491F-4B59-ADFF-A057EC3EC835} = {B1678CCD-95C8-4419-B9F9-14A03061BE4B} - {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1} = {B1678CCD-95C8-4419-B9F9-14A03061BE4B} {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} + {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A} = {D893B9AA-57C5-49E3-97B1-12CC62D84307} + {1B248B4C-7584-4C04-850A-A50EB592052C} = {E1AEBD5D-AE4E-4F61-B9ED-AEF950B0CC33} + {EF39CC5C-7A3B-40F2-82B6-C1C8BBC3F886} = {D893B9AA-57C5-49E3-97B1-12CC62D84307} + {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40} = {E1AEBD5D-AE4E-4F61-B9ED-AEF950B0CC33} + {768B77B0-EA45-469D-B39E-545EB72F5A43} = {E1AEBD5D-AE4E-4F61-B9ED-AEF950B0CC33} + {8671F164-F78C-44FA-93B7-A310F67890FE} = {D893B9AA-57C5-49E3-97B1-12CC62D84307} + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1} = {B1678CCD-95C8-4419-B9F9-14A03061BE4B} {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} {EA8DBC12-60BC-433E-ABFF-A89DFA795283} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} @@ -388,13 +398,7 @@ Global {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} {866D295E-424A-4747-9417-CD7746936138} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} - {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A} = {D893B9AA-57C5-49E3-97B1-12CC62D84307} - {EF39CC5C-7A3B-40F2-82B6-C1C8BBC3F886} = {D893B9AA-57C5-49E3-97B1-12CC62D84307} - {8671F164-F78C-44FA-93B7-A310F67890FE} = {D893B9AA-57C5-49E3-97B1-12CC62D84307} {0B5FD0C2-367D-4AD6-8001-80AD79B2441C} = {D893B9AA-57C5-49E3-97B1-12CC62D84307} - {1B248B4C-7584-4C04-850A-A50EB592052C} = {E1AEBD5D-AE4E-4F61-B9ED-AEF950B0CC33} - {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40} = {E1AEBD5D-AE4E-4F61-B9ED-AEF950B0CC33} - {768B77B0-EA45-469D-B39E-545EB72F5A43} = {E1AEBD5D-AE4E-4F61-B9ED-AEF950B0CC33} {C3EA0A28-A597-4946-9E08-EBBBFA94BFA5} = {E1AEBD5D-AE4E-4F61-B9ED-AEF950B0CC33} {1D771995-D475-429B-AC31-2B1F618AA45F} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} {3741C833-C364-4269-9B1D-D442055DA7CE} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} @@ -402,4 +406,7 @@ Global GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {D4031401-FEB5-4CCF-91C1-38F5646B2BFD} EndGlobalSection + GlobalSection(SharedMSBuildProjectFiles) = preSolution + ..\System.Private.CoreLib\src\System.Private.CoreLib.Shared.projitems*{94b59ba0-491f-4b59-adff-a057ec3ec835}*SharedItemsImports = 5 + EndGlobalSection EndGlobal diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.csproj b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.csproj index 6b0fb74742372..78eeb0e334fb4 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.csproj +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.csproj @@ -31,6 +31,7 @@ + diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGeneratorHelpers.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGeneratorHelpers.cs new file mode 100644 index 0000000000000..f9f0bf684ff82 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGeneratorHelpers.cs @@ -0,0 +1,54 @@ +// 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.Linq; +using System.Text; +using Microsoft.CodeAnalysis; + +namespace Microsoft.Interop +{ + internal static class ComInterfaceGeneratorHelpers + { + public static MarshallingGeneratorFactoryKey<(TargetFramework, Version)> CreateGeneratorFactory(StubEnvironment env) + { + IMarshallingGeneratorFactory generatorFactory; + + // If we're in a "supported" scenario, then emit a diagnostic as our final fallback. + generatorFactory = new UnsupportedMarshallingFactory(); + + generatorFactory = new NoMarshallingInfoErrorMarshallingFactory(generatorFactory); + + // The presence of System.Runtime.CompilerServices.DisableRuntimeMarshallingAttribute is tied to TFM, + // so we use TFM in the generator factory key instead of the Compilation as the compilation changes on every keystroke. + IAssemblySymbol coreLibraryAssembly = env.Compilation.GetSpecialType(SpecialType.System_Object).ContainingAssembly; + ITypeSymbol? disabledRuntimeMarshallingAttributeType = coreLibraryAssembly.GetTypeByMetadataName(TypeNames.System_Runtime_CompilerServices_DisableRuntimeMarshallingAttribute); + bool runtimeMarshallingDisabled = disabledRuntimeMarshallingAttributeType is not null + && env.Compilation.Assembly.GetAttributes().Any(attr => SymbolEqualityComparer.Default.Equals(attr.AttributeClass, disabledRuntimeMarshallingAttributeType)); + + // Since the char type can go into the P/Invoke signature here, we can only use it when + // runtime marshalling is disabled. + generatorFactory = new CharMarshallingGeneratorFactory(generatorFactory, useBlittableMarshallerForUtf16: runtimeMarshallingDisabled); + + InteropGenerationOptions interopGenerationOptions = new(UseMarshalType: true); + generatorFactory = new MarshalAsMarshallingGeneratorFactory(interopGenerationOptions, generatorFactory); + + IMarshallingGeneratorFactory elementFactory = new AttributedMarshallingModelGeneratorFactory( + // Since the char type in an array will not be part of the P/Invoke signature, we can + // use the regular blittable marshaller in all cases. + new CharMarshallingGeneratorFactory(generatorFactory, useBlittableMarshallerForUtf16: true), + new AttributedMarshallingModelOptions(runtimeMarshallingDisabled, MarshalMode.ElementIn, MarshalMode.ElementRef, MarshalMode.ElementOut)); + // We don't need to include the later generator factories for collection elements + // as the later generator factories only apply to parameters. + generatorFactory = new AttributedMarshallingModelGeneratorFactory( + generatorFactory, + elementFactory, + new AttributedMarshallingModelOptions(runtimeMarshallingDisabled, MarshalMode.ManagedToUnmanagedIn, MarshalMode.ManagedToUnmanagedRef, MarshalMode.ManagedToUnmanagedOut)); + + generatorFactory = new ByValueContentsMarshalKindValidator(generatorFactory); + + return MarshallingGeneratorFactoryKey.Create((env.TargetFramework, env.TargetFrameworkVersion), generatorFactory); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedToNativeVTableMethodGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedToNativeVTableMethodGenerator.cs index ae784ff047d2f..386ab7147c5b2 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedToNativeVTableMethodGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedToNativeVTableMethodGenerator.cs @@ -43,7 +43,8 @@ internal sealed class ManagedToNativeVTableMethodGenerator private readonly ManagedToNativeStubCodeContext _context; public ManagedToNativeVTableMethodGenerator( - StubEnvironment environment, + TargetFramework targetFramework, + Version targetFrameworkVersion, ImmutableArray argTypes, bool setLastError, bool implicitThis, @@ -73,13 +74,13 @@ public ManagedToNativeVTableMethodGenerator( argTypes = newArgTypes.ToImmutableArray(); } - _context = new ManagedToNativeStubCodeContext(environment, ReturnIdentifier, ReturnIdentifier); + _context = new ManagedToNativeStubCodeContext(targetFramework, targetFrameworkVersion, ReturnIdentifier, ReturnIdentifier); _marshallers = new BoundGenerators(argTypes, CreateGenerator); if (_marshallers.ManagedReturnMarshaller.Generator.UsesNativeIdentifier(_marshallers.ManagedReturnMarshaller.TypeInfo, _context)) { // If we need a different native return identifier, then recreate the context with the correct identifier before we generate any code. - _context = new ManagedToNativeStubCodeContext(environment, ReturnIdentifier, $"{ReturnIdentifier}{StubCodeContext.GeneratedNativeIdentifierSuffix}"); + _context = new ManagedToNativeStubCodeContext(targetFramework, targetFrameworkVersion, ReturnIdentifier, $"{ReturnIdentifier}{StubCodeContext.GeneratedNativeIdentifierSuffix}"); } IMarshallingGenerator CreateGenerator(TypePositionInfo p) @@ -90,7 +91,7 @@ IMarshallingGenerator CreateGenerator(TypePositionInfo p) // This check is to help with enabling the source generator for runtime libraries without making each // library directly reference System.Memory and System.Runtime.CompilerServices.Unsafe unless it needs to if (p.MarshallingAttributeInfo is MissingSupportMarshallingInfo - && (environment.TargetFramework == TargetFramework.Net && environment.TargetFrameworkVersion.Major >= 7)) + && (targetFramework == TargetFramework.Net && targetFrameworkVersion.Major >= 7)) { throw new MarshallingNotSupportedException(p, _context); } diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs index 7c51e745b3b54..dc4712924121f 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs @@ -6,8 +6,6 @@ using System.Collections.Immutable; using System.Diagnostics; using System.Linq; -using System.Runtime.InteropServices; -using System.Text; using System.Threading; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; @@ -21,35 +19,27 @@ namespace Microsoft.Interop [Generator] public sealed class VtableIndexStubGenerator : IIncrementalGenerator { + internal readonly record struct CallingConventions(ImmutableArray Syntax) + { + public bool Equals(CallingConventions other) + { + return Syntax.SequenceEqual(other.Syntax, (IEqualityComparer)SyntaxEquivalentComparer.Instance); + } + + public override int GetHashCode() => throw new UnreachableException(); + } + internal sealed record IncrementalStubGenerationContext( - StubEnvironment Environment, SignatureContext SignatureContext, ContainingSyntaxContext ContainingSyntaxContext, ContainingSyntax StubMethodSyntaxTemplate, MethodSignatureDiagnosticLocations DiagnosticLocation, ImmutableArray CallingConvention, VirtualMethodIndexData VtableIndexData, - IMarshallingGeneratorFactory GeneratorFactory, + MarshallingGeneratorFactoryKey<(TargetFramework TargetFramework, Version TargetFrameworkVersion)> GeneratorFactory, ManagedTypeInfo TypeKeyType, ManagedTypeInfo TypeKeyOwner, - ImmutableArray Diagnostics) - { - public bool Equals(IncrementalStubGenerationContext? other) - { - return other is not null - && StubEnvironment.AreCompilationSettingsEqual(Environment, other.Environment) - && SignatureContext.Equals(other.SignatureContext) - && ContainingSyntaxContext.Equals(other.ContainingSyntaxContext) - && VtableIndexData.Equals(other.VtableIndexData) - && CallingConvention.SequenceEqual(other.CallingConvention, (IEqualityComparer)SyntaxEquivalentComparer.Instance) - && Diagnostics.SequenceEqual(other.Diagnostics); - } - - public override int GetHashCode() - { - throw new UnreachableException(); - } - } + ImmutableArray Diagnostics); public static class StepNames { @@ -79,7 +69,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) var methodsWithDiagnostics = attributedMethods.Select(static (data, ct) => { Diagnostic? diagnostic = GetDiagnosticIfInvalidMethodForGeneration(data.Syntax, data.Symbol); - return new { Syntax = data.Syntax, Symbol = data.Symbol, Diagnostic = diagnostic }; + return new { data.Syntax, data.Symbol, Diagnostic = diagnostic }; }); var methodsToGenerate = methodsWithDiagnostics.Where(static data => data.Diagnostic is null); @@ -300,7 +290,7 @@ private static IncrementalStubGenerationContext CalculateStubInformation(MethodD } // Create the stub. - var signatureContext = SignatureContext.Create(symbol, virtualMethodIndexData, environment, generatorDiagnostics, virtualMethodIndexAttr, typeof(VtableIndexStubGenerator).Assembly); + var signatureContext = SignatureContext.Create(symbol, DefaultMarshallingInfoParser.Create(environment, generatorDiagnostics, symbol, virtualMethodIndexData, virtualMethodIndexAttr), environment, typeof(VtableIndexStubGenerator).Assembly); var containingSyntaxContext = new ContainingSyntaxContext(syntax); @@ -322,14 +312,13 @@ private static IncrementalStubGenerationContext CalculateStubInformation(MethodD } return new IncrementalStubGenerationContext( - environment, signatureContext, containingSyntaxContext, methodSyntaxTemplate, new MethodSignatureDiagnosticLocations(syntax), callConv, virtualMethodIndexData, - GetMarshallingGeneratorFactory(environment), + ComInterfaceGeneratorHelpers.CreateGeneratorFactory(environment), typeKeyType, typeKeyOwner, generatorDiagnostics.Diagnostics.ToImmutableArray()); @@ -365,7 +354,8 @@ private static (MemberDeclarationSyntax, ImmutableArray) GenerateMan // Generate stub code var stubGenerator = new ManagedToNativeVTableMethodGenerator( - methodStub.Environment, + methodStub.GeneratorFactory.Key.TargetFramework, + methodStub.GeneratorFactory.Key.TargetFrameworkVersion, methodStub.SignatureContext.ElementTypeInformation, methodStub.VtableIndexData.SetLastError, methodStub.VtableIndexData.ImplicitThisParameter, @@ -373,7 +363,7 @@ private static (MemberDeclarationSyntax, ImmutableArray) GenerateMan { diagnostics.ReportMarshallingNotSupported(methodStub.DiagnosticLocation, elementInfo, ex.NotSupportedDetails); }, - methodStub.GeneratorFactory); + methodStub.GeneratorFactory.GeneratorFactory); BlockSyntax code = stubGenerator.GenerateStubBody( methodStub.VtableIndexData.Index, diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/DefaultMarshallingInfoParser.cs b/src/libraries/System.Runtime.InteropServices/gen/Common/DefaultMarshallingInfoParser.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/DefaultMarshallingInfoParser.cs rename to src/libraries/System.Runtime.InteropServices/gen/Common/DefaultMarshallingInfoParser.cs diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/ConvertToLibraryImportAnalyzer.cs b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/ConvertToLibraryImportAnalyzer.cs index 77855eaee06e4..e2dba4aa0ae18 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/ConvertToLibraryImportAnalyzer.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/ConvertToLibraryImportAnalyzer.cs @@ -95,7 +95,7 @@ private static void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbo bool mayRequireAdditionalWork = diagnostics.AnyDiagnostics; bool anyExplicitlyUnsupportedInfo = false; - var stubCodeContext = new ManagedToNativeStubCodeContext(env, "return", "nativeReturn"); + var stubCodeContext = new ManagedToNativeStubCodeContext(env.TargetFramework, env.TargetFrameworkVersion, "return", "nativeReturn"); var forwarder = new Forwarder(); // We don't actually need the bound generators. We just need them to be attempted to be bound to determine if the generator will be able to bind them. diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs index 70ada65966b06..4f4e826a2d88b 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs @@ -21,36 +21,24 @@ namespace Microsoft.Interop [Generator] public sealed class LibraryImportGenerator : IIncrementalGenerator { + internal readonly record struct ForwardedAttributes(ImmutableArray Syntax) + { + public bool Equals(ForwardedAttributes other) + { + return Syntax.SequenceEqual(other.Syntax, (IEqualityComparer)SyntaxEquivalentComparer.Instance); + } + + public override int GetHashCode() => throw new UnreachableException(); + } internal sealed record IncrementalStubGenerationContext( - StubEnvironment Environment, SignatureContext SignatureContext, ContainingSyntaxContext ContainingSyntaxContext, ContainingSyntax StubMethodSyntaxTemplate, MethodSignatureDiagnosticLocations DiagnosticLocation, - ImmutableArray ForwardedAttributes, + ForwardedAttributes ForwardedAttributes, LibraryImportData LibraryImportData, - MarshallingGeneratorFactoryKey<(TargetFramework, Version, LibraryImportGeneratorOptions)> GeneratorFactoryKey, - ImmutableArray Diagnostics) - { - public bool Equals(IncrementalStubGenerationContext? other) - { - return other is not null - && StubEnvironment.AreCompilationSettingsEqual(Environment, other.Environment) - && SignatureContext.Equals(other.SignatureContext) - && ContainingSyntaxContext.Equals(other.ContainingSyntaxContext) - && StubMethodSyntaxTemplate.Equals(other.StubMethodSyntaxTemplate) - && LibraryImportData.Equals(other.LibraryImportData) - && DiagnosticLocation.Equals(DiagnosticLocation) - && ForwardedAttributes.SequenceEqual(other.ForwardedAttributes, (IEqualityComparer)SyntaxEquivalentComparer.Instance) - && GeneratorFactoryKey.Equals(other.GeneratorFactoryKey) - && Diagnostics.SequenceEqual(other.Diagnostics); - } - - public override int GetHashCode() - { - throw new UnreachableException(); - } - } + MarshallingGeneratorFactoryKey<(TargetFramework TargetFramework, Version Version, LibraryImportGeneratorOptions Options)> GeneratorFactoryKey, + ImmutableArray Diagnostics); public static class StepNames { @@ -318,12 +306,11 @@ private static IncrementalStubGenerationContext CalculateStubInformation( List additionalAttributes = GenerateSyntaxForForwardedAttributes(suppressGCTransitionAttribute, unmanagedCallConvAttribute, defaultDllImportSearchPathsAttribute); return new IncrementalStubGenerationContext( - environment, signatureContext, containingTypeContext, methodSyntaxTemplate, new MethodSignatureDiagnosticLocations(originalSyntax), - additionalAttributes.ToImmutableArray(), + new ForwardedAttributes(additionalAttributes.ToImmutableArray()), libraryImportData, LibraryImportGeneratorHelpers.CreateGeneratorFactory(environment, options), generatorDiagnostics.Diagnostics.ToImmutableArray()); @@ -341,7 +328,8 @@ private static (MemberDeclarationSyntax, ImmutableArray) GenerateSou // Generate stub code var stubGenerator = new PInvokeStubCodeGenerator( - pinvokeStub.Environment, + pinvokeStub.GeneratorFactoryKey.Key.TargetFramework, + pinvokeStub.GeneratorFactoryKey.Key.Version, pinvokeStub.SignatureContext.ElementTypeInformation, pinvokeStub.LibraryImportData.SetLastError && !options.GenerateForwarders, (elementInfo, ex) => @@ -358,7 +346,7 @@ private static (MemberDeclarationSyntax, ImmutableArray) GenerateSou return (PrintForwarderStub(pinvokeStub.StubMethodSyntaxTemplate, !stubGenerator.SupportsTargetFramework, pinvokeStub, diagnostics), pinvokeStub.Diagnostics.AddRange(diagnostics.Diagnostics)); } - ImmutableArray forwardedAttributes = pinvokeStub.ForwardedAttributes; + ImmutableArray forwardedAttributes = pinvokeStub.ForwardedAttributes.Syntax; const string innerPInvokeName = "__PInvoke"; diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.csproj b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.csproj index 9077f4cf523cb..7fff2e5413271 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.csproj +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.csproj @@ -9,7 +9,7 @@ RS2008;$(NoWarn) - cs + cs @@ -26,6 +26,7 @@ + diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/PInvokeStubCodeGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/PInvokeStubCodeGenerator.cs index 66b7c5f2f8544..71cb7e06968bd 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/PInvokeStubCodeGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/PInvokeStubCodeGenerator.cs @@ -4,9 +4,6 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; -using System.Diagnostics; -using System.Linq; -using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; @@ -49,7 +46,8 @@ internal sealed class PInvokeStubCodeGenerator private readonly ManagedToNativeStubCodeContext _context; public PInvokeStubCodeGenerator( - StubEnvironment environment, + TargetFramework targetFramework, + Version targetFrameworkVersion, ImmutableArray argTypes, bool setLastError, Action marshallingNotSupportedCallback, @@ -61,21 +59,21 @@ public PInvokeStubCodeGenerator( // supports target framework value with this value. if (_setLastError) { - SupportsTargetFramework = environment.TargetFramework == TargetFramework.Net - && environment.TargetFrameworkVersion.Major >= 6; + SupportsTargetFramework = targetFramework == TargetFramework.Net + && targetFrameworkVersion.Major >= 6; } else { SupportsTargetFramework = true; } - _context = new ManagedToNativeStubCodeContext(environment, ReturnIdentifier, ReturnIdentifier); + _context = new ManagedToNativeStubCodeContext(targetFramework, targetFrameworkVersion, ReturnIdentifier, ReturnIdentifier); _marshallers = new BoundGenerators(argTypes, CreateGenerator); if (_marshallers.ManagedReturnMarshaller.Generator.UsesNativeIdentifier(_marshallers.ManagedReturnMarshaller.TypeInfo, _context)) { // If we need a different native return identifier, then recreate the context with the correct identifier before we generate any code. - _context = new ManagedToNativeStubCodeContext(environment, ReturnIdentifier, $"{ReturnIdentifier}{StubCodeContext.GeneratedNativeIdentifierSuffix}"); + _context = new ManagedToNativeStubCodeContext(targetFramework, targetFrameworkVersion, ReturnIdentifier, $"{ReturnIdentifier}{StubCodeContext.GeneratedNativeIdentifierSuffix}"); } bool noMarshallingNeeded = true; @@ -84,7 +82,7 @@ public PInvokeStubCodeGenerator( { // Check if marshalling info and generator support the current target framework. SupportsTargetFramework &= generator.TypeInfo.MarshallingAttributeInfo is not MissingSupportMarshallingInfo - && generator.Generator.IsSupported(environment.TargetFramework, environment.TargetFrameworkVersion); + && generator.Generator.IsSupported(targetFramework, targetFrameworkVersion); // Check if generator is either blittable or just a forwarder. noMarshallingNeeded &= generator is { Generator: BlittableMarshaller, TypeInfo.IsByRef: false } diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManagedToNativeStubCodeContext.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManagedToNativeStubCodeContext.cs index 36b59f4600eac..c953e246a55e2 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManagedToNativeStubCodeContext.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManagedToNativeStubCodeContext.cs @@ -2,10 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; -using System.Collections.Generic; using System.Diagnostics; -using System.Text; - namespace Microsoft.Interop { public sealed record ManagedToNativeStubCodeContext : StubCodeContext @@ -22,12 +19,13 @@ public sealed record ManagedToNativeStubCodeContext : StubCodeContext private readonly string _nativeReturnIdentifier; public ManagedToNativeStubCodeContext( - StubEnvironment environment, + TargetFramework targetFramework, + Version targetFrameworkVersion, string returnIdentifier, string nativeReturnIdentifier) { - _framework = environment.TargetFramework; - _frameworkVersion = environment.TargetFrameworkVersion; + _framework = targetFramework; + _frameworkVersion = targetFrameworkVersion; _returnIdentifier = returnIdentifier; _nativeReturnIdentifier = nativeReturnIdentifier; } diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/StubEnvironment.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/StubEnvironment.cs index 268749de6dd6a..769c391b238b4 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/StubEnvironment.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/StubEnvironment.cs @@ -2,18 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Threading; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; namespace Microsoft.Interop { @@ -21,21 +11,5 @@ public sealed record StubEnvironment( Compilation Compilation, TargetFramework TargetFramework, Version TargetFrameworkVersion, - bool ModuleSkipLocalsInit) - { - /// - /// Override for determining if two StubEnvironment instances are - /// equal. This intentionally excludes the Compilation instance - /// since that represents the actual compilation and not just the settings. - /// - /// The first StubEnvironment - /// The second StubEnvironment - /// True if the settings are equal, otherwise false. - public static bool AreCompilationSettingsEqual(StubEnvironment env1, StubEnvironment env2) - { - return env1.TargetFramework == env2.TargetFramework - && env1.TargetFrameworkVersion == env2.TargetFrameworkVersion - && env1.ModuleSkipLocalsInit == env2.ModuleSkipLocalsInit; - } - } + bool ModuleSkipLocalsInit); } diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/IncrementalGenerationTests.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/IncrementalGenerationTests.cs index e116bfe339a6e..06cd100b55212 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/IncrementalGenerationTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/IncrementalGenerationTests.cs @@ -211,5 +211,52 @@ public async Task ChangingMarshallingAttributes_SameStrategy_DoesNotRegenerate() output => Assert.Equal(IncrementalStepRunReason.Unchanged, output.Reason)); }); } + + [Fact] + public async Task GeneratorRun_WithNewCompilation_DoesNotKeepOldCompilationAlive() + { + string source = $"namespace NS{{{CodeSnippets.BasicParametersAndModifiers()}}}"; + + SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(source, new CSharpParseOptions(LanguageVersion.Preview)); + + Compilation comp1 = await TestUtils.CreateCompilation(new[] { syntaxTree }); + + var (reference, driver) = RunTwoGeneratorOnTwoIterativeCompilationsAndReturnFirst(comp1); + + GC.Collect(); + + Assert.False(reference.IsAlive); + GC.KeepAlive(driver); + + static (WeakReference reference, GeneratorDriver driver) RunTwoGeneratorOnTwoIterativeCompilationsAndReturnFirst(Compilation startingCompilation) + { + Compilation comp2 = startingCompilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText("struct NewType {}", new CSharpParseOptions(LanguageVersion.Preview))); + + Microsoft.Interop.LibraryImportGenerator generator = new(); + GeneratorDriver driver = TestUtils.CreateDriver(comp2, null, new[] { generator }, EnableIncrementalTrackingDriverOptions); + + driver = driver.RunGenerators(comp2); + + Compilation comp3 = comp2.AddSyntaxTrees(CSharpSyntaxTree.ParseText("struct NewType2 {}", new CSharpParseOptions(LanguageVersion.Preview))); + + GeneratorDriver driver2 = driver.RunGenerators(comp3); + + // Assert here that we did use the last result and didn't regenerate. + Assert.Collection(driver2.GetRunResult().Results, + result => + { + Assert.Collection(result.TrackedSteps[StepNames.CalculateStubInformation], + step => + { + Assert.Collection(step.Outputs, + output => Assert.Equal(IncrementalStepRunReason.Unchanged, output.Reason)); + }); + }); + + // Return a weak reference to the first edited compilation and the driver from the most recent run. + // The most recent run with comp3 shouldn't keep anything from comp2 alive. + return (new WeakReference(comp2), driver2); + } + } } } From 1d8bd6a3a4a1053dbe81f4202640beb457942a45 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Thu, 29 Sep 2022 14:46:26 -0700 Subject: [PATCH 28/30] Use a wrapper struct to make using elementwise equality for immutable arrays easier. --- .../JSImportGenerator/JSExportGenerator.cs | 6 ++--- .../JSImportGenerator/JSImportGenerator.cs | 6 ++--- .../VtableIndexStubGenerator.cs | 22 +++++----------- .../LibraryImportGenerator.cs | 26 +++++++------------ .../SequenceEqualImmutableArray.cs | 25 ++++++++++++++++++ .../SyntaxEquivalentComparer.cs | 4 --- .../IncrementalGenerationTests.cs | 5 ++-- 7 files changed, 48 insertions(+), 46 deletions(-) create mode 100644 src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/SequenceEqualImmutableArray.cs diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportGenerator.cs index d84440e075087..ab4c93dc48cd2 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportGenerator.cs @@ -23,7 +23,7 @@ internal sealed record IncrementalStubGenerationContext( MethodSignatureDiagnosticLocations DiagnosticLocation, JSExportData JSExportData, MarshallingGeneratorFactoryKey<(TargetFramework TargetFramework, Version TargetFrameworkVersion, JSGeneratorOptions)> GeneratorFactoryKey, - ImmutableArray Diagnostics); + SequenceEqualImmutableArray Diagnostics); public static class StepNames { @@ -200,7 +200,7 @@ private static IncrementalStubGenerationContext CalculateStubInformation( new MethodSignatureDiagnosticLocations(originalSyntax), jsExportData, CreateGeneratorFactory(environment, options), - generatorDiagnostics.Diagnostics.ToImmutableArray()); + new SequenceEqualImmutableArray(generatorDiagnostics.Diagnostics.ToImmutableArray())); } private static MarshallingGeneratorFactoryKey<(TargetFramework, Version, JSGeneratorOptions)> CreateGeneratorFactory(StubEnvironment env, JSGeneratorOptions options) @@ -230,7 +230,7 @@ private static (MemberDeclarationSyntax, ImmutableArray) GenerateSou BlockSyntax wrapper = stubGenerator.GenerateJSExportBody(); BlockSyntax registration = stubGenerator.GenerateJSExportRegistration(); - return (PrintGeneratedSource(incrementalContext.StubMethodSyntaxTemplate, incrementalContext.SignatureContext, incrementalContext.ContainingSyntaxContext, wrapper, registration), incrementalContext.Diagnostics.AddRange(diagnostics.Diagnostics)); + return (PrintGeneratedSource(incrementalContext.StubMethodSyntaxTemplate, incrementalContext.SignatureContext, incrementalContext.ContainingSyntaxContext, wrapper, registration), incrementalContext.Diagnostics.Array.AddRange(diagnostics.Diagnostics)); } private static bool ShouldVisitNode(SyntaxNode syntaxNode) diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportGenerator.cs index 6aed61fe5dc11..4a387419f8128 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportGenerator.cs @@ -25,7 +25,7 @@ internal sealed record IncrementalStubGenerationContext( MethodSignatureDiagnosticLocations DiagnosticLocation, JSImportData JSImportData, MarshallingGeneratorFactoryKey<(TargetFramework TargetFramework, Version TargetFrameworkVersion, JSGeneratorOptions)> GeneratorFactoryKey, - ImmutableArray Diagnostics); + SequenceEqualImmutableArray Diagnostics); public static class StepNames { @@ -211,7 +211,7 @@ private static IncrementalStubGenerationContext CalculateStubInformation( new MethodSignatureDiagnosticLocations(originalSyntax), jsImportData, CreateGeneratorFactory(environment, options), - generatorDiagnostics.Diagnostics.ToImmutableArray()); + new SequenceEqualImmutableArray(generatorDiagnostics.Diagnostics.ToImmutableArray())); } private static MarshallingGeneratorFactoryKey<(TargetFramework, Version, JSGeneratorOptions)> CreateGeneratorFactory(StubEnvironment env, JSGeneratorOptions options) @@ -242,7 +242,7 @@ private static (MemberDeclarationSyntax, ImmutableArray) GenerateSou BlockSyntax code = stubGenerator.GenerateJSImportBody(); - return (PrintGeneratedSource(incrementalContext.StubMethodSyntaxTemplate, incrementalContext.SignatureContext, incrementalContext.ContainingSyntaxContext, code), incrementalContext.Diagnostics.AddRange(diagnostics.Diagnostics)); + return (PrintGeneratedSource(incrementalContext.StubMethodSyntaxTemplate, incrementalContext.SignatureContext, incrementalContext.ContainingSyntaxContext, code), incrementalContext.Diagnostics.Array.AddRange(diagnostics.Diagnostics)); } private static bool ShouldVisitNode(SyntaxNode syntaxNode) diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs index dc4712924121f..29258122a304b 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs @@ -19,27 +19,17 @@ namespace Microsoft.Interop [Generator] public sealed class VtableIndexStubGenerator : IIncrementalGenerator { - internal readonly record struct CallingConventions(ImmutableArray Syntax) - { - public bool Equals(CallingConventions other) - { - return Syntax.SequenceEqual(other.Syntax, (IEqualityComparer)SyntaxEquivalentComparer.Instance); - } - - public override int GetHashCode() => throw new UnreachableException(); - } - internal sealed record IncrementalStubGenerationContext( SignatureContext SignatureContext, ContainingSyntaxContext ContainingSyntaxContext, ContainingSyntax StubMethodSyntaxTemplate, MethodSignatureDiagnosticLocations DiagnosticLocation, - ImmutableArray CallingConvention, + SequenceEqualImmutableArray CallingConvention, VirtualMethodIndexData VtableIndexData, MarshallingGeneratorFactoryKey<(TargetFramework TargetFramework, Version TargetFrameworkVersion)> GeneratorFactory, ManagedTypeInfo TypeKeyType, ManagedTypeInfo TypeKeyOwner, - ImmutableArray Diagnostics); + SequenceEqualImmutableArray Diagnostics); public static class StepNames { @@ -316,12 +306,12 @@ private static IncrementalStubGenerationContext CalculateStubInformation(MethodD containingSyntaxContext, methodSyntaxTemplate, new MethodSignatureDiagnosticLocations(syntax), - callConv, + new SequenceEqualImmutableArray(callConv, SyntaxEquivalentComparer.Instance), virtualMethodIndexData, ComInterfaceGeneratorHelpers.CreateGeneratorFactory(environment), typeKeyType, typeKeyOwner, - generatorDiagnostics.Diagnostics.ToImmutableArray()); + new SequenceEqualImmutableArray(generatorDiagnostics.Diagnostics.ToImmutableArray())); } private static IMarshallingGeneratorFactory GetMarshallingGeneratorFactory(StubEnvironment env) @@ -367,7 +357,7 @@ private static (MemberDeclarationSyntax, ImmutableArray) GenerateMan BlockSyntax code = stubGenerator.GenerateStubBody( methodStub.VtableIndexData.Index, - methodStub.CallingConvention, + methodStub.CallingConvention.Array, methodStub.TypeKeyOwner.Syntax, methodStub.TypeKeyType); @@ -384,7 +374,7 @@ private static (MemberDeclarationSyntax, ImmutableArray) GenerateMan methodStub.ContainingSyntaxContext.ContainingSyntax[0], methodStub.SignatureContext, code)), - methodStub.Diagnostics.AddRange(diagnostics.Diagnostics)); + methodStub.Diagnostics.Array.AddRange(diagnostics.Diagnostics)); } private static bool ShouldVisitNode(SyntaxNode syntaxNode) diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs index 4f4e826a2d88b..88aaa11d82051 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs @@ -21,24 +21,15 @@ namespace Microsoft.Interop [Generator] public sealed class LibraryImportGenerator : IIncrementalGenerator { - internal readonly record struct ForwardedAttributes(ImmutableArray Syntax) - { - public bool Equals(ForwardedAttributes other) - { - return Syntax.SequenceEqual(other.Syntax, (IEqualityComparer)SyntaxEquivalentComparer.Instance); - } - - public override int GetHashCode() => throw new UnreachableException(); - } internal sealed record IncrementalStubGenerationContext( SignatureContext SignatureContext, ContainingSyntaxContext ContainingSyntaxContext, ContainingSyntax StubMethodSyntaxTemplate, MethodSignatureDiagnosticLocations DiagnosticLocation, - ForwardedAttributes ForwardedAttributes, + SequenceEqualImmutableArray ForwardedAttributes, LibraryImportData LibraryImportData, MarshallingGeneratorFactoryKey<(TargetFramework TargetFramework, Version Version, LibraryImportGeneratorOptions Options)> GeneratorFactoryKey, - ImmutableArray Diagnostics); + SequenceEqualImmutableArray Diagnostics); public static class StepNames { @@ -310,10 +301,11 @@ private static IncrementalStubGenerationContext CalculateStubInformation( containingTypeContext, methodSyntaxTemplate, new MethodSignatureDiagnosticLocations(originalSyntax), - new ForwardedAttributes(additionalAttributes.ToImmutableArray()), + new SequenceEqualImmutableArray(additionalAttributes.ToImmutableArray(), SyntaxEquivalentComparer.Instance), libraryImportData, LibraryImportGeneratorHelpers.CreateGeneratorFactory(environment, options), - generatorDiagnostics.Diagnostics.ToImmutableArray()); + new SequenceEqualImmutableArray(generatorDiagnostics.Diagnostics.ToImmutableArray()) + ); } private static (MemberDeclarationSyntax, ImmutableArray) GenerateSource( @@ -323,7 +315,7 @@ private static (MemberDeclarationSyntax, ImmutableArray) GenerateSou var diagnostics = new GeneratorDiagnostics(); if (options.GenerateForwarders) { - return (PrintForwarderStub(pinvokeStub.StubMethodSyntaxTemplate, explicitForwarding: true, pinvokeStub, diagnostics), pinvokeStub.Diagnostics.AddRange(diagnostics.Diagnostics)); + return (PrintForwarderStub(pinvokeStub.StubMethodSyntaxTemplate, explicitForwarding: true, pinvokeStub, diagnostics), pinvokeStub.Diagnostics.Array.AddRange(diagnostics.Diagnostics)); } // Generate stub code @@ -343,10 +335,10 @@ private static (MemberDeclarationSyntax, ImmutableArray) GenerateSou if (stubGenerator.StubIsBasicForwarder || !stubGenerator.SupportsTargetFramework) { - return (PrintForwarderStub(pinvokeStub.StubMethodSyntaxTemplate, !stubGenerator.SupportsTargetFramework, pinvokeStub, diagnostics), pinvokeStub.Diagnostics.AddRange(diagnostics.Diagnostics)); + return (PrintForwarderStub(pinvokeStub.StubMethodSyntaxTemplate, !stubGenerator.SupportsTargetFramework, pinvokeStub, diagnostics), pinvokeStub.Diagnostics.Array.AddRange(diagnostics.Diagnostics)); } - ImmutableArray forwardedAttributes = pinvokeStub.ForwardedAttributes.Syntax; + ImmutableArray forwardedAttributes = pinvokeStub.ForwardedAttributes.Array; const string innerPInvokeName = "__PInvoke"; @@ -367,7 +359,7 @@ private static (MemberDeclarationSyntax, ImmutableArray) GenerateSou dllImport = dllImport.WithLeadingTrivia(Comment("// Local P/Invoke")); code = code.AddStatements(dllImport); - return (pinvokeStub.ContainingSyntaxContext.WrapMemberInContainingSyntaxWithUnsafeModifier(PrintGeneratedSource(pinvokeStub.StubMethodSyntaxTemplate, pinvokeStub.SignatureContext, code)), pinvokeStub.Diagnostics.AddRange(diagnostics.Diagnostics)); + return (pinvokeStub.ContainingSyntaxContext.WrapMemberInContainingSyntaxWithUnsafeModifier(PrintGeneratedSource(pinvokeStub.StubMethodSyntaxTemplate, pinvokeStub.SignatureContext, code)), pinvokeStub.Diagnostics.Array.AddRange(diagnostics.Diagnostics)); } private static MemberDeclarationSyntax PrintForwarderStub(ContainingSyntax userDeclaredMethod, bool explicitForwarding, IncrementalStubGenerationContext stub, GeneratorDiagnostics diagnostics) diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/SequenceEqualImmutableArray.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/SequenceEqualImmutableArray.cs new file mode 100644 index 0000000000000..20d81168d77a6 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/SequenceEqualImmutableArray.cs @@ -0,0 +1,25 @@ +// 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.Collections.Immutable; +using System.Linq; + +namespace Microsoft.Interop +{ + public readonly record struct SequenceEqualImmutableArray(ImmutableArray Array, IEqualityComparer Comparer) + { + public SequenceEqualImmutableArray(ImmutableArray array) + : this(array, EqualityComparer.Default) + { + } + + public bool Equals(SequenceEqualImmutableArray other) + { + return Array.SequenceEqual(other.Array, Comparer); + } + + public override int GetHashCode() => throw new UnreachableException(); + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/SyntaxEquivalentComparer.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/SyntaxEquivalentComparer.cs index e56165393330d..31887788c314c 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/SyntaxEquivalentComparer.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/SyntaxEquivalentComparer.cs @@ -1,9 +1,7 @@ // 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 @@ -12,8 +10,6 @@ public sealed class SyntaxEquivalentComparer : IEqualityComparer, IE { public static readonly SyntaxEquivalentComparer Instance = new(); - private SyntaxEquivalentComparer() { } - public bool Equals(SyntaxNode x, SyntaxNode y) { if ((x is null) != (y is null)) diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/IncrementalGenerationTests.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/IncrementalGenerationTests.cs index 06cd100b55212..a560959d5211f 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/IncrementalGenerationTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/IncrementalGenerationTests.cs @@ -67,11 +67,10 @@ public async Task AppendingUnrelatedSource_DoesNotRegenerateSource() GeneratorDriver driver2 = driver.RunGenerators(comp2); GeneratorRunResult runResult = driver2.GetRunResult().Results[0]; - Assert.Collection(runResult.TrackedSteps[StepNames.CalculateStubInformation], + Assert.Collection(runResult.TrackedSteps[StepNames.GenerateSingleStub], step => { - // The input contains symbols and Compilation objects, so it will always be different. - // However, we validate that the calculated stub information is identical. + // The calculated stub information will differ since we have a new syntax tree for where to report diagnostics. Assert.Collection(step.Outputs, output => Assert.Equal(IncrementalStepRunReason.Unchanged, output.Reason)); }); From d403851bd1dd29e0ab93d79f3bb34fce9b258cfd Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Fri, 7 Oct 2022 14:13:26 -0700 Subject: [PATCH 29/30] Fix build --- .../ComInterfaceGenerator.Unit.Tests/CodeSnippets.cs | 8 ++------ .../LibraryImportGenerator.UnitTests/CodeSnippets.cs | 2 +- .../LibraryImportGenerator.UnitTests/CompileFails.cs | 2 -- .../tests/LibraryImportGenerator.UnitTests/Compiles.cs | 4 ---- .../IncrementalGenerationTests.cs | 1 - 5 files changed, 3 insertions(+), 14 deletions(-) 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 fa15018f69173..383e179504f0a 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 @@ -1,13 +1,9 @@ // 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.Linq; -using System.Text; -using System.Threading.Tasks; +using Microsoft.Interop.UnitTests; -namespace Microsoft.Interop.UnitTests +namespace ComInterfaceGenerator.Unit.Tests { internal partial class CodeSnippets : ICustomMarshallingSignatureTestProvider { diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CodeSnippets.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CodeSnippets.cs index e4f85862c054d..8a919c642312c 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CodeSnippets.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CodeSnippets.cs @@ -4,7 +4,7 @@ using System.Runtime.InteropServices; using Microsoft.Interop.UnitTests; -namespace Microsoft.Interop.UnitTests +namespace LibraryImportGenerator.UnitTests { internal partial class CodeSnippets : ICustomMarshallingSignatureTestProvider { diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CompileFails.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CompileFails.cs index cd4d2061ec9a6..630100e8db932 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CompileFails.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CompileFails.cs @@ -14,8 +14,6 @@ using Microsoft.Interop.UnitTests; using Xunit; -using StringMarshalling = Microsoft.Interop.StringMarshalling; - namespace LibraryImportGenerator.UnitTests { public class CompileFails diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/Compiles.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/Compiles.cs index 190fd06730f17..8acfd9f4a47de 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/Compiles.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/Compiles.cs @@ -5,8 +5,6 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.Interop; -using Microsoft.Interop.UnitTests; using System; using System.Collections.Generic; using System.Linq; @@ -15,8 +13,6 @@ using System.Threading.Tasks; using Xunit; -using StringMarshalling = Microsoft.Interop.StringMarshalling; - namespace LibraryImportGenerator.UnitTests { public class Compiles diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/IncrementalGenerationTests.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/IncrementalGenerationTests.cs index b01cbfdcc8fff..51a0858394400 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/IncrementalGenerationTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/IncrementalGenerationTests.cs @@ -13,7 +13,6 @@ using System.Text; using System.Threading.Tasks; using Xunit; -using Microsoft.Interop.UnitTests; using static Microsoft.Interop.LibraryImportGenerator; namespace LibraryImportGenerator.UnitTests From 1e890d4d7717203a935894a17532f3ba50ee60db Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Mon, 10 Oct 2022 13:51:18 -0700 Subject: [PATCH 30/30] Update the generator entry-point and the project file based on changes that have occured in our policy since this branch was started --- .../ComInterfaceGenerator.csproj | 13 +------------ .../VtableIndexStubGenerator.cs | 19 ++++++------------- 2 files changed, 7 insertions(+), 25 deletions(-) diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.csproj b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.csproj index 78eeb0e334fb4..0a827bce0e97b 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.csproj +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.csproj @@ -4,23 +4,12 @@ Microsoft.Interop.ComInterfaceGenerator netstandard2.0 true - Preview - enable Microsoft.Interop true - true RS2008;$(NoWarn) - - - - false - false - true - https://github.com/dotnet/runtime/tree/main/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator - ComInterfaceGenerator - ComInterfaceGenerator, analyzers + cs diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs index 29258122a304b..0805cef07c7eb 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs @@ -40,19 +40,12 @@ public static class StepNames public void Initialize(IncrementalGeneratorInitializationContext context) { var attributedMethods = context.SyntaxProvider - .CreateSyntaxProvider( - static (node, ct) => ShouldVisitNode(node), - static (context, ct) => - { - MethodDeclarationSyntax syntax = (MethodDeclarationSyntax)context.Node; - if (context.SemanticModel.GetDeclaredSymbol(syntax, ct) is IMethodSymbol methodSymbol - && methodSymbol.GetAttributes().Any(static attribute => attribute.AttributeClass?.ToDisplayString() == TypeNames.VirtualMethodIndexAttribute)) - { - return new { Syntax = syntax, Symbol = methodSymbol }; - } - - return null; - }) + .ForAttributeWithMetadataName( + TypeNames.VirtualMethodIndexAttribute, + static (node, ct) => node is MethodDeclarationSyntax, + static (context, ct) => context.TargetSymbol is IMethodSymbol methodSymbol + ? new { Syntax = (MethodDeclarationSyntax)context.TargetNode, Symbol = methodSymbol } + : null) .Where( static modelData => modelData is not null);