From ffe2f22a59f3487593601f281247fc06725e5bdc Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Wed, 12 May 2021 12:15:11 -0700 Subject: [PATCH 01/12] Move marshalling generators and the marshalling generator infra into it's own assembly for sharing purposes. --- .../DllImportGeneratorOptionsProvider.cs | 4 +- DllImportGenerator/DllImportGenerator.sln | 8 +- .../DllImportGenerator/DllImportGenerator.cs | 2 +- .../DllImportGenerator.csproj | 14 + ...Helper.cs => DllImportGeneratorOptions.cs} | 16 +- .../DllImportGenerator/DllImportStub.cs | 6 +- ...tedDllImportMarshallingGeneratorFactory.cs | 28 ++ .../GeneratorDiagnostics.cs | 45 +-- .../DllImportGenerator/Resources.Designer.cs | 90 ------ .../DllImportGenerator/Resources.resx | 30 -- .../DllImportGenerator/StubCodeGenerator.cs | 17 +- .../DllImportGenerator/TypeNames.cs | 20 +- .../ArrayMarshallingCodeContext.cs | 0 .../IGeneratorDiagnostics.cs | 69 +++++ .../InteropGenerationOptions.cs | 8 + .../LanguageSupport.cs | 10 + .../ManualTypeMarshallingHelper.cs | 2 +- .../Marshalling/BlittableArrayMarshaller.cs | 2 +- .../Marshalling/BlittableMarshaller.cs | 2 +- .../Marshalling/BoolMarshaller.cs | 8 +- .../Marshalling/CharMarshaller.cs | 2 +- ...nditionalStackallocMarshallingGenerator.cs | 2 +- .../Marshalling/CustomNativeTypeMarshaller.cs | 2 +- .../Marshalling/DelegateMarshaller.cs | 2 +- .../Marshalling/Forwarder.cs | 2 +- .../Marshalling/HResultExceptionMarshaller.cs | 2 +- .../Marshalling/MarshallerHelpers.cs | 2 +- .../Marshalling/MarshallingGenerator.cs | 102 +++++++ .../MarshallingGeneratorFactory.cs} | 170 +++-------- .../NonBlittableArrayMarshaller.cs | 2 +- .../Marshalling/SafeHandleMarshaller.cs | 8 +- .../Marshalling/StringMarshaller.Ansi.cs | 2 +- .../StringMarshaller.PlatformDefined.cs | 2 +- .../Marshalling/StringMarshaller.Utf16.cs | 2 +- .../Marshalling/StringMarshaller.Utf8.cs | 2 +- .../MarshallingAttributeInfo.cs | 30 +- .../Microsoft.Interop.SourceGeneration.csproj | 29 ++ .../Resources.Designer.cs | 270 ++++++++++++++++++ .../Resources.resx | 189 ++++++++++++ .../StubCodeContext.cs | 2 +- .../TypeNames.cs | 51 ++++ .../TypePositionInfo.cs | 16 +- .../TypeSymbolExtensions.cs | 2 +- 43 files changed, 894 insertions(+), 380 deletions(-) rename DllImportGenerator/DllImportGenerator/{OptionsHelper.cs => DllImportGeneratorOptions.cs} (70%) create mode 100644 DllImportGenerator/DllImportGenerator/GeneratedDllImportMarshallingGeneratorFactory.cs rename DllImportGenerator/{DllImportGenerator => Microsoft.Interop.SourceGeneration}/ArrayMarshallingCodeContext.cs (100%) create mode 100644 DllImportGenerator/Microsoft.Interop.SourceGeneration/IGeneratorDiagnostics.cs create mode 100644 DllImportGenerator/Microsoft.Interop.SourceGeneration/InteropGenerationOptions.cs create mode 100644 DllImportGenerator/Microsoft.Interop.SourceGeneration/LanguageSupport.cs rename DllImportGenerator/{DllImportGenerator => Microsoft.Interop.SourceGeneration}/ManualTypeMarshallingHelper.cs (98%) rename DllImportGenerator/{DllImportGenerator => Microsoft.Interop.SourceGeneration}/Marshalling/BlittableArrayMarshaller.cs (99%) rename DllImportGenerator/{DllImportGenerator => Microsoft.Interop.SourceGeneration}/Marshalling/BlittableMarshaller.cs (98%) rename DllImportGenerator/{DllImportGenerator => Microsoft.Interop.SourceGeneration}/Marshalling/BoolMarshaller.cs (95%) rename DllImportGenerator/{DllImportGenerator => Microsoft.Interop.SourceGeneration}/Marshalling/CharMarshaller.cs (97%) rename DllImportGenerator/{DllImportGenerator => Microsoft.Interop.SourceGeneration}/Marshalling/ConditionalStackallocMarshallingGenerator.cs (99%) rename DllImportGenerator/{DllImportGenerator => Microsoft.Interop.SourceGeneration}/Marshalling/CustomNativeTypeMarshaller.cs (99%) rename DllImportGenerator/{DllImportGenerator => Microsoft.Interop.SourceGeneration}/Marshalling/DelegateMarshaller.cs (98%) rename DllImportGenerator/{DllImportGenerator => Microsoft.Interop.SourceGeneration}/Marshalling/Forwarder.cs (95%) rename DllImportGenerator/{DllImportGenerator => Microsoft.Interop.SourceGeneration}/Marshalling/HResultExceptionMarshaller.cs (96%) rename DllImportGenerator/{DllImportGenerator => Microsoft.Interop.SourceGeneration}/Marshalling/MarshallerHelpers.cs (99%) create mode 100644 DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGenerator.cs rename DllImportGenerator/{DllImportGenerator/Marshalling/MarshallingGenerator.cs => Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGeneratorFactory.cs} (74%) rename DllImportGenerator/{DllImportGenerator => Microsoft.Interop.SourceGeneration}/Marshalling/NonBlittableArrayMarshaller.cs (99%) rename DllImportGenerator/{DllImportGenerator => Microsoft.Interop.SourceGeneration}/Marshalling/SafeHandleMarshaller.cs (98%) rename DllImportGenerator/{DllImportGenerator => Microsoft.Interop.SourceGeneration}/Marshalling/StringMarshaller.Ansi.cs (98%) rename DllImportGenerator/{DllImportGenerator => Microsoft.Interop.SourceGeneration}/Marshalling/StringMarshaller.PlatformDefined.cs (98%) rename DllImportGenerator/{DllImportGenerator => Microsoft.Interop.SourceGeneration}/Marshalling/StringMarshaller.Utf16.cs (99%) rename DllImportGenerator/{DllImportGenerator => Microsoft.Interop.SourceGeneration}/Marshalling/StringMarshaller.Utf8.cs (99%) rename DllImportGenerator/{DllImportGenerator => Microsoft.Interop.SourceGeneration}/MarshallingAttributeInfo.cs (74%) create mode 100644 DllImportGenerator/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj create mode 100644 DllImportGenerator/Microsoft.Interop.SourceGeneration/Resources.Designer.cs create mode 100644 DllImportGenerator/Microsoft.Interop.SourceGeneration/Resources.resx rename DllImportGenerator/{DllImportGenerator => Microsoft.Interop.SourceGeneration}/StubCodeContext.cs (98%) create mode 100644 DllImportGenerator/Microsoft.Interop.SourceGeneration/TypeNames.cs rename DllImportGenerator/{DllImportGenerator => Microsoft.Interop.SourceGeneration}/TypePositionInfo.cs (96%) rename DllImportGenerator/{DllImportGenerator => Microsoft.Interop.SourceGeneration}/TypeSymbolExtensions.cs (99%) diff --git a/DllImportGenerator/DllImportGenerator.UnitTests/DllImportGeneratorOptionsProvider.cs b/DllImportGenerator/DllImportGenerator.UnitTests/DllImportGeneratorOptionsProvider.cs index a774bd2ef353..221c4803efb5 100644 --- a/DllImportGenerator/DllImportGenerator.UnitTests/DllImportGeneratorOptionsProvider.cs +++ b/DllImportGenerator/DllImportGenerator.UnitTests/DllImportGeneratorOptionsProvider.cs @@ -42,11 +42,11 @@ public override bool TryGetValue(string key, [NotNullWhen(true)] out string? val { switch (key) { - case OptionsHelper.UseMarshalTypeOption: + case DllImportGeneratorOptions.UseMarshalTypeOption: value = _useMarshalType.ToString(); return true; - case OptionsHelper.GenerateForwardersOption: + case DllImportGeneratorOptions.GenerateForwardersOption: value = _generateForwarders.ToString(); return true; diff --git a/DllImportGenerator/DllImportGenerator.sln b/DllImportGenerator/DllImportGenerator.sln index d1ab231d1f0c..79455991304f 100644 --- a/DllImportGenerator/DllImportGenerator.sln +++ b/DllImportGenerator/DllImportGenerator.sln @@ -25,10 +25,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SharedTypes", "TestAssets\S EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TestAssets", "TestAssets", "{C7134A89-8852-4FBE-B426-EFE007C4A819}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Benchmarks", "Benchmarks\Benchmarks.csproj", "{0914590B-C47A-4754-A7BE-E4CD843A92E4}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Benchmarks", "Benchmarks\Benchmarks.csproj", "{0914590B-C47A-4754-A7BE-E4CD843A92E4}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DllImportGenerator.Vsix", "DllImportGenerator.Vsix\DllImportGenerator.Vsix.csproj", "{F9215CDD-7B47-4C17-9166-0BE5066CA6BB}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Interop.SourceGeneration", "Microsoft.Interop.SourceGeneration\Microsoft.Interop.SourceGeneration.csproj", "{03FAE24C-728D-419C-B6EC-5C7AE8C45705}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -79,6 +81,10 @@ Global {F9215CDD-7B47-4C17-9166-0BE5066CA6BB}.Debug|Any CPU.Build.0 = Debug|Any CPU {F9215CDD-7B47-4C17-9166-0BE5066CA6BB}.Release|Any CPU.ActiveCfg = Release|Any CPU {F9215CDD-7B47-4C17-9166-0BE5066CA6BB}.Release|Any CPU.Build.0 = Release|Any CPU + {03FAE24C-728D-419C-B6EC-5C7AE8C45705}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {03FAE24C-728D-419C-B6EC-5C7AE8C45705}.Debug|Any CPU.Build.0 = Debug|Any CPU + {03FAE24C-728D-419C-B6EC-5C7AE8C45705}.Release|Any CPU.ActiveCfg = Release|Any CPU + {03FAE24C-728D-419C-B6EC-5C7AE8C45705}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/DllImportGenerator/DllImportGenerator/DllImportGenerator.cs b/DllImportGenerator/DllImportGenerator/DllImportGenerator.cs index c1f94784456d..ddc0cf960118 100644 --- a/DllImportGenerator/DllImportGenerator/DllImportGenerator.cs +++ b/DllImportGenerator/DllImportGenerator/DllImportGenerator.cs @@ -58,7 +58,7 @@ public void Execute(GeneratorExecutionContext context) generatorDiagnostics.ReportTargetFrameworkNotSupported(MinimumSupportedFrameworkVersion); } - var env = new StubEnvironment(context.Compilation, isSupported, targetFrameworkVersion, context.AnalyzerConfigOptions.GlobalOptions); + var env = new StubEnvironment(context.Compilation, isSupported, targetFrameworkVersion, new DllImportGeneratorOptions(context.AnalyzerConfigOptions.GlobalOptions)); var generatedDllImports = new StringBuilder(); foreach (SyntaxReference synRef in synRec.Methods) { diff --git a/DllImportGenerator/DllImportGenerator/DllImportGenerator.csproj b/DllImportGenerator/DllImportGenerator/DllImportGenerator.csproj index dbc6bd335afe..3eddc59deb03 100644 --- a/DllImportGenerator/DllImportGenerator/DllImportGenerator.csproj +++ b/DllImportGenerator/DllImportGenerator/DllImportGenerator.csproj @@ -42,6 +42,10 @@ + + + + True @@ -57,4 +61,14 @@ + + + + + + + + + + diff --git a/DllImportGenerator/DllImportGenerator/OptionsHelper.cs b/DllImportGenerator/DllImportGenerator/DllImportGeneratorOptions.cs similarity index 70% rename from DllImportGenerator/DllImportGenerator/OptionsHelper.cs rename to DllImportGenerator/DllImportGenerator/DllImportGeneratorOptions.cs index 39f2fdc80c1e..5138c8169889 100644 --- a/DllImportGenerator/DllImportGenerator/OptionsHelper.cs +++ b/DllImportGenerator/DllImportGenerator/DllImportGeneratorOptions.cs @@ -1,13 +1,17 @@ -using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Runtime.InteropServices; namespace Microsoft.Interop { - public static class OptionsHelper + record DllImportGeneratorOptions(bool GenerateForwarders, bool UseMarshalType) : InteropGenerationOptions(UseMarshalType) + { + public DllImportGeneratorOptions(AnalyzerConfigOptions options) + : this(options.GenerateForwarders(), options.UseMarshalType()) + { + + } + } + + internal static class OptionsHelper { public const string UseMarshalTypeOption = "build_property.DllImportGenerator_UseMarshalType"; public const string GenerateForwardersOption = "build_property.DllImportGenerator_GenerateForwarders"; diff --git a/DllImportGenerator/DllImportGenerator/DllImportStub.cs b/DllImportGenerator/DllImportGenerator/DllImportStub.cs index cff9d7f41d83..06fe53554d5d 100644 --- a/DllImportGenerator/DllImportGenerator/DllImportStub.cs +++ b/DllImportGenerator/DllImportGenerator/DllImportStub.cs @@ -15,7 +15,7 @@ internal record StubEnvironment( Compilation Compilation, bool SupportedTargetFramework, Version TargetFrameworkVersion, - AnalyzerConfigOptions Options); + DllImportGeneratorOptions Options); internal class DllImportStub { @@ -181,7 +181,7 @@ public static DllImportStub Create( var managedRetTypeInfo = retTypeInfo; // Do not manually handle PreserveSig when generating forwarders. // We want the runtime to handle everything. - if (!dllImportData.PreserveSig && !env.Options.GenerateForwarders()) + if (!dllImportData.PreserveSig && !env.Options.GenerateForwarders) { // Create type info for native HRESULT return retTypeInfo = TypePositionInfo.CreateForType(env.Compilation.GetSpecialType(SpecialType.System_Int32), NoMarshallingInfo.Instance); @@ -207,7 +207,7 @@ public static DllImportStub Create( } // Generate stub code - var stubGenerator = new StubCodeGenerator(method, dllImportData, paramsTypeInfo, retTypeInfo, diagnostics, env.Options); + var stubGenerator = new StubCodeGenerator(method, dllImportData, paramsTypeInfo, retTypeInfo, diagnostics, env.Options, new GeneratedDllImportMarshallingGeneratorFactory()); var code = stubGenerator.GenerateSyntax(); var additionalAttrs = new List(); diff --git a/DllImportGenerator/DllImportGenerator/GeneratedDllImportMarshallingGeneratorFactory.cs b/DllImportGenerator/DllImportGenerator/GeneratedDllImportMarshallingGeneratorFactory.cs new file mode 100644 index 000000000000..9865a3bc287a --- /dev/null +++ b/DllImportGenerator/DllImportGenerator/GeneratedDllImportMarshallingGeneratorFactory.cs @@ -0,0 +1,28 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Microsoft.Interop +{ + class GeneratedDllImportMarshallingGeneratorFactory : DefaultMarshallingGeneratorFactory + { + protected override IMarshallingGenerator CreateCore(TypePositionInfo info, StubCodeContext context, DllImportGeneratorOptions options) + { + if (options.GenerateForwarders) + { + return Forwarder; + } + + if (info.IsNativeReturnPosition && !info.IsManagedReturnPosition) + { + // Use marshaller for native HRESULT return / exception throwing + System.Diagnostics.Debug.Assert(info.ManagedType.SpecialType == SpecialType.System_Int32); + return HResultException; + } + + return base.CreateCore(info, context, options); + } + } +} diff --git a/DllImportGenerator/DllImportGenerator/GeneratorDiagnostics.cs b/DllImportGenerator/DllImportGenerator/GeneratorDiagnostics.cs index 9c5d7952fa6b..6a103ccc71d4 100644 --- a/DllImportGenerator/DllImportGenerator/GeneratorDiagnostics.cs +++ b/DllImportGenerator/DllImportGenerator/GeneratorDiagnostics.cs @@ -1,51 +1,16 @@ -using System; +using Microsoft.CodeAnalysis; +using System; using System.Collections.Generic; using System.Diagnostics; -using System.Linq; - -using Microsoft.CodeAnalysis; +using System.Text; namespace Microsoft.Interop { - internal static class DiagnosticExtensions - { - public static Diagnostic CreateDiagnostic( - this ISymbol symbol, - DiagnosticDescriptor descriptor, - params object[] args) - { - IEnumerable locationsInSource = symbol.Locations.Where(l => l.IsInSource); - if (!locationsInSource.Any()) - return Diagnostic.Create(descriptor, Location.None, args); - - return Diagnostic.Create( - descriptor, - location: locationsInSource.First(), - additionalLocations: locationsInSource.Skip(1), - messageArgs: args); - } - - public static Diagnostic CreateDiagnostic( - this AttributeData attributeData, - DiagnosticDescriptor descriptor, - params object[] args) - { - SyntaxReference? syntaxReference = attributeData.ApplicationSyntaxReference; - Location location = syntaxReference is not null - ? syntaxReference.GetSyntax().GetLocation() - : Location.None; - - return Diagnostic.Create( - descriptor, - location: location.IsInSource ? location : Location.None, - messageArgs: args); - } - } /// /// Class for reporting diagnostics in the DLL import generator /// - public class GeneratorDiagnostics + public class GeneratorDiagnostics : IGeneratorDiagnostics { public class Ids { @@ -188,7 +153,7 @@ public void ReportConfigurationNotSupported( /// Method with the parameter/return /// Type info for the parameter/return /// [Optional] Specific reason for lack of support - internal void ReportMarshallingNotSupported( + public void ReportMarshallingNotSupported( IMethodSymbol method, TypePositionInfo info, string? notSupportedDetails) diff --git a/DllImportGenerator/DllImportGenerator/Resources.Designer.cs b/DllImportGenerator/DllImportGenerator/Resources.Designer.cs index 87fac1a3e0ff..f56f117d8b32 100644 --- a/DllImportGenerator/DllImportGenerator/Resources.Designer.cs +++ b/DllImportGenerator/DllImportGenerator/Resources.Designer.cs @@ -60,33 +60,6 @@ internal Resources() { } } - /// - /// Looks up a localized string similar to Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute'.. - /// - internal static string ArraySizeMustBeSpecified { - get { - return ResourceManager.GetString("ArraySizeMustBeSpecified", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The 'SizeParamIndex' value in the 'MarshalAsAttribute' is out of range.. - /// - internal static string ArraySizeParamIndexOutOfRange { - get { - return ResourceManager.GetString("ArraySizeParamIndexOutOfRange", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The specified array size parameter for an array must be an integer type.. - /// - internal static string ArraySizeParamTypeMustBeIntegral { - get { - return ResourceManager.GetString("ArraySizeParamTypeMustBeIntegral", resourceCulture); - } - } - /// /// Looks up a localized string similar to A type marked with 'BlittableTypeAttribute' must be blittable.. /// @@ -312,51 +285,6 @@ internal static string GetPinnableReferenceShouldSupportAllocatingMarshallingFal } } - /// - /// Looks up a localized string similar to The '[In]' attribute is not supported unless the '[Out]' attribute is also used. The behavior of the '[In]' attribute without the '[Out]' attribute is the same as the default behavior.. - /// - internal static string InAttributeNotSupportedWithoutOut { - get { - return ResourceManager.GetString("InAttributeNotSupportedWithoutOut", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The '[In]' and '[Out]' attributes are unsupported on parameters passed by reference. Use the 'in', 'ref', or 'out' keywords instead.. - /// - internal static string InOutAttributeByRefNotSupported { - get { - return ResourceManager.GetString("InOutAttributeByRefNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The provided '[In]' and '[Out]' attributes on this parameter are unsupported on this parameter.. - /// - internal static string InOutAttributeMarshalerNotSupported { - get { - return ResourceManager.GetString("InOutAttributeMarshalerNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Marshalling char with 'CharSet.{0}' is not supported. Instead, manually convert the char type to the desired byte representation and pass to the source-generated P/Invoke.. - /// - internal static string MarshallingCharAsSpecifiedCharSetNotSupported { - get { - return ResourceManager.GetString("MarshallingCharAsSpecifiedCharSetNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Marshalling string or char without explicit marshalling information is not supported. Specify either 'GeneratedDllImportAttribute.CharSet' or 'MarshalAsAttribute'.. - /// - internal static string MarshallingStringOrCharAsUndefinedNotSupported { - get { - return ResourceManager.GetString("MarshallingStringOrCharAsUndefinedNotSupported", resourceCulture); - } - } - /// /// Looks up a localized string similar to The native type '{0}' must be a closed generic so the emitted code can use a specific instantiation.. /// @@ -447,24 +375,6 @@ internal static string NativeTypeMustHaveRequiredShapeMessage { } } - /// - /// Looks up a localized string similar to The '[Out]' attribute is only supported on array parameters.. - /// - internal static string OutByValueNotSupportedDescription { - get { - return ResourceManager.GetString("OutByValueNotSupportedDescription", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The '[Out]' attribute is not supported on the '{0}' parameter.. - /// - internal static string OutByValueNotSupportedMessage { - get { - return ResourceManager.GetString("OutByValueNotSupportedMessage", resourceCulture); - } - } - /// /// Looks up a localized string similar to The 'Value' property must not be a 'ref' or 'readonly ref' property.. /// diff --git a/DllImportGenerator/DllImportGenerator/Resources.resx b/DllImportGenerator/DllImportGenerator/Resources.resx index f66d2945ad7a..a19f3ceb0296 100644 --- a/DllImportGenerator/DllImportGenerator/Resources.resx +++ b/DllImportGenerator/DllImportGenerator/Resources.resx @@ -117,15 +117,6 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute'. - - - The 'SizeParamIndex' value in the 'MarshalAsAttribute' is out of range. - - - The specified array size parameter for an array must be an integer type. - A type marked with 'BlittableTypeAttribute' must be blittable. @@ -202,21 +193,6 @@ Type '{0}' has a 'GetPinnableReference' method but its native type does not support marshalling in scenarios where pinning is impossible - - The '[In]' attribute is not supported unless the '[Out]' attribute is also used. The behavior of the '[In]' attribute without the '[Out]' attribute is the same as the default behavior. - - - The '[In]' and '[Out]' attributes are unsupported on parameters passed by reference. Use the 'in', 'ref', or 'out' keywords instead. - - - The provided '[In]' and '[Out]' attributes on this parameter are unsupported on this parameter. - - - Marshalling char with 'CharSet.{0}' is not supported. Instead, manually convert the char type to the desired byte representation and pass to the source-generated P/Invoke. - - - Marshalling string or char without explicit marshalling information is not supported. Specify either 'GeneratedDllImportAttribute.CharSet' or 'MarshalAsAttribute'. - The native type '{0}' must be a closed generic so the emitted code can use a specific instantiation. @@ -247,12 +223,6 @@ The native type '{0}' must be a value type and have a constructor that takes one parameter of type '{1}' or a parameterless instance method named 'ToManaged' that returns '{1}' - - The '[Out]' attribute is only supported on array parameters. - - - The '[Out]' attribute is not supported on the '{0}' parameter. - The 'Value' property must not be a 'ref' or 'readonly ref' property. diff --git a/DllImportGenerator/DllImportGenerator/StubCodeGenerator.cs b/DllImportGenerator/DllImportGenerator/StubCodeGenerator.cs index ea5995414f89..320f91783098 100644 --- a/DllImportGenerator/DllImportGenerator/StubCodeGenerator.cs +++ b/DllImportGenerator/DllImportGenerator/StubCodeGenerator.cs @@ -49,7 +49,7 @@ internal sealed class StubCodeGenerator : StubCodeContext }; private readonly GeneratorDiagnostics diagnostics; - private readonly AnalyzerConfigOptions options; + private readonly DllImportGeneratorOptions options; private readonly IMethodSymbol stubMethod; private readonly DllImportStub.GeneratedDllImportData dllImportData; private readonly IEnumerable paramsTypeInfo; @@ -62,7 +62,8 @@ public StubCodeGenerator( IEnumerable paramsTypeInfo, TypePositionInfo retTypeInfo, GeneratorDiagnostics generatorDiagnostics, - AnalyzerConfigOptions options) + DllImportGeneratorOptions options, + IMarshallingGeneratorFactory generatorFactory) { Debug.Assert(retTypeInfo.IsNativeReturnPosition); @@ -82,12 +83,12 @@ public StubCodeGenerator( { try { - return (p, MarshallingGenerators.Create(p, this, options)); + return (p, generatorFactory.Create(p, this, options)); } catch (MarshallingNotSupportedException e) { this.diagnostics.ReportMarshallingNotSupported(this.stubMethod, p, e.NotSupportedDetails); - return (p, MarshallingGenerators.Forwarder); + return (p, new Forwarder()); } } } @@ -179,7 +180,7 @@ public BlockSyntax GenerateSyntax() // Do not manually handle SetLastError when generating forwarders. // We want the runtime to handle everything. - if (this.dllImportData.SetLastError && !options.GenerateForwarders()) + if (this.dllImportData.SetLastError && !options.GenerateForwarders) { // Declare variable for last error setupStatements.Add(MarshallerHelpers.DeclareWithDefault( @@ -254,7 +255,7 @@ public BlockSyntax GenerateSyntax() // Do not manually handle SetLastError when generating forwarders. // We want the runtime to handle everything. - if (this.dllImportData.SetLastError && !options.GenerateForwarders()) + if (this.dllImportData.SetLastError && !options.GenerateForwarders) { // Marshal.SetLastSystemError(0); var clearLastError = ExpressionStatement( @@ -319,7 +320,7 @@ public BlockSyntax GenerateSyntax() allStatements.AddRange(tryStatements); } - if (this.dllImportData.SetLastError && !options.GenerateForwarders()) + if (this.dllImportData.SetLastError && !options.GenerateForwarders) { // Marshal.SetLastPInvokeError(); allStatements.Add(ExpressionStatement( @@ -496,7 +497,7 @@ DllImportStub.GeneratedDllImportData GetTargetDllImportDataFromStubData() // https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.dllimportattribute.setlasterror // If SetLastError=true (default is false), the P/Invoke stub gets/caches the last error after invoking the native function. & ~DllImportStub.DllImportMember.SetLastError; - if (options.GenerateForwarders()) + if (options.GenerateForwarders) { membersToForward = DllImportStub.DllImportMember.All; } diff --git a/DllImportGenerator/DllImportGenerator/TypeNames.cs b/DllImportGenerator/DllImportGenerator/TypeNames.cs index 509969a05230..58bd2803c42b 100644 --- a/DllImportGenerator/DllImportGenerator/TypeNames.cs +++ b/DllImportGenerator/DllImportGenerator/TypeNames.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Text; using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.Interop; namespace Microsoft.Interop { @@ -22,29 +23,10 @@ static class TypeNames public const string System_Span_Metadata = "System.Span`1"; public const string System_Span = "System.Span"; - public const string System_Activator = "System.Activator"; - public const string System_Runtime_InteropServices_StructLayoutAttribute = "System.Runtime.InteropServices.StructLayoutAttribute"; - public const string System_Runtime_InteropServices_MarshalAsAttribute = "System.Runtime.InteropServices.MarshalAsAttribute"; - public const string System_Runtime_InteropServices_Marshal = "System.Runtime.InteropServices.Marshal"; - private const string System_Runtime_InteropServices_MarshalEx = "System.Runtime.InteropServices.MarshalEx"; - - public static string MarshalEx(AnalyzerConfigOptions options) - { - return options.UseMarshalType() ? System_Runtime_InteropServices_Marshal : System_Runtime_InteropServices_MarshalEx; - } - - public const string System_Runtime_InteropServices_MemoryMarshal = "System.Runtime.InteropServices.MemoryMarshal"; - - public const string System_Runtime_InteropServices_SafeHandle = "System.Runtime.InteropServices.SafeHandle"; - - public const string System_Runtime_InteropServices_OutAttribute = "System.Runtime.InteropServices.OutAttribute"; - - public const string System_Runtime_InteropServices_InAttribute = "System.Runtime.InteropServices.InAttribute"; - public const string System_Runtime_CompilerServices_SkipLocalsInitAttribute = "System.Runtime.CompilerServices.SkipLocalsInitAttribute"; } } diff --git a/DllImportGenerator/DllImportGenerator/ArrayMarshallingCodeContext.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/ArrayMarshallingCodeContext.cs similarity index 100% rename from DllImportGenerator/DllImportGenerator/ArrayMarshallingCodeContext.cs rename to DllImportGenerator/Microsoft.Interop.SourceGeneration/ArrayMarshallingCodeContext.cs diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/IGeneratorDiagnostics.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/IGeneratorDiagnostics.cs new file mode 100644 index 000000000000..435ab7d3a4a7 --- /dev/null +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/IGeneratorDiagnostics.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; + +using Microsoft.CodeAnalysis; + +namespace Microsoft.Interop +{ + public static class DiagnosticExtensions + { + public static Diagnostic CreateDiagnostic( + this ISymbol symbol, + DiagnosticDescriptor descriptor, + params object[] args) + { + IEnumerable locationsInSource = symbol.Locations.Where(l => l.IsInSource); + if (!locationsInSource.Any()) + return Diagnostic.Create(descriptor, Location.None, args); + + return Diagnostic.Create( + descriptor, + location: locationsInSource.First(), + additionalLocations: locationsInSource.Skip(1), + messageArgs: args); + } + + public static Diagnostic CreateDiagnostic( + this AttributeData attributeData, + DiagnosticDescriptor descriptor, + params object[] args) + { + SyntaxReference? syntaxReference = attributeData.ApplicationSyntaxReference; + Location location = syntaxReference is not null + ? syntaxReference.GetSyntax().GetLocation() + : Location.None; + + return Diagnostic.Create( + descriptor, + location: location.IsInSource ? location : Location.None, + messageArgs: args); + } + } + + public interface IGeneratorDiagnostics + { + /// + /// 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 + void ReportMarshallingNotSupported( + IMethodSymbol method, + TypePositionInfo info, + string? notSupportedDetails); + + /// + /// 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 + void ReportConfigurationNotSupported( + AttributeData attributeData, + string configurationName, + string? unsupportedValue = null); + } +} diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/InteropGenerationOptions.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/InteropGenerationOptions.cs new file mode 100644 index 000000000000..d65ea4cb67ee --- /dev/null +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/InteropGenerationOptions.cs @@ -0,0 +1,8 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Microsoft.Interop +{ + public record InteropGenerationOptions(bool UseMarshalType); +} diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/LanguageSupport.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/LanguageSupport.cs new file mode 100644 index 000000000000..ddf2c4203111 --- /dev/null +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/LanguageSupport.cs @@ -0,0 +1,10 @@ +// 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 + {} +} \ No newline at end of file diff --git a/DllImportGenerator/DllImportGenerator/ManualTypeMarshallingHelper.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/ManualTypeMarshallingHelper.cs similarity index 98% rename from DllImportGenerator/DllImportGenerator/ManualTypeMarshallingHelper.cs rename to DllImportGenerator/Microsoft.Interop.SourceGeneration/ManualTypeMarshallingHelper.cs index eb825f1c7a61..7f86b833665c 100644 --- a/DllImportGenerator/DllImportGenerator/ManualTypeMarshallingHelper.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/ManualTypeMarshallingHelper.cs @@ -4,7 +4,7 @@ namespace Microsoft.Interop { - static class ManualTypeMarshallingHelper + public static class ManualTypeMarshallingHelper { public const string ValuePropertyName = "Value"; public const string GetPinnableReferenceName = "GetPinnableReference"; diff --git a/DllImportGenerator/DllImportGenerator/Marshalling/BlittableArrayMarshaller.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/BlittableArrayMarshaller.cs similarity index 99% rename from DllImportGenerator/DllImportGenerator/Marshalling/BlittableArrayMarshaller.cs rename to DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/BlittableArrayMarshaller.cs index cd42a96d8324..a1bba95c3932 100644 --- a/DllImportGenerator/DllImportGenerator/Marshalling/BlittableArrayMarshaller.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/BlittableArrayMarshaller.cs @@ -7,7 +7,7 @@ namespace Microsoft.Interop { - internal class BlittableArrayMarshaller : ConditionalStackallocMarshallingGenerator + public sealed class BlittableArrayMarshaller : ConditionalStackallocMarshallingGenerator { /// /// Stack-alloc threshold set to 256 bytes to enable small arrays to be passed on the stack. diff --git a/DllImportGenerator/DllImportGenerator/Marshalling/BlittableMarshaller.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/BlittableMarshaller.cs similarity index 98% rename from DllImportGenerator/DllImportGenerator/Marshalling/BlittableMarshaller.cs rename to DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/BlittableMarshaller.cs index df59478466fa..817734c0d38f 100644 --- a/DllImportGenerator/DllImportGenerator/Marshalling/BlittableMarshaller.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/BlittableMarshaller.cs @@ -7,7 +7,7 @@ namespace Microsoft.Interop { - internal class BlittableMarshaller : IMarshallingGenerator + public sealed class BlittableMarshaller : IMarshallingGenerator { public TypeSyntax AsNativeType(TypePositionInfo info) { diff --git a/DllImportGenerator/DllImportGenerator/Marshalling/BoolMarshaller.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/BoolMarshaller.cs similarity index 95% rename from DllImportGenerator/DllImportGenerator/Marshalling/BoolMarshaller.cs rename to DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/BoolMarshaller.cs index b659ccbda4b7..b20bf1e2e4ed 100644 --- a/DllImportGenerator/DllImportGenerator/Marshalling/BoolMarshaller.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/BoolMarshaller.cs @@ -8,7 +8,7 @@ namespace Microsoft.Interop { - internal abstract class BoolMarshallerBase : IMarshallingGenerator + public abstract class BoolMarshallerBase : IMarshallingGenerator { private readonly PredefinedTypeSyntax _nativeType; private readonly int _trueValue; @@ -114,7 +114,7 @@ public IEnumerable Generate(TypePositionInfo info, StubCodeCont /// and C++, but those is implementation defined. /// Consult your compiler specification. /// - internal class ByteBoolMarshaller : BoolMarshallerBase + public sealed class ByteBoolMarshaller : BoolMarshallerBase { public ByteBoolMarshaller() : base(PredefinedType(Token(SyntaxKind.ByteKeyword)), trueValue: 1, falseValue: 0, compareToTrue: false) @@ -128,7 +128,7 @@ public ByteBoolMarshaller() /// /// Corresponds to the definition of BOOL. /// - internal class WinBoolMarshaller : BoolMarshallerBase + public sealed class WinBoolMarshaller : BoolMarshallerBase { public WinBoolMarshaller() : base(PredefinedType(Token(SyntaxKind.IntKeyword)), trueValue: 1, falseValue: 0, compareToTrue: false) @@ -139,7 +139,7 @@ public WinBoolMarshaller() /// /// Marshal a boolean value as a VARIANT_BOOL (Windows OLE/Automation type). /// - internal class VariantBoolMarshaller : BoolMarshallerBase + public sealed class VariantBoolMarshaller : BoolMarshallerBase { private const short VARIANT_TRUE = -1; private const short VARIANT_FALSE = 0; diff --git a/DllImportGenerator/DllImportGenerator/Marshalling/CharMarshaller.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/CharMarshaller.cs similarity index 97% rename from DllImportGenerator/DllImportGenerator/Marshalling/CharMarshaller.cs rename to DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/CharMarshaller.cs index b3279390da77..ba193ce4d802 100644 --- a/DllImportGenerator/DllImportGenerator/Marshalling/CharMarshaller.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/CharMarshaller.cs @@ -9,7 +9,7 @@ namespace Microsoft.Interop { - internal class Utf16CharMarshaller : IMarshallingGenerator + public sealed class Utf16CharMarshaller : IMarshallingGenerator { private static readonly PredefinedTypeSyntax NativeType = PredefinedType(Token(SyntaxKind.UShortKeyword)); diff --git a/DllImportGenerator/DllImportGenerator/Marshalling/ConditionalStackallocMarshallingGenerator.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/ConditionalStackallocMarshallingGenerator.cs similarity index 99% rename from DllImportGenerator/DllImportGenerator/Marshalling/ConditionalStackallocMarshallingGenerator.cs rename to DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/ConditionalStackallocMarshallingGenerator.cs index f071d153d9bb..f0bde9de1903 100644 --- a/DllImportGenerator/DllImportGenerator/Marshalling/ConditionalStackallocMarshallingGenerator.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/ConditionalStackallocMarshallingGenerator.cs @@ -6,7 +6,7 @@ namespace Microsoft.Interop { - internal abstract class ConditionalStackallocMarshallingGenerator : IMarshallingGenerator + public abstract class ConditionalStackallocMarshallingGenerator : IMarshallingGenerator { protected static string GetAllocationMarkerIdentifier(string managedIdentifier) => $"{managedIdentifier}__allocated"; diff --git a/DllImportGenerator/DllImportGenerator/Marshalling/CustomNativeTypeMarshaller.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/CustomNativeTypeMarshaller.cs similarity index 99% rename from DllImportGenerator/DllImportGenerator/Marshalling/CustomNativeTypeMarshaller.cs rename to DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/CustomNativeTypeMarshaller.cs index c2f70b702b8f..155ad5e7a9bd 100644 --- a/DllImportGenerator/DllImportGenerator/Marshalling/CustomNativeTypeMarshaller.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/CustomNativeTypeMarshaller.cs @@ -8,7 +8,7 @@ namespace Microsoft.Interop { - class CustomNativeTypeMarshaller : IMarshallingGenerator + public sealed class CustomNativeTypeMarshaller : IMarshallingGenerator { private const string MarshalerLocalSuffix = "__marshaler"; private readonly TypeSyntax _nativeTypeSyntax; diff --git a/DllImportGenerator/DllImportGenerator/Marshalling/DelegateMarshaller.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/DelegateMarshaller.cs similarity index 98% rename from DllImportGenerator/DllImportGenerator/Marshalling/DelegateMarshaller.cs rename to DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/DelegateMarshaller.cs index b874ba0d1c6b..45432ec384cf 100644 --- a/DllImportGenerator/DllImportGenerator/Marshalling/DelegateMarshaller.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/DelegateMarshaller.cs @@ -6,7 +6,7 @@ namespace Microsoft.Interop { - internal class DelegateMarshaller : IMarshallingGenerator + public sealed class DelegateMarshaller : IMarshallingGenerator { public TypeSyntax AsNativeType(TypePositionInfo info) { diff --git a/DllImportGenerator/DllImportGenerator/Marshalling/Forwarder.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/Forwarder.cs similarity index 95% rename from DllImportGenerator/DllImportGenerator/Marshalling/Forwarder.cs rename to DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/Forwarder.cs index 4921ae92ec64..34c9c7119f06 100644 --- a/DllImportGenerator/DllImportGenerator/Marshalling/Forwarder.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/Forwarder.cs @@ -6,7 +6,7 @@ namespace Microsoft.Interop { - internal class Forwarder : IMarshallingGenerator + public sealed class Forwarder : IMarshallingGenerator { public TypeSyntax AsNativeType(TypePositionInfo info) { diff --git a/DllImportGenerator/DllImportGenerator/Marshalling/HResultExceptionMarshaller.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/HResultExceptionMarshaller.cs similarity index 96% rename from DllImportGenerator/DllImportGenerator/Marshalling/HResultExceptionMarshaller.cs rename to DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/HResultExceptionMarshaller.cs index 4b56c8a31072..360d2b26216e 100644 --- a/DllImportGenerator/DllImportGenerator/Marshalling/HResultExceptionMarshaller.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/HResultExceptionMarshaller.cs @@ -9,7 +9,7 @@ namespace Microsoft.Interop { - internal sealed class HResultExceptionMarshaller : IMarshallingGenerator + public sealed class HResultExceptionMarshaller : IMarshallingGenerator { private static readonly TypeSyntax NativeType = PredefinedType(Token(SyntaxKind.IntKeyword)); diff --git a/DllImportGenerator/DllImportGenerator/Marshalling/MarshallerHelpers.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallerHelpers.cs similarity index 99% rename from DllImportGenerator/DllImportGenerator/Marshalling/MarshallerHelpers.cs rename to DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallerHelpers.cs index fd2b8c6200b3..e4145d3e9bb8 100644 --- a/DllImportGenerator/DllImportGenerator/Marshalling/MarshallerHelpers.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallerHelpers.cs @@ -5,7 +5,7 @@ namespace Microsoft.Interop { - internal static class MarshallerHelpers + public static class MarshallerHelpers { public static readonly ExpressionSyntax IsWindows = InvocationExpression( MemberAccessExpression( diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGenerator.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGenerator.cs new file mode 100644 index 000000000000..63653d2884ce --- /dev/null +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGenerator.cs @@ -0,0 +1,102 @@ +using System; +using System.Collections.Generic; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace Microsoft.Interop +{ + /// + /// Interface for generation of marshalling code for P/Invoke stubs + /// + public interface IMarshallingGenerator + { + /// + /// Get the native type syntax for + /// + /// Object to marshal + /// Type syntax for the native type representing + TypeSyntax AsNativeType(TypePositionInfo info); + + /// + /// Get the as a parameter of the P/Invoke declaration + /// + /// Object to marshal + /// Parameter syntax for + ParameterSyntax AsParameter(TypePositionInfo info); + + /// + /// Get the as an argument to be passed to the P/Invoke + /// + /// Object to marshal + /// Code generation context + /// Argument syntax for + ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context); + + /// + /// Generate code for marshalling + /// + /// Object to marshal + /// Code generation context + /// List of statements to be added to the P/Invoke stub + /// + /// The generator should return the appropriate statements based on the + /// of . + /// For , any statements not of type + /// will be ignored. + /// + IEnumerable Generate(TypePositionInfo info, StubCodeContext context); + + /// + /// Returns whether or not this marshaller uses an identifier for the native value in addition + /// to an identifer for the managed value. + /// + /// Object to marshal + /// Code generation context + /// If the marshaller uses an identifier for the native value, true; otherwise, false. + /// + /// of may not be valid. + /// + bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context); + + /// + /// Returns if the given ByValueContentsMarshalKind is supported in the current marshalling context. + /// A supported marshal kind has a different behavior than the default behavior. + /// + /// The marshal kind. + /// The marshalling context. + /// + bool SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, StubCodeContext context); + } + + /// + /// Exception used to indicate marshalling isn't supported. + /// + public sealed class MarshallingNotSupportedException : Exception + { + /// + /// Construct a new instance. + /// + /// instance + /// instance + public MarshallingNotSupportedException(TypePositionInfo info, StubCodeContext context) + { + this.TypePositionInfo = info; + this.StubCodeContext = context; + } + + /// + /// Type that is being marshalled. + /// + public TypePositionInfo TypePositionInfo { get; private init; } + + /// + /// Context in which the marshalling is taking place. + /// + public StubCodeContext StubCodeContext { get; private init; } + + /// + /// [Optional] Specific reason marshalling of the supplied type isn't supported. + /// + public string? NotSupportedDetails { get; init; } + } +} diff --git a/DllImportGenerator/DllImportGenerator/Marshalling/MarshallingGenerator.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGeneratorFactory.cs similarity index 74% rename from DllImportGenerator/DllImportGenerator/Marshalling/MarshallingGenerator.cs rename to DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGeneratorFactory.cs index c8f13da707c3..01516f490ee6 100644 --- a/DllImportGenerator/DllImportGenerator/Marshalling/MarshallingGenerator.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGeneratorFactory.cs @@ -1,6 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; +using System.Runtime.InteropServices; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -9,117 +7,39 @@ namespace Microsoft.Interop { - /// - /// Interface for generation of marshalling code for P/Invoke stubs - /// - internal interface IMarshallingGenerator + public interface IMarshallingGeneratorFactory + where TOptions : InteropGenerationOptions { /// - /// Get the native type syntax for - /// - /// Object to marshal - /// Type syntax for the native type representing - TypeSyntax AsNativeType(TypePositionInfo info); - - /// - /// Get the as a parameter of the P/Invoke declaration - /// - /// Object to marshal - /// Parameter syntax for - ParameterSyntax AsParameter(TypePositionInfo info); - - /// - /// Get the as an argument to be passed to the P/Invoke - /// - /// Object to marshal - /// Code generation context - /// Argument syntax for - ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context); - - /// - /// Generate code for marshalling - /// - /// Object to marshal - /// Code generation context - /// List of statements to be added to the P/Invoke stub - /// - /// The generator should return the appropriate statements based on the - /// of . - /// For , any statements not of type - /// will be ignored. - /// - IEnumerable Generate(TypePositionInfo info, StubCodeContext context); - - /// - /// Returns whether or not this marshaller uses an identifier for the native value in addition - /// to an identifer for the managed value. - /// - /// Object to marshal - /// Code generation context - /// If the marshaller uses an identifier for the native value, true; otherwise, false. - /// - /// of may not be valid. - /// - bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context); - - /// - /// Returns if the given ByValueContentsMarshalKind is supported in the current marshalling context. - /// A supported marshal kind has a different behavior than the default behavior. - /// - /// The marshal kind. - /// The marshalling context. - /// - bool SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, StubCodeContext context); - } - - /// - /// Exception used to indicate marshalling isn't supported. - /// - internal class MarshallingNotSupportedException : Exception - { - /// - /// Construct a new instance. - /// - /// instance - /// instance - public MarshallingNotSupportedException(TypePositionInfo info, StubCodeContext context) - { - this.TypePositionInfo = info; - this.StubCodeContext = context; - } - - /// - /// Type that is being marshalled. - /// - public TypePositionInfo TypePositionInfo { get; private init; } - - /// - /// Context in which the marshalling is taking place. - /// - public StubCodeContext StubCodeContext { get; private init; } - - /// - /// [Optional] Specific reason marshalling of the supplied type isn't supported. + /// Create an instance for marshalling the supplied type in the given position. /// - public string? NotSupportedDetails { get; init; } + /// Type details + /// Metadata about the stub the type is associated with + /// A instance. + public IMarshallingGenerator Create( + TypePositionInfo info, + StubCodeContext context, + TOptions options); } - internal class MarshallingGenerators + public class DefaultMarshallingGeneratorFactory : IMarshallingGeneratorFactory + where TOptions : InteropGenerationOptions { - public static readonly ByteBoolMarshaller ByteBool = new ByteBoolMarshaller(); - public static readonly WinBoolMarshaller WinBool = new WinBoolMarshaller(); - public static readonly VariantBoolMarshaller VariantBool = new VariantBoolMarshaller(); - - public static readonly Utf16CharMarshaller Utf16Char = new Utf16CharMarshaller(); - public static readonly Utf16StringMarshaller Utf16String = new Utf16StringMarshaller(); - public static readonly Utf8StringMarshaller Utf8String = new Utf8StringMarshaller(); - public static readonly AnsiStringMarshaller AnsiString = new AnsiStringMarshaller(Utf8String); - public static readonly PlatformDefinedStringMarshaller PlatformDefinedString = new PlatformDefinedStringMarshaller(Utf16String, Utf8String); - - public static readonly Forwarder Forwarder = new Forwarder(); - public static readonly BlittableMarshaller Blittable = new BlittableMarshaller(); - public static readonly DelegateMarshaller Delegate = new DelegateMarshaller(); - public static readonly HResultExceptionMarshaller HResultException = new HResultExceptionMarshaller(); + protected static readonly ByteBoolMarshaller ByteBool = new(); + protected static readonly WinBoolMarshaller WinBool = new(); + protected static readonly VariantBoolMarshaller VariantBool = new(); + + protected static readonly Utf16CharMarshaller Utf16Char = new(); + protected static readonly Utf16StringMarshaller Utf16String = new(); + protected static readonly Utf8StringMarshaller Utf8String = new(); + protected static readonly AnsiStringMarshaller AnsiString = new AnsiStringMarshaller(Utf8String); + protected static readonly PlatformDefinedStringMarshaller PlatformDefinedString = new PlatformDefinedStringMarshaller(Utf16String, Utf8String); + + protected static readonly Forwarder Forwarder = new(); + protected static readonly BlittableMarshaller Blittable = new(); + protected static readonly DelegateMarshaller Delegate = new(); + protected static readonly HResultExceptionMarshaller HResultException = new(); + protected static readonly SafeHandleMarshaller SafeHandle = new(); /// /// Create an instance for marshalling the supplied type in the given position. @@ -127,15 +47,15 @@ internal class MarshallingGenerators /// Type details /// Metadata about the stub the type is associated with /// A instance. - public static IMarshallingGenerator Create( + public IMarshallingGenerator Create( TypePositionInfo info, StubCodeContext context, - AnalyzerConfigOptions options) + TOptions options) { return ValidateByValueMarshalKind(context, info, CreateCore(info, context, options)); } - private static IMarshallingGenerator ValidateByValueMarshalKind(StubCodeContext context, TypePositionInfo info, IMarshallingGenerator generator) + private IMarshallingGenerator ValidateByValueMarshalKind(StubCodeContext context, TypePositionInfo info, IMarshallingGenerator generator) { if (info.IsByRef && info.ByValueContentsMarshalKind != ByValueContentsMarshalKind.Default) { @@ -168,23 +88,11 @@ private static IMarshallingGenerator ValidateByValueMarshalKind(StubCodeContext /// Type details /// Metadata about the stub the type is associated with /// A instance. - private static IMarshallingGenerator CreateCore( + protected virtual IMarshallingGenerator CreateCore( TypePositionInfo info, StubCodeContext context, - AnalyzerConfigOptions options) + TOptions options) { - if (options.GenerateForwarders()) - { - return MarshallingGenerators.Forwarder; - } - - if (info.IsNativeReturnPosition && !info.IsManagedReturnPosition) - { - // Use marshaller for native HRESULT return / exception throwing - System.Diagnostics.Debug.Assert(info.ManagedType.SpecialType == SpecialType.System_Int32); - return HResultException; - } - switch (info) { // Blittable primitives with no marshalling info or with a compatible [MarshalAs] attribute. @@ -244,7 +152,7 @@ private static IMarshallingGenerator CreateCore( NotSupportedDetails = Resources.SafeHandleByRefMustBeConcrete }; } - return new SafeHandleMarshaller(options); + return SafeHandle; // Marshalling in new model. // Must go before the cases that do not explicitly check for marshalling info to support @@ -278,7 +186,7 @@ private static IMarshallingGenerator CreateCore( } } - private static IMarshallingGenerator CreateCharMarshaller(TypePositionInfo info, StubCodeContext context) + private IMarshallingGenerator CreateCharMarshaller(TypePositionInfo info, StubCodeContext context) { MarshallingInfo marshalInfo = info.MarshallingAttributeInfo; if (marshalInfo is NoMarshallingInfo) @@ -322,7 +230,7 @@ private static IMarshallingGenerator CreateCharMarshaller(TypePositionInfo info, throw new MarshallingNotSupportedException(info, context); } - private static IMarshallingGenerator CreateStringMarshaller(TypePositionInfo info, StubCodeContext context) + private IMarshallingGenerator CreateStringMarshaller(TypePositionInfo info, StubCodeContext context) { MarshallingInfo marshalInfo = info.MarshallingAttributeInfo; if (marshalInfo is NoMarshallingInfo) @@ -366,7 +274,7 @@ private static IMarshallingGenerator CreateStringMarshaller(TypePositionInfo inf throw new MarshallingNotSupportedException(info, context); } - private static ExpressionSyntax GetNumElementsExpressionFromMarshallingInfo(TypePositionInfo info, StubCodeContext context, AnalyzerConfigOptions options) + private ExpressionSyntax GetNumElementsExpressionFromMarshallingInfo(TypePositionInfo info, StubCodeContext context, TOptions options) { ExpressionSyntax numElementsExpression; if (info.MarshallingAttributeInfo is not ArrayMarshalAsInfo marshalAsInfo) @@ -420,7 +328,7 @@ private static ExpressionSyntax GetNumElementsExpressionFromMarshallingInfo(Type return numElementsExpression; } - private static IMarshallingGenerator CreateArrayMarshaller(TypePositionInfo info, StubCodeContext context, AnalyzerConfigOptions options, ITypeSymbol elementType) + private IMarshallingGenerator CreateArrayMarshaller(TypePositionInfo info, StubCodeContext context, TOptions options, ITypeSymbol elementType) { var elementMarshallingInfo = info.MarshallingAttributeInfo switch { @@ -446,7 +354,7 @@ private static IMarshallingGenerator CreateArrayMarshaller(TypePositionInfo info : new NonBlittableArrayMarshaller(elementMarshaller, numElementsExpression); } - private static IMarshallingGenerator CreateCustomNativeTypeMarshaller(TypePositionInfo info, StubCodeContext context, NativeMarshallingAttributeInfo marshalInfo) + private IMarshallingGenerator CreateCustomNativeTypeMarshaller(TypePositionInfo info, StubCodeContext context, NativeMarshallingAttributeInfo marshalInfo) { if (marshalInfo.ValuePropertyType is not null && !context.CanUseAdditionalTemporaryState) { diff --git a/DllImportGenerator/DllImportGenerator/Marshalling/NonBlittableArrayMarshaller.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/NonBlittableArrayMarshaller.cs similarity index 99% rename from DllImportGenerator/DllImportGenerator/Marshalling/NonBlittableArrayMarshaller.cs rename to DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/NonBlittableArrayMarshaller.cs index 40d793c73101..9c1755ab9341 100644 --- a/DllImportGenerator/DllImportGenerator/Marshalling/NonBlittableArrayMarshaller.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/NonBlittableArrayMarshaller.cs @@ -8,7 +8,7 @@ namespace Microsoft.Interop { - internal class NonBlittableArrayMarshaller : ConditionalStackallocMarshallingGenerator + public sealed class NonBlittableArrayMarshaller : ConditionalStackallocMarshallingGenerator { /// /// Stack-alloc threshold set to 256 bytes to enable small arrays to be passed on the stack. diff --git a/DllImportGenerator/DllImportGenerator/Marshalling/SafeHandleMarshaller.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/SafeHandleMarshaller.cs similarity index 98% rename from DllImportGenerator/DllImportGenerator/Marshalling/SafeHandleMarshaller.cs rename to DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/SafeHandleMarshaller.cs index 7fa6513186c1..b4536cbcfe39 100644 --- a/DllImportGenerator/DllImportGenerator/Marshalling/SafeHandleMarshaller.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/SafeHandleMarshaller.cs @@ -8,15 +8,9 @@ namespace Microsoft.Interop { - internal class SafeHandleMarshaller : IMarshallingGenerator + public sealed class SafeHandleMarshaller : IMarshallingGenerator { private static readonly TypeSyntax NativeType = ParseTypeName("global::System.IntPtr"); - private readonly AnalyzerConfigOptions options; - - public SafeHandleMarshaller(AnalyzerConfigOptions options) - { - this.options = options; - } public TypeSyntax AsNativeType(TypePositionInfo info) { diff --git a/DllImportGenerator/DllImportGenerator/Marshalling/StringMarshaller.Ansi.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Ansi.cs similarity index 98% rename from DllImportGenerator/DllImportGenerator/Marshalling/StringMarshaller.Ansi.cs rename to DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Ansi.cs index b12dcfcd0231..16e1f026606d 100644 --- a/DllImportGenerator/DllImportGenerator/Marshalling/StringMarshaller.Ansi.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Ansi.cs @@ -9,7 +9,7 @@ namespace Microsoft.Interop { - internal sealed class AnsiStringMarshaller : ConditionalStackallocMarshallingGenerator + public sealed class AnsiStringMarshaller : ConditionalStackallocMarshallingGenerator { private static readonly TypeSyntax NativeType = PointerType(PredefinedType(Token(SyntaxKind.ByteKeyword))); diff --git a/DllImportGenerator/DllImportGenerator/Marshalling/StringMarshaller.PlatformDefined.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.PlatformDefined.cs similarity index 98% rename from DllImportGenerator/DllImportGenerator/Marshalling/StringMarshaller.PlatformDefined.cs rename to DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.PlatformDefined.cs index a9b665f88b09..3de4c48a724b 100644 --- a/DllImportGenerator/DllImportGenerator/Marshalling/StringMarshaller.PlatformDefined.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.PlatformDefined.cs @@ -10,7 +10,7 @@ namespace Microsoft.Interop { - internal sealed class PlatformDefinedStringMarshaller : ConditionalStackallocMarshallingGenerator + public sealed class PlatformDefinedStringMarshaller : ConditionalStackallocMarshallingGenerator { private static readonly TypeSyntax NativeType = PointerType(PredefinedType(Token(SyntaxKind.VoidKeyword))); diff --git a/DllImportGenerator/DllImportGenerator/Marshalling/StringMarshaller.Utf16.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Utf16.cs similarity index 99% rename from DllImportGenerator/DllImportGenerator/Marshalling/StringMarshaller.Utf16.cs rename to DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Utf16.cs index ffe989fddd2e..9623967cf6e4 100644 --- a/DllImportGenerator/DllImportGenerator/Marshalling/StringMarshaller.Utf16.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Utf16.cs @@ -8,7 +8,7 @@ namespace Microsoft.Interop { - internal sealed class Utf16StringMarshaller : ConditionalStackallocMarshallingGenerator + public sealed class Utf16StringMarshaller : ConditionalStackallocMarshallingGenerator { // [Compat] Equivalent of MAX_PATH on Windows to match built-in system // The assumption is file paths are the most common case for marshalling strings, diff --git a/DllImportGenerator/DllImportGenerator/Marshalling/StringMarshaller.Utf8.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Utf8.cs similarity index 99% rename from DllImportGenerator/DllImportGenerator/Marshalling/StringMarshaller.Utf8.cs rename to DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Utf8.cs index a4c52bffa9a2..2a4801e8d3c3 100644 --- a/DllImportGenerator/DllImportGenerator/Marshalling/StringMarshaller.Utf8.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Utf8.cs @@ -8,7 +8,7 @@ namespace Microsoft.Interop { - internal sealed class Utf8StringMarshaller : ConditionalStackallocMarshallingGenerator + public sealed class Utf8StringMarshaller : ConditionalStackallocMarshallingGenerator { // [Compat] Equivalent of MAX_PATH on Windows to match built-in system // The assumption is file paths are the most common case for marshalling strings, diff --git a/DllImportGenerator/DllImportGenerator/MarshallingAttributeInfo.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/MarshallingAttributeInfo.cs similarity index 74% rename from DllImportGenerator/DllImportGenerator/MarshallingAttributeInfo.cs rename to DllImportGenerator/Microsoft.Interop.SourceGeneration/MarshallingAttributeInfo.cs index a9c036948d56..88c378919ea0 100644 --- a/DllImportGenerator/DllImportGenerator/MarshallingAttributeInfo.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/MarshallingAttributeInfo.cs @@ -10,11 +10,15 @@ namespace Microsoft.Interop // for C# 10 discriminated unions. Once discriminated unions are released, // these should be updated to be implemented as a discriminated union. - internal abstract record MarshallingInfo + public abstract record MarshallingInfo { + // Add a constructor that can only be called by derived types in the same assembly + // to enforce that this type cannot be extended by users of this library. + private protected MarshallingInfo() + {} } - internal sealed record NoMarshallingInfo : MarshallingInfo + public sealed record NoMarshallingInfo : MarshallingInfo { public static readonly MarshallingInfo Instance = new NoMarshallingInfo(); @@ -24,7 +28,7 @@ private NoMarshallingInfo() { } /// /// Character encoding enumeration. /// - internal enum CharEncoding + public enum CharEncoding { Undefined, Utf8, @@ -36,20 +40,20 @@ internal enum CharEncoding /// /// Details that are required when scenario supports strings. /// - internal record MarshallingInfoStringSupport( + public record MarshallingInfoStringSupport( CharEncoding CharEncoding ) : MarshallingInfo; /// /// Simple User-application of System.Runtime.InteropServices.MarshalAsAttribute /// - internal record MarshalAsInfo( + public record MarshalAsInfo( UnmanagedType UnmanagedType, CharEncoding CharEncoding) : MarshallingInfoStringSupport(CharEncoding) { } - enum UnmanagedArrayType + public enum UnmanagedArrayType { LPArray = UnmanagedType.LPArray, ByValArray = UnmanagedType.ByValArray @@ -58,7 +62,7 @@ enum UnmanagedArrayType /// /// User-applied System.Runtime.InteropServices.MarshalAsAttribute with array marshalling info /// - internal sealed record ArrayMarshalAsInfo( + public sealed record ArrayMarshalAsInfo( UnmanagedArrayType UnmanagedArrayType, int ArraySizeConst, short ArraySizeParamIndex, @@ -73,10 +77,10 @@ internal sealed record ArrayMarshalAsInfo( /// or System.Runtime.InteropServices.GeneratedMarshallingAttribute on a blittable type /// in source in this compilation. /// - internal sealed record BlittableTypeAttributeInfo : MarshallingInfo; + public sealed record BlittableTypeAttributeInfo : MarshallingInfo; [Flags] - internal enum SupportedMarshallingMethods + public enum SupportedMarshallingMethods { ManagedToNative = 0x1, NativeToManaged = 0x2, @@ -87,7 +91,7 @@ internal enum SupportedMarshallingMethods /// /// User-applied System.Runtime.InteropServices.NativeMarshallingAttribute /// - internal sealed record NativeMarshallingAttributeInfo( + public sealed record NativeMarshallingAttributeInfo( ITypeSymbol NativeMarshallingType, ITypeSymbol? ValuePropertyType, SupportedMarshallingMethods MarshallingMethods, @@ -97,17 +101,17 @@ internal sealed record NativeMarshallingAttributeInfo( /// User-applied System.Runtime.InteropServices.GeneratedMarshallingAttribute /// on a non-blittable type in source in this compilation. /// - internal sealed record GeneratedNativeMarshallingAttributeInfo( + public sealed record GeneratedNativeMarshallingAttributeInfo( string NativeMarshallingFullyQualifiedTypeName) : MarshallingInfo; /// /// The type of the element is a SafeHandle-derived type with no marshalling attributes. /// - internal sealed record SafeHandleMarshallingInfo(bool AccessibleDefaultConstructor) : MarshallingInfo; + public sealed record SafeHandleMarshallingInfo(bool AccessibleDefaultConstructor) : MarshallingInfo; /// /// Default marshalling for arrays /// - internal sealed record ArrayMarshallingInfo(MarshallingInfo ElementMarshallingInfo) : MarshallingInfo; + public sealed record ArrayMarshallingInfo(MarshallingInfo ElementMarshallingInfo) : MarshallingInfo; } diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj new file mode 100644 index 000000000000..703bce87fd4f --- /dev/null +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj @@ -0,0 +1,29 @@ + + + + netstandard2.0 + false + enable + Microsoft.Interop + + + + + + + + + Resources.resx + True + True + + + + + + Designer + Resources.Designer.cs + ResXFileCodeGenerator + + + diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Resources.Designer.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Resources.Designer.cs new file mode 100644 index 000000000000..c451a2bece59 --- /dev/null +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Resources.Designer.cs @@ -0,0 +1,270 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Microsoft.Interop { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.Interop.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute'.. + /// + internal static string ArraySizeMustBeSpecified { + get { + return ResourceManager.GetString("ArraySizeMustBeSpecified", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The 'SizeParamIndex' value in the 'MarshalAsAttribute' is out of range.. + /// + internal static string ArraySizeParamIndexOutOfRange { + get { + return ResourceManager.GetString("ArraySizeParamIndexOutOfRange", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The specified array size parameter for an array must be an integer type.. + /// + internal static string ArraySizeParamTypeMustBeIntegral { + get { + return ResourceManager.GetString("ArraySizeParamTypeMustBeIntegral", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The 'BlittableTypeAttribute' and 'NativeMarshallingAttribute' attributes are mutually exclusive.. + /// + internal static string CannotHaveMultipleMarshallingAttributesDescription { + get { + return ResourceManager.GetString("CannotHaveMultipleMarshallingAttributesDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Type '{0}' is marked with 'BlittableTypeAttribute' and 'NativeMarshallingAttribute'. A type can only have one of these two attributes.. + /// + internal static string CannotHaveMultipleMarshallingAttributesMessage { + get { + return ResourceManager.GetString("CannotHaveMultipleMarshallingAttributesMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The specified parameter needs to be marshalled from managed to native, but the native type '{0}' does not support it.. + /// + internal static string CustomTypeMarshallingManagedToNativeUnsupported { + get { + return ResourceManager.GetString("CustomTypeMarshallingManagedToNativeUnsupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The specified parameter needs to be marshalled from native to managed, but the native type '{0}' does not support it.. + /// + internal static string CustomTypeMarshallingNativeToManagedUnsupported { + get { + return ResourceManager.GetString("CustomTypeMarshallingNativeToManagedUnsupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The '[In]' attribute is not supported unless the '[Out]' attribute is also used. The behavior of the '[In]' attribute without the '[Out]' attribute is the same as the default behavior.. + /// + internal static string InAttributeNotSupportedWithoutOut { + get { + return ResourceManager.GetString("InAttributeNotSupportedWithoutOut", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The '[In]' and '[Out]' attributes are unsupported on parameters passed by reference. Use the 'in', 'ref', or 'out' keywords instead.. + /// + internal static string InOutAttributeByRefNotSupported { + get { + return ResourceManager.GetString("InOutAttributeByRefNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The provided '[In]' and '[Out]' attributes on this parameter are unsupported on this parameter.. + /// + internal static string InOutAttributeMarshalerNotSupported { + get { + return ResourceManager.GetString("InOutAttributeMarshalerNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Marshalling char with 'CharSet.{0}' is not supported. Instead, manually convert the char type to the desired byte representation and pass to the source-generated P/Invoke.. + /// + internal static string MarshallingCharAsSpecifiedCharSetNotSupported { + get { + return ResourceManager.GetString("MarshallingCharAsSpecifiedCharSetNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Marshalling string or char without explicit marshalling information is not supported. Specify either 'GeneratedDllImportAttribute.CharSet' or 'MarshalAsAttribute'.. + /// + internal static string MarshallingStringOrCharAsUndefinedNotSupported { + get { + return ResourceManager.GetString("MarshallingStringOrCharAsUndefinedNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The '[Out]' attribute is only supported on array parameters.. + /// + internal static string OutByValueNotSupportedDescription { + get { + return ResourceManager.GetString("OutByValueNotSupportedDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The '[Out]' attribute is not supported on the '{0}' parameter.. + /// + internal static string OutByValueNotSupportedMessage { + get { + return ResourceManager.GetString("OutByValueNotSupportedMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The 'Value' property must not be a 'ref' or 'readonly ref' property.. + /// + internal static string RefValuePropertyUnsupportedDescription { + get { + return ResourceManager.GetString("RefValuePropertyUnsupportedDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The 'Value' property on the native type '{0}' must not be a 'ref' or 'readonly ref' property.. + /// + internal static string RefValuePropertyUnsupportedMessage { + get { + return ResourceManager.GetString("RefValuePropertyUnsupportedMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to An abstract type derived from 'SafeHandle' cannot be marshalled by reference. The provided type must be concrete.. + /// + internal static string SafeHandleByRefMustBeConcrete { + get { + return ResourceManager.GetString("SafeHandleByRefMustBeConcrete", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Specified type is not supported by source-generated P/Invokes. + /// + internal static string TypeNotSupportedTitle { + get { + return ResourceManager.GetString("TypeNotSupportedTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Marshalling a value between managed and native with a native type with a 'Value' property requires extra state, which is not supported in this context.. + /// + internal static string ValuePropertyMarshallingRequiresAdditionalState { + get { + return ResourceManager.GetString("ValuePropertyMarshallingRequiresAdditionalState", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The native type's 'Value' property must have a getter to support marshalling from managed to native.. + /// + internal static string ValuePropertyMustHaveGetterDescription { + get { + return ResourceManager.GetString("ValuePropertyMustHaveGetterDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The 'Value' property on the native type '{0}' must have a getter. + /// + internal static string ValuePropertyMustHaveGetterMessage { + get { + return ResourceManager.GetString("ValuePropertyMustHaveGetterMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The native type's 'Value' property must have a setter to support marshalling from native to managed.. + /// + internal static string ValuePropertyMustHaveSetterDescription { + get { + return ResourceManager.GetString("ValuePropertyMustHaveSetterDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The 'Value' property on the native type '{0}' must have a setter. + /// + internal static string ValuePropertyMustHaveSetterMessage { + get { + return ResourceManager.GetString("ValuePropertyMustHaveSetterMessage", resourceCulture); + } + } + } +} diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Resources.resx b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Resources.resx new file mode 100644 index 000000000000..d21ad29d3da4 --- /dev/null +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Resources.resx @@ -0,0 +1,189 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute'. + + + The 'SizeParamIndex' value in the 'MarshalAsAttribute' is out of range. + + + The specified array size parameter for an array must be an integer type. + + + The 'BlittableTypeAttribute' and 'NativeMarshallingAttribute' attributes are mutually exclusive. + + + Type '{0}' is marked with 'BlittableTypeAttribute' and 'NativeMarshallingAttribute'. A type can only have one of these two attributes. + + + The specified parameter needs to be marshalled from managed to native, but the native type '{0}' does not support it. + + + The specified parameter needs to be marshalled from native to managed, but the native type '{0}' does not support it. + + + The '[In]' attribute is not supported unless the '[Out]' attribute is also used. The behavior of the '[In]' attribute without the '[Out]' attribute is the same as the default behavior. + + + The '[In]' and '[Out]' attributes are unsupported on parameters passed by reference. Use the 'in', 'ref', or 'out' keywords instead. + + + The provided '[In]' and '[Out]' attributes on this parameter are unsupported on this parameter. + + + Marshalling char with 'CharSet.{0}' is not supported. Instead, manually convert the char type to the desired byte representation and pass to the source-generated P/Invoke. + + + Marshalling string or char without explicit marshalling information is not supported. Specify either 'GeneratedDllImportAttribute.CharSet' or 'MarshalAsAttribute'. + + + The '[Out]' attribute is only supported on array parameters. + + + The '[Out]' attribute is not supported on the '{0}' parameter. + + + The 'Value' property must not be a 'ref' or 'readonly ref' property. + + + The 'Value' property on the native type '{0}' must not be a 'ref' or 'readonly ref' property. + + + An abstract type derived from 'SafeHandle' cannot be marshalled by reference. The provided type must be concrete. + + + Specified type is not supported by source-generated P/Invokes + + + Marshalling a value between managed and native with a native type with a 'Value' property requires extra state, which is not supported in this context. + + + The native type's 'Value' property must have a getter to support marshalling from managed to native. + + + The 'Value' property on the native type '{0}' must have a getter + + + The native type's 'Value' property must have a setter to support marshalling from native to managed. + + + The 'Value' property on the native type '{0}' must have a setter + + \ No newline at end of file diff --git a/DllImportGenerator/DllImportGenerator/StubCodeContext.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/StubCodeContext.cs similarity index 98% rename from DllImportGenerator/DllImportGenerator/StubCodeContext.cs rename to DllImportGenerator/Microsoft.Interop.SourceGeneration/StubCodeContext.cs index 3ddef8d5e331..9b212d35735e 100644 --- a/DllImportGenerator/DllImportGenerator/StubCodeContext.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/StubCodeContext.cs @@ -2,7 +2,7 @@ namespace Microsoft.Interop { - internal abstract class StubCodeContext + public abstract class StubCodeContext { /// /// Code generation stage diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/TypeNames.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/TypeNames.cs new file mode 100644 index 000000000000..1a640a2c395e --- /dev/null +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/TypeNames.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.Interop; + +namespace Microsoft.Interop +{ + static class TypeNames + { + public const string GeneratedDllImportAttribute = "System.Runtime.InteropServices.GeneratedDllImportAttribute"; + + public const string GeneratedMarshallingAttribute = "System.Runtime.InteropServices.GeneratedMarshallingAttribute"; + + public const string BlittableTypeAttribute = "System.Runtime.InteropServices.BlittableTypeAttribute"; + + public const string NativeMarshallingAttribute = "System.Runtime.InteropServices.NativeMarshallingAttribute"; + + public const string MarshalUsingAttribute = "System.Runtime.InteropServices.MarshalUsingAttribute"; + + public const string LCIDConversionAttribute = "System.Runtime.InteropServices.LCIDConversionAttribute"; + + public const string System_Span_Metadata = "System.Span`1"; + public const string System_Span = "System.Span"; + + public const string System_Activator = "System.Activator"; + + public const string System_Runtime_InteropServices_StructLayoutAttribute = "System.Runtime.InteropServices.StructLayoutAttribute"; + + public const string System_Runtime_InteropServices_MarshalAsAttribute = "System.Runtime.InteropServices.MarshalAsAttribute"; + + public const string System_Runtime_InteropServices_Marshal = "System.Runtime.InteropServices.Marshal"; + + private const string System_Runtime_InteropServices_MarshalEx = "System.Runtime.InteropServices.MarshalEx"; + + public static string MarshalEx(InteropGenerationOptions options) + { + return options.UseMarshalType ? System_Runtime_InteropServices_Marshal : System_Runtime_InteropServices_MarshalEx; + } + + public const string System_Runtime_InteropServices_MemoryMarshal = "System.Runtime.InteropServices.MemoryMarshal"; + + public const string System_Runtime_InteropServices_SafeHandle = "System.Runtime.InteropServices.SafeHandle"; + + public const string System_Runtime_InteropServices_OutAttribute = "System.Runtime.InteropServices.OutAttribute"; + + public const string System_Runtime_InteropServices_InAttribute = "System.Runtime.InteropServices.InAttribute"; + + public const string System_Runtime_CompilerServices_SkipLocalsInitAttribute = "System.Runtime.CompilerServices.SkipLocalsInitAttribute"; + } +} diff --git a/DllImportGenerator/DllImportGenerator/TypePositionInfo.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/TypePositionInfo.cs similarity index 96% rename from DllImportGenerator/DllImportGenerator/TypePositionInfo.cs rename to DllImportGenerator/Microsoft.Interop.SourceGeneration/TypePositionInfo.cs index 06d6040ea3c0..79ae33ec11f4 100644 --- a/DllImportGenerator/DllImportGenerator/TypePositionInfo.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/TypePositionInfo.cs @@ -12,7 +12,7 @@ namespace Microsoft.Interop /// /// Type used to pass on default marshalling details. /// - internal sealed record DefaultMarshallingInfo ( + public sealed record DefaultMarshallingInfo ( CharEncoding CharEncoding ); @@ -23,7 +23,7 @@ CharEncoding CharEncoding /// contents of the managed array. /// [Flags] - internal enum ByValueContentsMarshalKind + public enum ByValueContentsMarshalKind { /// /// Marshal contents from managed to native only. @@ -48,7 +48,7 @@ internal enum ByValueContentsMarshalKind /// /// Positional type information involved in unmanaged/managed scenarios. /// - internal sealed record TypePositionInfo + public sealed record TypePositionInfo { public const int UnsetIndex = int.MinValue; public const int ReturnIndex = UnsetIndex + 1; @@ -82,7 +82,7 @@ private TypePositionInfo() public MarshallingInfo MarshallingAttributeInfo { get; init; } - public static TypePositionInfo CreateForParameter(IParameterSymbol paramSymbol, DefaultMarshallingInfo defaultInfo, Compilation compilation, GeneratorDiagnostics diagnostics, INamedTypeSymbol scopeSymbol) + public static TypePositionInfo CreateForParameter(IParameterSymbol paramSymbol, DefaultMarshallingInfo defaultInfo, Compilation compilation, IGeneratorDiagnostics diagnostics, INamedTypeSymbol scopeSymbol) { var marshallingInfo = GetMarshallingInfo(paramSymbol.Type, paramSymbol.GetAttributes(), defaultInfo, compilation, diagnostics, scopeSymbol); var typeInfo = new TypePositionInfo() @@ -98,7 +98,7 @@ public static TypePositionInfo CreateForParameter(IParameterSymbol paramSymbol, return typeInfo; } - public static TypePositionInfo CreateForType(ITypeSymbol type, IEnumerable attributes, DefaultMarshallingInfo defaultInfo, Compilation compilation, GeneratorDiagnostics diagnostics, INamedTypeSymbol scopeSymbol) + public static TypePositionInfo CreateForType(ITypeSymbol type, IEnumerable attributes, DefaultMarshallingInfo defaultInfo, Compilation compilation, IGeneratorDiagnostics diagnostics, INamedTypeSymbol scopeSymbol) { var marshallingInfo = GetMarshallingInfo(type, attributes, defaultInfo, compilation, diagnostics, scopeSymbol); var typeInfo = new TypePositionInfo() @@ -127,7 +127,7 @@ public static TypePositionInfo CreateForType(ITypeSymbol type, MarshallingInfo m return typeInfo; } - private static MarshallingInfo GetMarshallingInfo(ITypeSymbol type, IEnumerable attributes, DefaultMarshallingInfo defaultInfo, Compilation compilation, GeneratorDiagnostics diagnostics, INamedTypeSymbol scopeSymbol) + private static MarshallingInfo GetMarshallingInfo(ITypeSymbol type, IEnumerable attributes, DefaultMarshallingInfo defaultInfo, Compilation compilation, IGeneratorDiagnostics diagnostics, INamedTypeSymbol scopeSymbol) { // Look at attributes passed in - usage specific. foreach (var attrData in attributes) @@ -183,7 +183,7 @@ private static MarshallingInfo GetMarshallingInfo(ITypeSymbol type, IEnumerable< return NoMarshallingInfo.Instance; - static MarshalAsInfo CreateMarshalAsInfo(ITypeSymbol type, AttributeData attrData, DefaultMarshallingInfo defaultInfo, Compilation compilation, GeneratorDiagnostics diagnostics, INamedTypeSymbol scopeSymbol) + static MarshalAsInfo CreateMarshalAsInfo(ITypeSymbol type, AttributeData attrData, DefaultMarshallingInfo defaultInfo, Compilation compilation, IGeneratorDiagnostics diagnostics, INamedTypeSymbol scopeSymbol) { object unmanagedTypeObj = attrData.ConstructorArguments[0].Value!; UnmanagedType unmanagedType = unmanagedTypeObj is short @@ -307,7 +307,7 @@ static NativeMarshallingAttributeInfo CreateNativeMarshallingInfo(ITypeSymbol ty NativeTypePinnable: ManualTypeMarshallingHelper.FindGetPinnableReference(nativeType) is not null); } - static bool TryCreateTypeBasedMarshallingInfo(ITypeSymbol type, DefaultMarshallingInfo defaultInfo, Compilation compilation, GeneratorDiagnostics diagnostics, INamedTypeSymbol scopeSymbol, out MarshallingInfo marshallingInfo) + static bool TryCreateTypeBasedMarshallingInfo(ITypeSymbol type, DefaultMarshallingInfo defaultInfo, Compilation compilation, IGeneratorDiagnostics diagnostics, INamedTypeSymbol scopeSymbol, out MarshallingInfo marshallingInfo) { var conversion = compilation.ClassifyCommonConversion(type, compilation.GetTypeByMetadataName(TypeNames.System_Runtime_InteropServices_SafeHandle)!); if (conversion.Exists diff --git a/DllImportGenerator/DllImportGenerator/TypeSymbolExtensions.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/TypeSymbolExtensions.cs similarity index 99% rename from DllImportGenerator/DllImportGenerator/TypeSymbolExtensions.cs rename to DllImportGenerator/Microsoft.Interop.SourceGeneration/TypeSymbolExtensions.cs index 745f861f6101..92ae1214e31a 100644 --- a/DllImportGenerator/DllImportGenerator/TypeSymbolExtensions.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/TypeSymbolExtensions.cs @@ -11,7 +11,7 @@ namespace Microsoft.Interop { - static class TypeSymbolExtensions + public static class TypeSymbolExtensions { public static bool HasOnlyBlittableFields(this ITypeSymbol type) { From aa619bf00a3585eed36b778f87d514a296712562 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Wed, 12 May 2021 16:09:23 -0700 Subject: [PATCH 02/12] Fix build. Make the PInvoke stub code-gen less opinionated to simplify reuse for in other P/Invoke-style scenarios (like QCalls or function-pointer-based targets). --- .../Benchmarks/Benchmarks.csproj | 1 + DllImportGenerator/Demo/Demo.csproj | 1 + ...DllImportGenerator.IntegrationTests.csproj | 1 + .../DllImportGeneratorOptionsProvider.cs | 4 +- .../DllImportGenerator.csproj | 6 +- .../DllImportGeneratorOptions.cs | 3 +- .../DllImportGenerator/DllImportStub.cs | 165 +++++++++++++- ...tedDllImportMarshallingGeneratorFactory.cs | 8 +- ...nerator.cs => PInvokeStubCodeGenerator.cs} | 208 ++++-------------- .../DllImportGenerator/TypeNames.cs | 2 + .../MarshallingGeneratorFactory.cs | 29 +-- 11 files changed, 231 insertions(+), 197 deletions(-) rename DllImportGenerator/DllImportGenerator/{StubCodeGenerator.cs => PInvokeStubCodeGenerator.cs} (63%) diff --git a/DllImportGenerator/Benchmarks/Benchmarks.csproj b/DllImportGenerator/Benchmarks/Benchmarks.csproj index 232c421e2886..16ec90095d08 100644 --- a/DllImportGenerator/Benchmarks/Benchmarks.csproj +++ b/DllImportGenerator/Benchmarks/Benchmarks.csproj @@ -14,6 +14,7 @@ + diff --git a/DllImportGenerator/Demo/Demo.csproj b/DllImportGenerator/Demo/Demo.csproj index 11805179e79d..1ffe230ada81 100644 --- a/DllImportGenerator/Demo/Demo.csproj +++ b/DllImportGenerator/Demo/Demo.csproj @@ -16,6 +16,7 @@ + diff --git a/DllImportGenerator/DllImportGenerator.IntegrationTests/DllImportGenerator.IntegrationTests.csproj b/DllImportGenerator/DllImportGenerator.IntegrationTests/DllImportGenerator.IntegrationTests.csproj index 4588c962fc81..ecd9ee7adf63 100644 --- a/DllImportGenerator/DllImportGenerator.IntegrationTests/DllImportGenerator.IntegrationTests.csproj +++ b/DllImportGenerator/DllImportGenerator.IntegrationTests/DllImportGenerator.IntegrationTests.csproj @@ -18,6 +18,7 @@ + diff --git a/DllImportGenerator/DllImportGenerator.UnitTests/DllImportGeneratorOptionsProvider.cs b/DllImportGenerator/DllImportGenerator.UnitTests/DllImportGeneratorOptionsProvider.cs index 221c4803efb5..a774bd2ef353 100644 --- a/DllImportGenerator/DllImportGenerator.UnitTests/DllImportGeneratorOptionsProvider.cs +++ b/DllImportGenerator/DllImportGenerator.UnitTests/DllImportGeneratorOptionsProvider.cs @@ -42,11 +42,11 @@ public override bool TryGetValue(string key, [NotNullWhen(true)] out string? val { switch (key) { - case DllImportGeneratorOptions.UseMarshalTypeOption: + case OptionsHelper.UseMarshalTypeOption: value = _useMarshalType.ToString(); return true; - case DllImportGeneratorOptions.GenerateForwardersOption: + case OptionsHelper.GenerateForwardersOption: value = _generateForwarders.ToString(); return true; diff --git a/DllImportGenerator/DllImportGenerator/DllImportGenerator.csproj b/DllImportGenerator/DllImportGenerator/DllImportGenerator.csproj index 3eddc59deb03..c0c8bc14dbc4 100644 --- a/DllImportGenerator/DllImportGenerator/DllImportGenerator.csproj +++ b/DllImportGenerator/DllImportGenerator/DllImportGenerator.csproj @@ -33,10 +33,6 @@ - - - - @@ -61,7 +57,7 @@ - + diff --git a/DllImportGenerator/DllImportGenerator/DllImportGeneratorOptions.cs b/DllImportGenerator/DllImportGenerator/DllImportGeneratorOptions.cs index 5138c8169889..4d15a759c7a1 100644 --- a/DllImportGenerator/DllImportGenerator/DllImportGeneratorOptions.cs +++ b/DllImportGenerator/DllImportGenerator/DllImportGeneratorOptions.cs @@ -7,11 +7,10 @@ record DllImportGeneratorOptions(bool GenerateForwarders, bool UseMarshalType) : public DllImportGeneratorOptions(AnalyzerConfigOptions options) : this(options.GenerateForwarders(), options.UseMarshalType()) { - } } - internal static class OptionsHelper + public static class OptionsHelper { public const string UseMarshalTypeOption = "build_property.DllImportGenerator_UseMarshalType"; public const string GenerateForwardersOption = "build_property.DllImportGenerator_GenerateForwarders"; diff --git a/DllImportGenerator/DllImportGenerator/DllImportStub.cs b/DllImportGenerator/DllImportGenerator/DllImportStub.cs index 06fe53554d5d..7e68d362e7a9 100644 --- a/DllImportGenerator/DllImportGenerator/DllImportStub.cs +++ b/DllImportGenerator/DllImportGenerator/DllImportStub.cs @@ -196,7 +196,7 @@ public static DllImportStub Create( // Transform the managed return type info into an out parameter and add it as the last param TypePositionInfo nativeOutInfo = managedRetTypeInfo with { - InstanceIdentifier = StubCodeGenerator.ReturnIdentifier, + InstanceIdentifier = PInvokeStubCodeGenerator.ReturnIdentifier, RefKind = RefKind.Out, RefKindSyntax = SyntaxKind.OutKeyword, ManagedIndex = TypePositionInfo.ReturnIndex, @@ -207,8 +207,16 @@ public static DllImportStub Create( } // Generate stub code - var stubGenerator = new StubCodeGenerator(method, dllImportData, paramsTypeInfo, retTypeInfo, diagnostics, env.Options, new GeneratedDllImportMarshallingGeneratorFactory()); - var code = stubGenerator.GenerateSyntax(); + var stubGenerator = new PInvokeStubCodeGenerator( + method, + paramsTypeInfo, + retTypeInfo, + diagnostics, + dllImportData.SetLastError && !env.Options.GenerateForwarders, + new GeneratedDllImportMarshallingGeneratorFactory(env.Options)); + string stubTargetName = "__PInvoke__"; + var code = stubGenerator.GeneratePInvokeBody(IdentifierName(stubTargetName)); + code = code.AddStatements(CreateTargetFunctionAsLocalStatement(stubGenerator, env.Options, dllImportData, stubTargetName, method.Name)); var additionalAttrs = new List(); @@ -236,5 +244,156 @@ public static DllImportStub Create( AdditionalAttributes = additionalAttrs.ToArray(), }; } + + private static LocalFunctionStatementSyntax CreateTargetFunctionAsLocalStatement( + PInvokeStubCodeGenerator stubGenerator, + DllImportGeneratorOptions options, + GeneratedDllImportData dllImportData, + string stubTargetName, + string stubMethodName) + { + var (parameterList, returnType) = stubGenerator.GenerateTargetMethodSignatureData(); + return LocalFunctionStatement(returnType, stubTargetName) + .AddModifiers( + Token(SyntaxKind.ExternKeyword), + Token(SyntaxKind.StaticKeyword), + Token(SyntaxKind.UnsafeKeyword)) + .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)) + .WithAttributeLists( + SingletonList(AttributeList( + SingletonSeparatedList( + CreateDllImportAttributeForTarget( + GetTargetDllImportDataFromStubData( + dllImportData, + stubMethodName, + options.GenerateForwarders)))))) + .WithParameterList(parameterList); + } + + private static AttributeSyntax CreateDllImportAttributeForTarget(GeneratedDllImportData targetDllImportData) + { + var newAttributeArgs = new List + { + AttributeArgument(LiteralExpression( + SyntaxKind.StringLiteralExpression, + Literal(targetDllImportData.ModuleName))), + AttributeArgument( + NameEquals(nameof(DllImportAttribute.EntryPoint)), + null, + CreateStringExpressionSyntax(targetDllImportData.EntryPoint)) + }; + + if (targetDllImportData.IsUserDefined.HasFlag(DllImportStub.DllImportMember.BestFitMapping)) + { + var name = NameEquals(nameof(DllImportAttribute.BestFitMapping)); + var value = CreateBoolExpressionSyntax(targetDllImportData.BestFitMapping); + newAttributeArgs.Add(AttributeArgument(name, null, value)); + } + if (targetDllImportData.IsUserDefined.HasFlag(DllImportStub.DllImportMember.CallingConvention)) + { + var name = NameEquals(nameof(DllImportAttribute.CallingConvention)); + var value = CreateEnumExpressionSyntax(targetDllImportData.CallingConvention); + newAttributeArgs.Add(AttributeArgument(name, null, value)); + } + if (targetDllImportData.IsUserDefined.HasFlag(DllImportStub.DllImportMember.CharSet)) + { + var name = NameEquals(nameof(DllImportAttribute.CharSet)); + var value = CreateEnumExpressionSyntax(targetDllImportData.CharSet); + newAttributeArgs.Add(AttributeArgument(name, null, value)); + } + if (targetDllImportData.IsUserDefined.HasFlag(DllImportStub.DllImportMember.ExactSpelling)) + { + var name = NameEquals(nameof(DllImportAttribute.ExactSpelling)); + var value = CreateBoolExpressionSyntax(targetDllImportData.ExactSpelling); + newAttributeArgs.Add(AttributeArgument(name, null, value)); + } + if (targetDllImportData.IsUserDefined.HasFlag(DllImportStub.DllImportMember.PreserveSig)) + { + var name = NameEquals(nameof(DllImportAttribute.PreserveSig)); + var value = CreateBoolExpressionSyntax(targetDllImportData.PreserveSig); + newAttributeArgs.Add(AttributeArgument(name, null, value)); + } + if (targetDllImportData.IsUserDefined.HasFlag(DllImportStub.DllImportMember.SetLastError)) + { + var name = NameEquals(nameof(DllImportAttribute.SetLastError)); + var value = CreateBoolExpressionSyntax(targetDllImportData.SetLastError); + newAttributeArgs.Add(AttributeArgument(name, null, value)); + } + if (targetDllImportData.IsUserDefined.HasFlag(DllImportStub.DllImportMember.ThrowOnUnmappableChar)) + { + var name = NameEquals(nameof(DllImportAttribute.ThrowOnUnmappableChar)); + var value = CreateBoolExpressionSyntax(targetDllImportData.ThrowOnUnmappableChar); + newAttributeArgs.Add(AttributeArgument(name, null, value)); + } + + // Create new attribute + return Attribute( + ParseName(typeof(DllImportAttribute).FullName), + AttributeArgumentList(SeparatedList(newAttributeArgs))); + + static ExpressionSyntax CreateBoolExpressionSyntax(bool trueOrFalse) + { + return LiteralExpression( + trueOrFalse + ? SyntaxKind.TrueLiteralExpression + : SyntaxKind.FalseLiteralExpression); + } + + static ExpressionSyntax CreateStringExpressionSyntax(string str) + { + return LiteralExpression( + SyntaxKind.StringLiteralExpression, + Literal(str)); + } + + static ExpressionSyntax CreateEnumExpressionSyntax(T value) where T : Enum + { + return MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + IdentifierName(typeof(T).FullName), + IdentifierName(value.ToString())); + } + } + + private static GeneratedDllImportData GetTargetDllImportDataFromStubData(GeneratedDllImportData dllImportData, string originalMethodName, bool forwardAll) + { + DllImportMember membersToForward = DllImportStub.DllImportMember.All + // https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.dllimportattribute.preservesig + // If PreserveSig=false (default is true), the P/Invoke stub checks/converts a returned HRESULT to an exception. + & ~DllImportStub.DllImportMember.PreserveSig + // https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.dllimportattribute.setlasterror + // If SetLastError=true (default is false), the P/Invoke stub gets/caches the last error after invoking the native function. + & ~DllImportStub.DllImportMember.SetLastError; + if (forwardAll) + { + membersToForward = DllImportStub.DllImportMember.All; + } + + var targetDllImportData = new GeneratedDllImportData + { + CharSet = dllImportData.CharSet, + BestFitMapping = dllImportData.BestFitMapping, + CallingConvention = dllImportData.CallingConvention, + EntryPoint = dllImportData.EntryPoint, + ModuleName = dllImportData.ModuleName, + ExactSpelling = dllImportData.ExactSpelling, + SetLastError = dllImportData.SetLastError, + PreserveSig = dllImportData.PreserveSig, + ThrowOnUnmappableChar = dllImportData.ThrowOnUnmappableChar, + IsUserDefined = dllImportData.IsUserDefined & membersToForward + }; + + // If the EntryPoint property is not set, we will compute and + // add it based on existing semantics (i.e. method name). + // + // N.B. The export discovery logic is identical regardless of where + // the name is defined (i.e. method name vs EntryPoint property). + if (!targetDllImportData.IsUserDefined.HasFlag(DllImportStub.DllImportMember.EntryPoint)) + { + targetDllImportData.EntryPoint = originalMethodName; + } + + return targetDllImportData; + } } } diff --git a/DllImportGenerator/DllImportGenerator/GeneratedDllImportMarshallingGeneratorFactory.cs b/DllImportGenerator/DllImportGenerator/GeneratedDllImportMarshallingGeneratorFactory.cs index 9865a3bc287a..98e2c94c858a 100644 --- a/DllImportGenerator/DllImportGenerator/GeneratedDllImportMarshallingGeneratorFactory.cs +++ b/DllImportGenerator/DllImportGenerator/GeneratedDllImportMarshallingGeneratorFactory.cs @@ -8,9 +8,11 @@ namespace Microsoft.Interop { class GeneratedDllImportMarshallingGeneratorFactory : DefaultMarshallingGeneratorFactory { - protected override IMarshallingGenerator CreateCore(TypePositionInfo info, StubCodeContext context, DllImportGeneratorOptions options) + public GeneratedDllImportMarshallingGeneratorFactory(DllImportGeneratorOptions options) : base(options) { } + + protected override IMarshallingGenerator CreateCore(TypePositionInfo info, StubCodeContext context) { - if (options.GenerateForwarders) + if (Options.GenerateForwarders) { return Forwarder; } @@ -22,7 +24,7 @@ protected override IMarshallingGenerator CreateCore(TypePositionInfo info, StubC return HResultException; } - return base.CreateCore(info, context, options); + return base.CreateCore(info, context); } } } diff --git a/DllImportGenerator/DllImportGenerator/StubCodeGenerator.cs b/DllImportGenerator/DllImportGenerator/PInvokeStubCodeGenerator.cs similarity index 63% rename from DllImportGenerator/DllImportGenerator/StubCodeGenerator.cs rename to DllImportGenerator/DllImportGenerator/PInvokeStubCodeGenerator.cs index 320f91783098..3bc4db993535 100644 --- a/DllImportGenerator/DllImportGenerator/StubCodeGenerator.cs +++ b/DllImportGenerator/DllImportGenerator/PInvokeStubCodeGenerator.cs @@ -6,12 +6,25 @@ 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 { - internal sealed class StubCodeGenerator : StubCodeContext + /// + /// 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 [GeneratedDllImport] 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 PInvokeStubCodeGenerator : StubCodeContext { public override bool PinningSupported => true; @@ -48,30 +61,27 @@ internal sealed class StubCodeGenerator : StubCodeContext Stage.Cleanup }; - private readonly GeneratorDiagnostics diagnostics; - private readonly DllImportGeneratorOptions options; + private readonly IGeneratorDiagnostics diagnostics; private readonly IMethodSymbol stubMethod; - private readonly DllImportStub.GeneratedDllImportData dllImportData; + private readonly bool setLastError; private readonly IEnumerable paramsTypeInfo; - private readonly List<(TypePositionInfo TypeInfo, IMarshallingGenerator Generator)> paramMarshallers; + private readonly IReadOnlyList<(TypePositionInfo TypeInfo, IMarshallingGenerator Generator)> paramMarshallers; private readonly (TypePositionInfo TypeInfo, IMarshallingGenerator Generator) retMarshaller; - public StubCodeGenerator( + public PInvokeStubCodeGenerator( IMethodSymbol stubMethod, - DllImportStub.GeneratedDllImportData dllImportData, IEnumerable paramsTypeInfo, TypePositionInfo retTypeInfo, - GeneratorDiagnostics generatorDiagnostics, - DllImportGeneratorOptions options, - IMarshallingGeneratorFactory generatorFactory) + IGeneratorDiagnostics generatorDiagnostics, + bool setLastError, + IMarshallingGeneratorFactory generatorFactory) { Debug.Assert(retTypeInfo.IsNativeReturnPosition); this.stubMethod = stubMethod; - this.dllImportData = dllImportData; + this.setLastError = setLastError; this.paramsTypeInfo = paramsTypeInfo.ToList(); this.diagnostics = generatorDiagnostics; - this.options = options; // Get marshallers for parameters this.paramMarshallers = paramsTypeInfo.Select(p => CreateGenerator(p)).ToList(); @@ -83,7 +93,7 @@ public StubCodeGenerator( { try { - return (p, generatorFactory.Create(p, this, options)); + return (p, generatorFactory.Create(p, this)); } catch (MarshallingNotSupportedException e) { @@ -116,9 +126,8 @@ public override (string managed, string native) GetIdentifiers(TypePositionInfo } } - public BlockSyntax GenerateSyntax() + public BlockSyntax GeneratePInvokeBody(ExpressionSyntax targetMethodExpression) { - string dllImportName = stubMethod.Name + "__PInvoke__"; var setupStatements = new List(); if (retMarshaller.Generator.UsesNativeIdentifier(retMarshaller.TypeInfo, this)) @@ -155,9 +164,6 @@ public BlockSyntax GenerateSyntax() // Stub return is not the same as invoke return if (!stubReturnsVoid && !retMarshaller.TypeInfo.IsManagedReturnPosition) { - // Should only happen when PreserveSig=false - Debug.Assert(!dllImportData.PreserveSig, "Expected PreserveSig=false when invoke return is not the stub return"); - // Stub return should be the last parameter for the invoke Debug.Assert(paramMarshallers.Any() && paramMarshallers.Last().TypeInfo.IsManagedReturnPosition, "Expected stub return to be the last parameter for the invoke"); @@ -180,7 +186,7 @@ public BlockSyntax GenerateSyntax() // Do not manually handle SetLastError when generating forwarders. // We want the runtime to handle everything. - if (this.dllImportData.SetLastError && !options.GenerateForwarders) + if (this.setLastError) { // Declare variable for last error setupStatements.Add(MarshallerHelpers.DeclareWithDefault( @@ -190,7 +196,7 @@ public BlockSyntax GenerateSyntax() var tryStatements = new List(); var finallyStatements = new List(); - var invoke = InvocationExpression(IdentifierName(dllImportName)); + var invoke = InvocationExpression(targetMethodExpression); var fixedStatements = new List(); foreach (var stage in Stages) { @@ -255,7 +261,7 @@ public BlockSyntax GenerateSyntax() // Do not manually handle SetLastError when generating forwarders. // We want the runtime to handle everything. - if (this.dllImportData.SetLastError && !options.GenerateForwarders) + if (this.setLastError) { // Marshal.SetLastSystemError(0); var clearLastError = ExpressionStatement( @@ -320,7 +326,7 @@ public BlockSyntax GenerateSyntax() allStatements.AddRange(tryStatements); } - if (this.dllImportData.SetLastError && !options.GenerateForwarders) + if (this.setLastError) { // Marshal.SetLastPInvokeError(); allStatements.Add(ExpressionStatement( @@ -338,25 +344,7 @@ public BlockSyntax GenerateSyntax() allStatements.Add(ReturnStatement(IdentifierName(ReturnIdentifier))); // Wrap all statements in an unsafe block - var codeBlock = Block(UnsafeStatement(Block(allStatements))); - - // Define P/Invoke declaration - var dllImport = LocalFunctionStatement(retMarshaller.Generator.AsNativeType(retMarshaller.TypeInfo), dllImportName) - .AddModifiers( - Token(SyntaxKind.ExternKeyword), - Token(SyntaxKind.StaticKeyword), - Token(SyntaxKind.UnsafeKeyword)) - .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)) - .WithAttributeLists( - SingletonList(AttributeList( - SingletonSeparatedList(CreateDllImportAttributeForTarget(GetTargetDllImportDataFromStubData()))))); - foreach (var marshaller in paramMarshallers) - { - ParameterSyntax paramSyntax = marshaller.Generator.AsParameter(marshaller.TypeInfo); - dllImport = dllImport.AddParameterListParameters(paramSyntax); - } - - return codeBlock.AddStatements(dllImport); + return Block(UnsafeStatement(Block(allStatements))); List GetStatements(Stage stage) { @@ -370,6 +358,16 @@ List GetStatements(Stage stage) } } + public (ParameterListSyntax ParameterList, TypeSyntax ReturnType) GenerateTargetMethodSignatureData() + { + return ( + ParameterList( + SeparatedList( + paramMarshallers.Select(marshaler => marshaler.Generator.AsParameter(marshaler.TypeInfo)))), + retMarshaller.Generator.AsNativeType(retMarshaller.TypeInfo) + ); + } + public override TypePositionInfo? GetTypePositionInfoForManagedIndex(int index) { foreach (var info in paramsTypeInfo) @@ -402,131 +400,5 @@ private void AppendVariableDeclations(List statementsToUpdate, native)); } } - - private static AttributeSyntax CreateDllImportAttributeForTarget(DllImportStub.GeneratedDllImportData targetDllImportData) - { - var newAttributeArgs = new List - { - AttributeArgument(LiteralExpression( - SyntaxKind.StringLiteralExpression, - Literal(targetDllImportData.ModuleName))), - AttributeArgument( - NameEquals(nameof(DllImportAttribute.EntryPoint)), - null, - CreateStringExpressionSyntax(targetDllImportData.EntryPoint)) - }; - - if (targetDllImportData.IsUserDefined.HasFlag(DllImportStub.DllImportMember.BestFitMapping)) - { - var name = NameEquals(nameof(DllImportAttribute.BestFitMapping)); - var value = CreateBoolExpressionSyntax(targetDllImportData.BestFitMapping); - newAttributeArgs.Add(AttributeArgument(name, null, value)); - } - if (targetDllImportData.IsUserDefined.HasFlag(DllImportStub.DllImportMember.CallingConvention)) - { - var name = NameEquals(nameof(DllImportAttribute.CallingConvention)); - var value = CreateEnumExpressionSyntax(targetDllImportData.CallingConvention); - newAttributeArgs.Add(AttributeArgument(name, null, value)); - } - if (targetDllImportData.IsUserDefined.HasFlag(DllImportStub.DllImportMember.CharSet)) - { - var name = NameEquals(nameof(DllImportAttribute.CharSet)); - var value = CreateEnumExpressionSyntax(targetDllImportData.CharSet); - newAttributeArgs.Add(AttributeArgument(name, null, value)); - } - if (targetDllImportData.IsUserDefined.HasFlag(DllImportStub.DllImportMember.ExactSpelling)) - { - var name = NameEquals(nameof(DllImportAttribute.ExactSpelling)); - var value = CreateBoolExpressionSyntax(targetDllImportData.ExactSpelling); - newAttributeArgs.Add(AttributeArgument(name, null, value)); - } - if (targetDllImportData.IsUserDefined.HasFlag(DllImportStub.DllImportMember.PreserveSig)) - { - var name = NameEquals(nameof(DllImportAttribute.PreserveSig)); - var value = CreateBoolExpressionSyntax(targetDllImportData.PreserveSig); - newAttributeArgs.Add(AttributeArgument(name, null, value)); - } - if (targetDllImportData.IsUserDefined.HasFlag(DllImportStub.DllImportMember.SetLastError)) - { - var name = NameEquals(nameof(DllImportAttribute.SetLastError)); - var value = CreateBoolExpressionSyntax(targetDllImportData.SetLastError); - newAttributeArgs.Add(AttributeArgument(name, null, value)); - } - if (targetDllImportData.IsUserDefined.HasFlag(DllImportStub.DllImportMember.ThrowOnUnmappableChar)) - { - var name = NameEquals(nameof(DllImportAttribute.ThrowOnUnmappableChar)); - var value = CreateBoolExpressionSyntax(targetDllImportData.ThrowOnUnmappableChar); - newAttributeArgs.Add(AttributeArgument(name, null, value)); - } - - // Create new attribute - return Attribute( - ParseName(typeof(DllImportAttribute).FullName), - AttributeArgumentList(SeparatedList(newAttributeArgs))); - - static ExpressionSyntax CreateBoolExpressionSyntax(bool trueOrFalse) - { - return LiteralExpression( - trueOrFalse - ? SyntaxKind.TrueLiteralExpression - : SyntaxKind.FalseLiteralExpression); - } - - static ExpressionSyntax CreateStringExpressionSyntax(string str) - { - return LiteralExpression( - SyntaxKind.StringLiteralExpression, - Literal(str)); - } - - static ExpressionSyntax CreateEnumExpressionSyntax(T value) where T : Enum - { - return MemberAccessExpression( - SyntaxKind.SimpleMemberAccessExpression, - IdentifierName(typeof(T).FullName), - IdentifierName(value.ToString())); - } - } - - DllImportStub.GeneratedDllImportData GetTargetDllImportDataFromStubData() - { - DllImportStub.DllImportMember membersToForward = DllImportStub.DllImportMember.All - // https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.dllimportattribute.preservesig - // If PreserveSig=false (default is true), the P/Invoke stub checks/converts a returned HRESULT to an exception. - & ~DllImportStub.DllImportMember.PreserveSig - // https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.dllimportattribute.setlasterror - // If SetLastError=true (default is false), the P/Invoke stub gets/caches the last error after invoking the native function. - & ~DllImportStub.DllImportMember.SetLastError; - if (options.GenerateForwarders) - { - membersToForward = DllImportStub.DllImportMember.All; - } - - var targetDllImportData = new DllImportStub.GeneratedDllImportData - { - CharSet = dllImportData.CharSet, - BestFitMapping = dllImportData.BestFitMapping, - CallingConvention = dllImportData.CallingConvention, - EntryPoint = dllImportData.EntryPoint, - ModuleName = dllImportData.ModuleName, - ExactSpelling = dllImportData.ExactSpelling, - SetLastError = dllImportData.SetLastError, - PreserveSig = dllImportData.PreserveSig, - ThrowOnUnmappableChar = dllImportData.ThrowOnUnmappableChar, - IsUserDefined = dllImportData.IsUserDefined & membersToForward - }; - - // If the EntryPoint property is not set, we will compute and - // add it based on existing semantics (i.e. method name). - // - // N.B. The export discovery logic is identical regardless of where - // the name is defined (i.e. method name vs EntryPoint property). - if (!targetDllImportData.IsUserDefined.HasFlag(DllImportStub.DllImportMember.EntryPoint)) - { - targetDllImportData.EntryPoint = stubMethod.Name; - } - - return targetDllImportData; - } } } diff --git a/DllImportGenerator/DllImportGenerator/TypeNames.cs b/DllImportGenerator/DllImportGenerator/TypeNames.cs index 58bd2803c42b..da36cf5d93d8 100644 --- a/DllImportGenerator/DllImportGenerator/TypeNames.cs +++ b/DllImportGenerator/DllImportGenerator/TypeNames.cs @@ -8,6 +8,8 @@ namespace Microsoft.Interop { static class TypeNames { + public const string DllImportAttribute = "System.Runtime.InteropServices.DllImportAttribute"; + public const string GeneratedDllImportAttribute = "System.Runtime.InteropServices.GeneratedDllImportAttribute"; public const string GeneratedMarshallingAttribute = "System.Runtime.InteropServices.GeneratedMarshallingAttribute"; diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGeneratorFactory.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGeneratorFactory.cs index 01516f490ee6..551b4733c88e 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGeneratorFactory.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGeneratorFactory.cs @@ -7,8 +7,7 @@ namespace Microsoft.Interop { - public interface IMarshallingGeneratorFactory - where TOptions : InteropGenerationOptions + public interface IMarshallingGeneratorFactory { /// /// Create an instance for marshalling the supplied type in the given position. @@ -18,11 +17,10 @@ public interface IMarshallingGeneratorFactory /// A instance. public IMarshallingGenerator Create( TypePositionInfo info, - StubCodeContext context, - TOptions options); + StubCodeContext context); } - public class DefaultMarshallingGeneratorFactory : IMarshallingGeneratorFactory + public class DefaultMarshallingGeneratorFactory : IMarshallingGeneratorFactory where TOptions : InteropGenerationOptions { protected static readonly ByteBoolMarshaller ByteBool = new(); @@ -40,6 +38,12 @@ public class DefaultMarshallingGeneratorFactory : IMarshallingGenerato protected static readonly DelegateMarshaller Delegate = new(); protected static readonly HResultExceptionMarshaller HResultException = new(); protected static readonly SafeHandleMarshaller SafeHandle = new(); + protected TOptions Options { get; } + + public DefaultMarshallingGeneratorFactory(TOptions options) + { + this.Options = options; + } /// /// Create an instance for marshalling the supplied type in the given position. @@ -49,10 +53,9 @@ public class DefaultMarshallingGeneratorFactory : IMarshallingGenerato /// A instance. public IMarshallingGenerator Create( TypePositionInfo info, - StubCodeContext context, - TOptions options) + StubCodeContext context) { - return ValidateByValueMarshalKind(context, info, CreateCore(info, context, options)); + return ValidateByValueMarshalKind(context, info, CreateCore(info, context)); } private IMarshallingGenerator ValidateByValueMarshalKind(StubCodeContext context, TypePositionInfo info, IMarshallingGenerator generator) @@ -90,8 +93,7 @@ private IMarshallingGenerator ValidateByValueMarshalKind(StubCodeContext context /// A instance. protected virtual IMarshallingGenerator CreateCore( TypePositionInfo info, - StubCodeContext context, - TOptions options) + StubCodeContext context) { switch (info) { @@ -176,7 +178,7 @@ protected virtual IMarshallingGenerator CreateCore( return CreateStringMarshaller(info, context); case { ManagedType: IArrayTypeSymbol { IsSZArray: true, ElementType: ITypeSymbol elementType } }: - return CreateArrayMarshaller(info, context, options, elementType); + return CreateArrayMarshaller(info, context, Options, elementType); case { ManagedType: { SpecialType: SpecialType.System_Void } }: return Forwarder; @@ -309,7 +311,7 @@ private ExpressionSyntax GetNumElementsExpressionFromMarshallingInfo(TypePositio else { var (managed, native) = context.GetIdentifiers(paramIndexInfo); - string identifier = Create(paramIndexInfo, context, options).UsesNativeIdentifier(paramIndexInfo, context) ? native : managed; + string identifier = Create(paramIndexInfo, context).UsesNativeIdentifier(paramIndexInfo, context) ? native : managed; sizeParamIndexExpression = CastExpression( PredefinedType(Token(SyntaxKind.IntKeyword)), IdentifierName(identifier)); @@ -340,8 +342,7 @@ private IMarshallingGenerator CreateArrayMarshaller(TypePositionInfo info, StubC var elementMarshaller = Create( TypePositionInfo.CreateForType(elementType, elementMarshallingInfo), - new ArrayMarshallingCodeContext(StubCodeContext.Stage.Setup, string.Empty, context, false), - options); + new ArrayMarshallingCodeContext(StubCodeContext.Stage.Setup, string.Empty, context, false)); ExpressionSyntax numElementsExpression = LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(0)); if (info.IsManagedReturnPosition || (info.IsByRef && info.RefKind != RefKind.In)) { From 363cb2e976bff5752f3fc8ae2a8f9372f9cf2221 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Thu, 13 May 2021 09:58:13 -0700 Subject: [PATCH 03/12] Use decorator pattern instead of inheritance to handle customizations of the selection. --- .../DllImportGeneratorOptions.cs | 2 +- .../DllImportGenerator/DllImportStub.cs | 53 ++++++++++++------- .../ForwarderMarshallingGeneratorFactory.cs | 13 +++++ ...PreserveSigMarshallingGeneratorFactory.cs} | 18 +++---- .../MarshallingGeneratorFactory.cs | 48 ++++++++--------- 5 files changed, 79 insertions(+), 55 deletions(-) create mode 100644 DllImportGenerator/DllImportGenerator/ForwarderMarshallingGeneratorFactory.cs rename DllImportGenerator/DllImportGenerator/{GeneratedDllImportMarshallingGeneratorFactory.cs => NoPreserveSigMarshallingGeneratorFactory.cs} (50%) diff --git a/DllImportGenerator/DllImportGenerator/DllImportGeneratorOptions.cs b/DllImportGenerator/DllImportGenerator/DllImportGeneratorOptions.cs index 4d15a759c7a1..e2480ba84185 100644 --- a/DllImportGenerator/DllImportGenerator/DllImportGeneratorOptions.cs +++ b/DllImportGenerator/DllImportGenerator/DllImportGeneratorOptions.cs @@ -2,7 +2,7 @@ namespace Microsoft.Interop { - record DllImportGeneratorOptions(bool GenerateForwarders, bool UseMarshalType) : InteropGenerationOptions(UseMarshalType) + record DllImportGeneratorOptions(bool GenerateForwarders, bool UseMarshalType) { public DllImportGeneratorOptions(AnalyzerConfigOptions options) : this(options.GenerateForwarders(), options.UseMarshalType()) diff --git a/DllImportGenerator/DllImportGenerator/DllImportStub.cs b/DllImportGenerator/DllImportGenerator/DllImportStub.cs index 7e68d362e7a9..ba336d36ed41 100644 --- a/DllImportGenerator/DllImportGenerator/DllImportStub.cs +++ b/DllImportGenerator/DllImportGenerator/DllImportStub.cs @@ -179,30 +179,43 @@ public static DllImportStub Create( }; var managedRetTypeInfo = retTypeInfo; - // Do not manually handle PreserveSig when generating forwarders. - // We want the runtime to handle everything. - if (!dllImportData.PreserveSig && !env.Options.GenerateForwarders) + IMarshallingGeneratorFactory generatorFactory; + if (env.Options.GenerateForwarders) { - // Create type info for native HRESULT return - retTypeInfo = TypePositionInfo.CreateForType(env.Compilation.GetSpecialType(SpecialType.System_Int32), NoMarshallingInfo.Instance); - retTypeInfo = retTypeInfo with - { - NativeIndex = TypePositionInfo.ReturnIndex - }; + generatorFactory = new ForwarderMarshallingGeneratorFactory(); + } + else + { + generatorFactory = new DefaultMarshallingGeneratorFactory(new InteropGenerationOptions(env.Options.UseMarshalType)); - // Create type info for native out param - if (!method.ReturnsVoid) + // Do not manually handle PreserveSig when generating forwarders. + // We want the runtime to handle everything. + if (!dllImportData.PreserveSig) { - // Transform the managed return type info into an out parameter and add it as the last param - TypePositionInfo nativeOutInfo = managedRetTypeInfo with + // Use a marshalling generator that supports the HRESULT return->exception marshalling. + generatorFactory = new NoPreserveSigMarshallingGeneratorFactory(generatorFactory); + + // Create type info for native HRESULT return + retTypeInfo = TypePositionInfo.CreateForType(env.Compilation.GetSpecialType(SpecialType.System_Int32), NoMarshallingInfo.Instance); + retTypeInfo = retTypeInfo with { - InstanceIdentifier = PInvokeStubCodeGenerator.ReturnIdentifier, - RefKind = RefKind.Out, - RefKindSyntax = SyntaxKind.OutKeyword, - ManagedIndex = TypePositionInfo.ReturnIndex, - NativeIndex = paramsTypeInfo.Count + NativeIndex = TypePositionInfo.ReturnIndex }; - paramsTypeInfo.Add(nativeOutInfo); + + // Create type info for native out param + if (!method.ReturnsVoid) + { + // Transform the managed return type info into an out parameter and add it as the last param + TypePositionInfo nativeOutInfo = managedRetTypeInfo with + { + InstanceIdentifier = PInvokeStubCodeGenerator.ReturnIdentifier, + RefKind = RefKind.Out, + RefKindSyntax = SyntaxKind.OutKeyword, + ManagedIndex = TypePositionInfo.ReturnIndex, + NativeIndex = paramsTypeInfo.Count + }; + paramsTypeInfo.Add(nativeOutInfo); + } } } @@ -213,7 +226,7 @@ public static DllImportStub Create( retTypeInfo, diagnostics, dllImportData.SetLastError && !env.Options.GenerateForwarders, - new GeneratedDllImportMarshallingGeneratorFactory(env.Options)); + generatorFactory); string stubTargetName = "__PInvoke__"; var code = stubGenerator.GeneratePInvokeBody(IdentifierName(stubTargetName)); code = code.AddStatements(CreateTargetFunctionAsLocalStatement(stubGenerator, env.Options, dllImportData, stubTargetName, method.Name)); diff --git a/DllImportGenerator/DllImportGenerator/ForwarderMarshallingGeneratorFactory.cs b/DllImportGenerator/DllImportGenerator/ForwarderMarshallingGeneratorFactory.cs new file mode 100644 index 000000000000..60c85b4baba0 --- /dev/null +++ b/DllImportGenerator/DllImportGenerator/ForwarderMarshallingGeneratorFactory.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Microsoft.Interop +{ + class ForwarderMarshallingGeneratorFactory : IMarshallingGeneratorFactory + { + private static readonly Forwarder Forwarder = new Forwarder(); + + public IMarshallingGenerator Create(TypePositionInfo info, StubCodeContext context) => Forwarder; + } +} diff --git a/DllImportGenerator/DllImportGenerator/GeneratedDllImportMarshallingGeneratorFactory.cs b/DllImportGenerator/DllImportGenerator/NoPreserveSigMarshallingGeneratorFactory.cs similarity index 50% rename from DllImportGenerator/DllImportGenerator/GeneratedDllImportMarshallingGeneratorFactory.cs rename to DllImportGenerator/DllImportGenerator/NoPreserveSigMarshallingGeneratorFactory.cs index 98e2c94c858a..d0ed18a3520a 100644 --- a/DllImportGenerator/DllImportGenerator/GeneratedDllImportMarshallingGeneratorFactory.cs +++ b/DllImportGenerator/DllImportGenerator/NoPreserveSigMarshallingGeneratorFactory.cs @@ -6,25 +6,25 @@ namespace Microsoft.Interop { - class GeneratedDllImportMarshallingGeneratorFactory : DefaultMarshallingGeneratorFactory + class NoPreserveSigMarshallingGeneratorFactory : IMarshallingGeneratorFactory { - public GeneratedDllImportMarshallingGeneratorFactory(DllImportGeneratorOptions options) : base(options) { } + private static readonly HResultExceptionMarshaller HResultException = new HResultExceptionMarshaller(); + private readonly IMarshallingGeneratorFactory inner; - protected override IMarshallingGenerator CreateCore(TypePositionInfo info, StubCodeContext context) + public NoPreserveSigMarshallingGeneratorFactory(IMarshallingGeneratorFactory inner) { - if (Options.GenerateForwarders) - { - return Forwarder; - } + this.inner = inner; + } + public IMarshallingGenerator Create(TypePositionInfo info, StubCodeContext context) + { if (info.IsNativeReturnPosition && !info.IsManagedReturnPosition) { // Use marshaller for native HRESULT return / exception throwing System.Diagnostics.Debug.Assert(info.ManagedType.SpecialType == SpecialType.System_Int32); return HResultException; } - - return base.CreateCore(info, context); + return inner.Create(info, context); } } } diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGeneratorFactory.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGeneratorFactory.cs index 551b4733c88e..fa6b66a1d966 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGeneratorFactory.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGeneratorFactory.cs @@ -20,27 +20,25 @@ public IMarshallingGenerator Create( StubCodeContext context); } - public class DefaultMarshallingGeneratorFactory : IMarshallingGeneratorFactory - where TOptions : InteropGenerationOptions + public sealed class DefaultMarshallingGeneratorFactory : IMarshallingGeneratorFactory { - protected static readonly ByteBoolMarshaller ByteBool = new(); - protected static readonly WinBoolMarshaller WinBool = new(); - protected static readonly VariantBoolMarshaller VariantBool = new(); - - protected static readonly Utf16CharMarshaller Utf16Char = new(); - protected static readonly Utf16StringMarshaller Utf16String = new(); - protected static readonly Utf8StringMarshaller Utf8String = new(); - protected static readonly AnsiStringMarshaller AnsiString = new AnsiStringMarshaller(Utf8String); - protected static readonly PlatformDefinedStringMarshaller PlatformDefinedString = new PlatformDefinedStringMarshaller(Utf16String, Utf8String); - - protected static readonly Forwarder Forwarder = new(); - protected static readonly BlittableMarshaller Blittable = new(); - protected static readonly DelegateMarshaller Delegate = new(); - protected static readonly HResultExceptionMarshaller HResultException = new(); - protected static readonly SafeHandleMarshaller SafeHandle = new(); - protected TOptions Options { get; } - - public DefaultMarshallingGeneratorFactory(TOptions options) + private static readonly ByteBoolMarshaller ByteBool = new(); + private static readonly WinBoolMarshaller WinBool = new(); + private static readonly VariantBoolMarshaller VariantBool = new(); + + private static readonly Utf16CharMarshaller Utf16Char = new(); + private static readonly Utf16StringMarshaller Utf16String = new(); + private static readonly Utf8StringMarshaller Utf8String = new(); + private static readonly AnsiStringMarshaller AnsiString = new AnsiStringMarshaller(Utf8String); + private static readonly PlatformDefinedStringMarshaller PlatformDefinedString = new PlatformDefinedStringMarshaller(Utf16String, Utf8String); + + private static readonly Forwarder Forwarder = new(); + private static readonly BlittableMarshaller Blittable = new(); + private static readonly DelegateMarshaller Delegate = new(); + private static readonly SafeHandleMarshaller SafeHandle = new(); + private InteropGenerationOptions Options { get; } + + public DefaultMarshallingGeneratorFactory(InteropGenerationOptions options) { this.Options = options; } @@ -91,7 +89,7 @@ private IMarshallingGenerator ValidateByValueMarshalKind(StubCodeContext context /// Type details /// Metadata about the stub the type is associated with /// A instance. - protected virtual IMarshallingGenerator CreateCore( + private IMarshallingGenerator CreateCore( TypePositionInfo info, StubCodeContext context) { @@ -178,7 +176,7 @@ protected virtual IMarshallingGenerator CreateCore( return CreateStringMarshaller(info, context); case { ManagedType: IArrayTypeSymbol { IsSZArray: true, ElementType: ITypeSymbol elementType } }: - return CreateArrayMarshaller(info, context, Options, elementType); + return CreateArrayMarshaller(info, context, elementType); case { ManagedType: { SpecialType: SpecialType.System_Void } }: return Forwarder; @@ -276,7 +274,7 @@ private IMarshallingGenerator CreateStringMarshaller(TypePositionInfo info, Stub throw new MarshallingNotSupportedException(info, context); } - private ExpressionSyntax GetNumElementsExpressionFromMarshallingInfo(TypePositionInfo info, StubCodeContext context, TOptions options) + private ExpressionSyntax GetNumElementsExpressionFromMarshallingInfo(TypePositionInfo info, StubCodeContext context) { ExpressionSyntax numElementsExpression; if (info.MarshallingAttributeInfo is not ArrayMarshalAsInfo marshalAsInfo) @@ -330,7 +328,7 @@ private ExpressionSyntax GetNumElementsExpressionFromMarshallingInfo(TypePositio return numElementsExpression; } - private IMarshallingGenerator CreateArrayMarshaller(TypePositionInfo info, StubCodeContext context, TOptions options, ITypeSymbol elementType) + private IMarshallingGenerator CreateArrayMarshaller(TypePositionInfo info, StubCodeContext context, ITypeSymbol elementType) { var elementMarshallingInfo = info.MarshallingAttributeInfo switch { @@ -347,7 +345,7 @@ private IMarshallingGenerator CreateArrayMarshaller(TypePositionInfo info, StubC if (info.IsManagedReturnPosition || (info.IsByRef && info.RefKind != RefKind.In)) { // In this case, we need a numElementsExpression supplied from metadata, so we'll calculate it here. - numElementsExpression = GetNumElementsExpressionFromMarshallingInfo(info, context, options); + numElementsExpression = GetNumElementsExpressionFromMarshallingInfo(info, context); } return elementMarshaller == Blittable From 3d2b9dcad0588254a45875432ace6d6c6271df91 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Thu, 13 May 2021 10:35:02 -0700 Subject: [PATCH 04/12] Remove default parameter value. --- .../IGeneratorDiagnostics.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/IGeneratorDiagnostics.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/IGeneratorDiagnostics.cs index 435ab7d3a4a7..fb01f60070d2 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/IGeneratorDiagnostics.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/IGeneratorDiagnostics.cs @@ -64,6 +64,12 @@ void ReportMarshallingNotSupported( void ReportConfigurationNotSupported( AttributeData attributeData, string configurationName, - string? unsupportedValue = null); + string? unsupportedValue); + } + + public static class IGeneratorDiagnosticsExtensions + { + public static void ReportConfigurationNotSupported(this IGeneratorDiagnostics diagnostics, AttributeData attributeData, string configurationName) + => diagnostics.ReportConfigurationNotSupported(attributeData, configurationName, null); } } From 458ccab3620fc0c1ff56c5de59dfcde7e20af5a7 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Mon, 17 May 2021 14:28:37 -0700 Subject: [PATCH 05/12] Convert Microsoft.Interop.SourceGeneration to a source package. --- DllImportGenerator/Directory.Build.props | 13 ++++++++ .../ConvertToGeneratedDllImportAnalyzer.cs | 2 +- .../Analyzers/GeneratedDllImportAnalyzer.cs | 2 +- .../ManualTypeMarshallingAnalyzer.cs | 2 +- .../DllImportGenerator.csproj | 27 ++-------------- .../DllImportGenerator/DllImportStub.cs | 1 + .../ForwarderMarshallingGeneratorFactory.cs | 3 +- .../GeneratorDiagnostics.cs | 4 +-- .../DllImportGenerator/LanguageSupport.cs | 10 ------ ...oPreserveSigMarshallingGeneratorFactory.cs | 1 + .../PInvokeStubCodeGenerator.cs | 1 + .../ArrayMarshallingCodeContext.cs | 2 +- .../IGeneratorDiagnostics.cs | 8 ++--- .../InteropGenerationOptions.cs | 4 +-- .../ManualTypeMarshallingHelper.cs | 4 +-- .../Marshalling/BlittableArrayMarshaller.cs | 4 +-- .../Marshalling/BlittableMarshaller.cs | 4 +-- .../Marshalling/BoolMarshaller.cs | 10 +++--- .../Marshalling/CharMarshaller.cs | 4 +-- ...nditionalStackallocMarshallingGenerator.cs | 4 +-- .../Marshalling/CustomNativeTypeMarshaller.cs | 4 +-- .../Marshalling/DelegateMarshaller.cs | 4 +-- .../Marshalling/Forwarder.cs | 4 +-- .../Marshalling/HResultExceptionMarshaller.cs | 4 +-- .../Marshalling/MarshallerHelpers.cs | 4 +-- .../Marshalling/MarshallingGenerator.cs | 6 ++-- .../MarshallingGeneratorFactory.cs | 6 ++-- .../NonBlittableArrayMarshaller.cs | 4 +-- .../Marshalling/SafeHandleMarshaller.cs | 4 +-- .../Marshalling/StringMarshaller.Ansi.cs | 6 ++-- .../StringMarshaller.PlatformDefined.cs | 6 ++-- .../Marshalling/StringMarshaller.Utf16.cs | 6 ++-- .../Marshalling/StringMarshaller.Utf8.cs | 6 ++-- .../MarshallingAttributeInfo.cs | 32 ++++++++----------- .../Microsoft.Interop.SourceGeneration.csproj | 14 ++++---- .../Resources.Designer.cs | 13 ++++++-- .../Resources.resx | 3 ++ .../StubCodeContext.cs | 4 +-- .../TypeNames.cs | 2 +- .../TypePositionInfo.cs | 8 ++--- .../TypeSymbolExtensions.cs | 4 +-- 41 files changed, 125 insertions(+), 129 deletions(-) create mode 100644 DllImportGenerator/Directory.Build.props delete mode 100644 DllImportGenerator/DllImportGenerator/LanguageSupport.cs diff --git a/DllImportGenerator/Directory.Build.props b/DllImportGenerator/Directory.Build.props new file mode 100644 index 000000000000..22565674b76a --- /dev/null +++ b/DllImportGenerator/Directory.Build.props @@ -0,0 +1,13 @@ + + + + Microsoft + https://github.com/dotnet/runtimelab/tree/feature/DllImportGenerator + https://github.com/dotnet/runtimelab/tree/feature/DllImportGenerator + false + DllImportGenerator + Summary of changes made in this release of the package. + Copyright + DllImportGenerator, analyzers + + \ No newline at end of file diff --git a/DllImportGenerator/DllImportGenerator/Analyzers/ConvertToGeneratedDllImportAnalyzer.cs b/DllImportGenerator/DllImportGenerator/Analyzers/ConvertToGeneratedDllImportAnalyzer.cs index 2df44242463e..061205bb3f68 100644 --- a/DllImportGenerator/DllImportGenerator/Analyzers/ConvertToGeneratedDllImportAnalyzer.cs +++ b/DllImportGenerator/DllImportGenerator/Analyzers/ConvertToGeneratedDllImportAnalyzer.cs @@ -4,7 +4,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; - +using Microsoft.Interop.SourceGeneration; using static Microsoft.Interop.Analyzers.AnalyzerDiagnostics; namespace Microsoft.Interop.Analyzers diff --git a/DllImportGenerator/DllImportGenerator/Analyzers/GeneratedDllImportAnalyzer.cs b/DllImportGenerator/DllImportGenerator/Analyzers/GeneratedDllImportAnalyzer.cs index 3bedc018cf58..9f4146492583 100644 --- a/DllImportGenerator/DllImportGenerator/Analyzers/GeneratedDllImportAnalyzer.cs +++ b/DllImportGenerator/DllImportGenerator/Analyzers/GeneratedDllImportAnalyzer.cs @@ -5,7 +5,7 @@ using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; - +using Microsoft.Interop.SourceGeneration; using static Microsoft.Interop.Analyzers.AnalyzerDiagnostics; namespace Microsoft.Interop.Analyzers diff --git a/DllImportGenerator/DllImportGenerator/Analyzers/ManualTypeMarshallingAnalyzer.cs b/DllImportGenerator/DllImportGenerator/Analyzers/ManualTypeMarshallingAnalyzer.cs index 97bc59387711..f618742ed9bf 100644 --- a/DllImportGenerator/DllImportGenerator/Analyzers/ManualTypeMarshallingAnalyzer.cs +++ b/DllImportGenerator/DllImportGenerator/Analyzers/ManualTypeMarshallingAnalyzer.cs @@ -4,7 +4,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; - +using Microsoft.Interop.SourceGeneration; using static Microsoft.Interop.Analyzers.AnalyzerDiagnostics; namespace Microsoft.Interop.Analyzers diff --git a/DllImportGenerator/DllImportGenerator/DllImportGenerator.csproj b/DllImportGenerator/DllImportGenerator/DllImportGenerator.csproj index c0c8bc14dbc4..3409e73485e4 100644 --- a/DllImportGenerator/DllImportGenerator/DllImportGenerator.csproj +++ b/DllImportGenerator/DllImportGenerator/DllImportGenerator.csproj @@ -9,18 +9,7 @@ true Preview enable - Microsoft.Interop - - - - Microsoft - https://github.com/dotnet/runtimelab/tree/feature/DllImportGenerator - https://github.com/dotnet/runtimelab/tree/feature/DllImportGenerator - false - DllImportGenerator - Summary of changes made in this release of the package. - Copyright - DllImportGenerator, analyzers + Microsoft.Interop.DllImportGenerator true @@ -39,7 +28,8 @@ - + @@ -56,15 +46,4 @@ Resources.Designer.cs - - - - - - - - - - - diff --git a/DllImportGenerator/DllImportGenerator/DllImportStub.cs b/DllImportGenerator/DllImportGenerator/DllImportStub.cs index ba336d36ed41..789e9a5308f6 100644 --- a/DllImportGenerator/DllImportGenerator/DllImportStub.cs +++ b/DllImportGenerator/DllImportGenerator/DllImportStub.cs @@ -7,6 +7,7 @@ using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.Interop.SourceGeneration; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; namespace Microsoft.Interop diff --git a/DllImportGenerator/DllImportGenerator/ForwarderMarshallingGeneratorFactory.cs b/DllImportGenerator/DllImportGenerator/ForwarderMarshallingGeneratorFactory.cs index 60c85b4baba0..d6261c6fa464 100644 --- a/DllImportGenerator/DllImportGenerator/ForwarderMarshallingGeneratorFactory.cs +++ b/DllImportGenerator/DllImportGenerator/ForwarderMarshallingGeneratorFactory.cs @@ -1,4 +1,5 @@ -using System; +using Microsoft.Interop.SourceGeneration; +using System; using System.Collections.Generic; using System.Text; diff --git a/DllImportGenerator/DllImportGenerator/GeneratorDiagnostics.cs b/DllImportGenerator/DllImportGenerator/GeneratorDiagnostics.cs index 6a103ccc71d4..73e674450514 100644 --- a/DllImportGenerator/DllImportGenerator/GeneratorDiagnostics.cs +++ b/DllImportGenerator/DllImportGenerator/GeneratorDiagnostics.cs @@ -1,4 +1,5 @@ using Microsoft.CodeAnalysis; +using Microsoft.Interop.SourceGeneration; using System; using System.Collections.Generic; using System.Diagnostics; @@ -6,11 +7,10 @@ namespace Microsoft.Interop { - /// /// Class for reporting diagnostics in the DLL import generator /// - public class GeneratorDiagnostics : IGeneratorDiagnostics + internal class GeneratorDiagnostics : IGeneratorDiagnostics { public class Ids { diff --git a/DllImportGenerator/DllImportGenerator/LanguageSupport.cs b/DllImportGenerator/DllImportGenerator/LanguageSupport.cs deleted file mode 100644 index ddf2c4203111..000000000000 --- a/DllImportGenerator/DllImportGenerator/LanguageSupport.cs +++ /dev/null @@ -1,10 +0,0 @@ -// 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 - {} -} \ No newline at end of file diff --git a/DllImportGenerator/DllImportGenerator/NoPreserveSigMarshallingGeneratorFactory.cs b/DllImportGenerator/DllImportGenerator/NoPreserveSigMarshallingGeneratorFactory.cs index d0ed18a3520a..9c771a5f39fc 100644 --- a/DllImportGenerator/DllImportGenerator/NoPreserveSigMarshallingGeneratorFactory.cs +++ b/DllImportGenerator/DllImportGenerator/NoPreserveSigMarshallingGeneratorFactory.cs @@ -1,5 +1,6 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.Interop.SourceGeneration; using System; using System.Collections.Generic; using System.Text; diff --git a/DllImportGenerator/DllImportGenerator/PInvokeStubCodeGenerator.cs b/DllImportGenerator/DllImportGenerator/PInvokeStubCodeGenerator.cs index 3bc4db993535..d22e40197cbf 100644 --- a/DllImportGenerator/DllImportGenerator/PInvokeStubCodeGenerator.cs +++ b/DllImportGenerator/DllImportGenerator/PInvokeStubCodeGenerator.cs @@ -6,6 +6,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.Interop.SourceGeneration; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; namespace Microsoft.Interop diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/ArrayMarshallingCodeContext.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/ArrayMarshallingCodeContext.cs index 9e8d1ab5a200..2b581ee77414 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/ArrayMarshallingCodeContext.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/ArrayMarshallingCodeContext.cs @@ -8,7 +8,7 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -namespace Microsoft.Interop +namespace Microsoft.Interop.SourceGeneration { internal sealed class ArrayMarshallingCodeContext : StubCodeContext { diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/IGeneratorDiagnostics.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/IGeneratorDiagnostics.cs index fb01f60070d2..7a3e830e8311 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/IGeneratorDiagnostics.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/IGeneratorDiagnostics.cs @@ -5,9 +5,9 @@ using Microsoft.CodeAnalysis; -namespace Microsoft.Interop +namespace Microsoft.Interop.SourceGeneration { - public static class DiagnosticExtensions + internal static class DiagnosticExtensions { public static Diagnostic CreateDiagnostic( this ISymbol symbol, @@ -42,7 +42,7 @@ public static Diagnostic CreateDiagnostic( } } - public interface IGeneratorDiagnostics + internal interface IGeneratorDiagnostics { /// /// Report diagnostic for marshalling of a parameter/return that is not supported @@ -67,7 +67,7 @@ void ReportConfigurationNotSupported( string? unsupportedValue); } - public static class IGeneratorDiagnosticsExtensions + internal static class IGeneratorDiagnosticsExtensions { public static void ReportConfigurationNotSupported(this IGeneratorDiagnostics diagnostics, AttributeData attributeData, string configurationName) => diagnostics.ReportConfigurationNotSupported(attributeData, configurationName, null); diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/InteropGenerationOptions.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/InteropGenerationOptions.cs index d65ea4cb67ee..014dacec09a6 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/InteropGenerationOptions.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/InteropGenerationOptions.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Text; -namespace Microsoft.Interop +namespace Microsoft.Interop.SourceGeneration { - public record InteropGenerationOptions(bool UseMarshalType); + internal record InteropGenerationOptions(bool UseMarshalType); } diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/ManualTypeMarshallingHelper.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/ManualTypeMarshallingHelper.cs index 7f86b833665c..bb8e3a5a6c23 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/ManualTypeMarshallingHelper.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/ManualTypeMarshallingHelper.cs @@ -2,9 +2,9 @@ using System.Linq; using Microsoft.CodeAnalysis; -namespace Microsoft.Interop +namespace Microsoft.Interop.SourceGeneration { - public static class ManualTypeMarshallingHelper + internal static class ManualTypeMarshallingHelper { public const string ValuePropertyName = "Value"; public const string GetPinnableReferenceName = "GetPinnableReference"; diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/BlittableArrayMarshaller.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/BlittableArrayMarshaller.cs index a1bba95c3932..57127a1d7c57 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/BlittableArrayMarshaller.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/BlittableArrayMarshaller.cs @@ -5,9 +5,9 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -namespace Microsoft.Interop +namespace Microsoft.Interop.SourceGeneration { - public sealed class BlittableArrayMarshaller : ConditionalStackallocMarshallingGenerator + internal sealed class BlittableArrayMarshaller : ConditionalStackallocMarshallingGenerator { /// /// Stack-alloc threshold set to 256 bytes to enable small arrays to be passed on the stack. diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/BlittableMarshaller.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/BlittableMarshaller.cs index 817734c0d38f..551653e6b488 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/BlittableMarshaller.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/BlittableMarshaller.cs @@ -5,9 +5,9 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -namespace Microsoft.Interop +namespace Microsoft.Interop.SourceGeneration { - public sealed class BlittableMarshaller : IMarshallingGenerator + internal sealed class BlittableMarshaller : IMarshallingGenerator { public TypeSyntax AsNativeType(TypePositionInfo info) { diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/BoolMarshaller.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/BoolMarshaller.cs index b20bf1e2e4ed..3ae9be4458a8 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/BoolMarshaller.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/BoolMarshaller.cs @@ -6,9 +6,9 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -namespace Microsoft.Interop +namespace Microsoft.Interop.SourceGeneration { - public abstract class BoolMarshallerBase : IMarshallingGenerator + internal abstract class BoolMarshallerBase : IMarshallingGenerator { private readonly PredefinedTypeSyntax _nativeType; private readonly int _trueValue; @@ -114,7 +114,7 @@ public IEnumerable Generate(TypePositionInfo info, StubCodeCont /// and C++, but those is implementation defined. /// Consult your compiler specification. /// - public sealed class ByteBoolMarshaller : BoolMarshallerBase + internal sealed class ByteBoolMarshaller : BoolMarshallerBase { public ByteBoolMarshaller() : base(PredefinedType(Token(SyntaxKind.ByteKeyword)), trueValue: 1, falseValue: 0, compareToTrue: false) @@ -128,7 +128,7 @@ public ByteBoolMarshaller() /// /// Corresponds to the definition of BOOL. /// - public sealed class WinBoolMarshaller : BoolMarshallerBase + internal sealed class WinBoolMarshaller : BoolMarshallerBase { public WinBoolMarshaller() : base(PredefinedType(Token(SyntaxKind.IntKeyword)), trueValue: 1, falseValue: 0, compareToTrue: false) @@ -139,7 +139,7 @@ public WinBoolMarshaller() /// /// Marshal a boolean value as a VARIANT_BOOL (Windows OLE/Automation type). /// - public sealed class VariantBoolMarshaller : BoolMarshallerBase + internal sealed class VariantBoolMarshaller : BoolMarshallerBase { private const short VARIANT_TRUE = -1; private const short VARIANT_FALSE = 0; diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/CharMarshaller.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/CharMarshaller.cs index ba193ce4d802..ed43faac3f51 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/CharMarshaller.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/CharMarshaller.cs @@ -7,9 +7,9 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -namespace Microsoft.Interop +namespace Microsoft.Interop.SourceGeneration { - public sealed class Utf16CharMarshaller : IMarshallingGenerator + internal sealed class Utf16CharMarshaller : IMarshallingGenerator { private static readonly PredefinedTypeSyntax NativeType = PredefinedType(Token(SyntaxKind.UShortKeyword)); diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/ConditionalStackallocMarshallingGenerator.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/ConditionalStackallocMarshallingGenerator.cs index f0bde9de1903..034322b1f6b9 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/ConditionalStackallocMarshallingGenerator.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/ConditionalStackallocMarshallingGenerator.cs @@ -4,9 +4,9 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -namespace Microsoft.Interop +namespace Microsoft.Interop.SourceGeneration { - public abstract class ConditionalStackallocMarshallingGenerator : IMarshallingGenerator + internal abstract class ConditionalStackallocMarshallingGenerator : IMarshallingGenerator { protected static string GetAllocationMarkerIdentifier(string managedIdentifier) => $"{managedIdentifier}__allocated"; diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/CustomNativeTypeMarshaller.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/CustomNativeTypeMarshaller.cs index 155ad5e7a9bd..b3f0e5ce8996 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/CustomNativeTypeMarshaller.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/CustomNativeTypeMarshaller.cs @@ -6,9 +6,9 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -namespace Microsoft.Interop +namespace Microsoft.Interop.SourceGeneration { - public sealed class CustomNativeTypeMarshaller : IMarshallingGenerator + internal sealed class CustomNativeTypeMarshaller : IMarshallingGenerator { private const string MarshalerLocalSuffix = "__marshaler"; private readonly TypeSyntax _nativeTypeSyntax; diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/DelegateMarshaller.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/DelegateMarshaller.cs index 45432ec384cf..ee30df792973 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/DelegateMarshaller.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/DelegateMarshaller.cs @@ -4,9 +4,9 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -namespace Microsoft.Interop +namespace Microsoft.Interop.SourceGeneration { - public sealed class DelegateMarshaller : IMarshallingGenerator + internal sealed class DelegateMarshaller : IMarshallingGenerator { public TypeSyntax AsNativeType(TypePositionInfo info) { diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/Forwarder.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/Forwarder.cs index 34c9c7119f06..31bf925be2e1 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/Forwarder.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/Forwarder.cs @@ -4,9 +4,9 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -namespace Microsoft.Interop +namespace Microsoft.Interop.SourceGeneration { - public sealed class Forwarder : IMarshallingGenerator + internal sealed class Forwarder : IMarshallingGenerator { public TypeSyntax AsNativeType(TypePositionInfo info) { diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/HResultExceptionMarshaller.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/HResultExceptionMarshaller.cs index 360d2b26216e..3d6994c2ee77 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/HResultExceptionMarshaller.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/HResultExceptionMarshaller.cs @@ -7,9 +7,9 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -namespace Microsoft.Interop +namespace Microsoft.Interop.SourceGeneration { - public sealed class HResultExceptionMarshaller : IMarshallingGenerator + internal sealed class HResultExceptionMarshaller : IMarshallingGenerator { private static readonly TypeSyntax NativeType = PredefinedType(Token(SyntaxKind.IntKeyword)); diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallerHelpers.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallerHelpers.cs index e4145d3e9bb8..30361975a20a 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallerHelpers.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallerHelpers.cs @@ -3,9 +3,9 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -namespace Microsoft.Interop +namespace Microsoft.Interop.SourceGeneration { - public static class MarshallerHelpers + internal static class MarshallerHelpers { public static readonly ExpressionSyntax IsWindows = InvocationExpression( MemberAccessExpression( diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGenerator.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGenerator.cs index 63653d2884ce..b2205f2136ec 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGenerator.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGenerator.cs @@ -3,12 +3,12 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; -namespace Microsoft.Interop +namespace Microsoft.Interop.SourceGeneration { /// /// Interface for generation of marshalling code for P/Invoke stubs /// - public interface IMarshallingGenerator + internal interface IMarshallingGenerator { /// /// Get the native type syntax for @@ -71,7 +71,7 @@ public interface IMarshallingGenerator /// /// Exception used to indicate marshalling isn't supported. /// - public sealed class MarshallingNotSupportedException : Exception + internal sealed class MarshallingNotSupportedException : Exception { /// /// Construct a new instance. diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGeneratorFactory.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGeneratorFactory.cs index fa6b66a1d966..2576edc57273 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGeneratorFactory.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGeneratorFactory.cs @@ -5,9 +5,9 @@ using Microsoft.CodeAnalysis.Diagnostics; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -namespace Microsoft.Interop +namespace Microsoft.Interop.SourceGeneration { - public interface IMarshallingGeneratorFactory + internal interface IMarshallingGeneratorFactory { /// /// Create an instance for marshalling the supplied type in the given position. @@ -20,7 +20,7 @@ public IMarshallingGenerator Create( StubCodeContext context); } - public sealed class DefaultMarshallingGeneratorFactory : IMarshallingGeneratorFactory + internal sealed class DefaultMarshallingGeneratorFactory : IMarshallingGeneratorFactory { private static readonly ByteBoolMarshaller ByteBool = new(); private static readonly WinBoolMarshaller WinBool = new(); diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/NonBlittableArrayMarshaller.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/NonBlittableArrayMarshaller.cs index 9c1755ab9341..70136cd85d5a 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/NonBlittableArrayMarshaller.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/NonBlittableArrayMarshaller.cs @@ -6,9 +6,9 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -namespace Microsoft.Interop +namespace Microsoft.Interop.SourceGeneration { - public sealed class NonBlittableArrayMarshaller : ConditionalStackallocMarshallingGenerator + internal sealed class NonBlittableArrayMarshaller : ConditionalStackallocMarshallingGenerator { /// /// Stack-alloc threshold set to 256 bytes to enable small arrays to be passed on the stack. diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/SafeHandleMarshaller.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/SafeHandleMarshaller.cs index b4536cbcfe39..54d2100b42f5 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/SafeHandleMarshaller.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/SafeHandleMarshaller.cs @@ -6,9 +6,9 @@ using Microsoft.CodeAnalysis.Diagnostics; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -namespace Microsoft.Interop +namespace Microsoft.Interop.SourceGeneration { - public sealed class SafeHandleMarshaller : IMarshallingGenerator + internal sealed class SafeHandleMarshaller : IMarshallingGenerator { private static readonly TypeSyntax NativeType = ParseTypeName("global::System.IntPtr"); diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Ansi.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Ansi.cs index 16e1f026606d..7edc11aba2d0 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Ansi.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Ansi.cs @@ -5,11 +5,11 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -using static Microsoft.Interop.MarshallerHelpers; +using static Microsoft.Interop.SourceGeneration.MarshallerHelpers; -namespace Microsoft.Interop +namespace Microsoft.Interop.SourceGeneration { - public sealed class AnsiStringMarshaller : ConditionalStackallocMarshallingGenerator + internal sealed class AnsiStringMarshaller : ConditionalStackallocMarshallingGenerator { private static readonly TypeSyntax NativeType = PointerType(PredefinedType(Token(SyntaxKind.ByteKeyword))); diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.PlatformDefined.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.PlatformDefined.cs index 3de4c48a724b..02ee37d53c91 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.PlatformDefined.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.PlatformDefined.cs @@ -6,11 +6,11 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -using static Microsoft.Interop.MarshallerHelpers; +using static Microsoft.Interop.SourceGeneration.MarshallerHelpers; -namespace Microsoft.Interop +namespace Microsoft.Interop.SourceGeneration { - public sealed class PlatformDefinedStringMarshaller : ConditionalStackallocMarshallingGenerator + internal sealed class PlatformDefinedStringMarshaller : ConditionalStackallocMarshallingGenerator { private static readonly TypeSyntax NativeType = PointerType(PredefinedType(Token(SyntaxKind.VoidKeyword))); diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Utf16.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Utf16.cs index 9623967cf6e4..38b77525c3d1 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Utf16.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Utf16.cs @@ -4,11 +4,11 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -using static Microsoft.Interop.MarshallerHelpers; +using static Microsoft.Interop.SourceGeneration.MarshallerHelpers; -namespace Microsoft.Interop +namespace Microsoft.Interop.SourceGeneration { - public sealed class Utf16StringMarshaller : ConditionalStackallocMarshallingGenerator + internal sealed class Utf16StringMarshaller : ConditionalStackallocMarshallingGenerator { // [Compat] Equivalent of MAX_PATH on Windows to match built-in system // The assumption is file paths are the most common case for marshalling strings, diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Utf8.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Utf8.cs index 2a4801e8d3c3..c082cccbefea 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Utf8.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Utf8.cs @@ -4,11 +4,11 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -using static Microsoft.Interop.MarshallerHelpers; +using static Microsoft.Interop.SourceGeneration.MarshallerHelpers; -namespace Microsoft.Interop +namespace Microsoft.Interop.SourceGeneration { - public sealed class Utf8StringMarshaller : ConditionalStackallocMarshallingGenerator + internal sealed class Utf8StringMarshaller : ConditionalStackallocMarshallingGenerator { // [Compat] Equivalent of MAX_PATH on Windows to match built-in system // The assumption is file paths are the most common case for marshalling strings, diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/MarshallingAttributeInfo.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/MarshallingAttributeInfo.cs index 88c378919ea0..7a7790d5be54 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/MarshallingAttributeInfo.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/MarshallingAttributeInfo.cs @@ -4,21 +4,17 @@ using System.Diagnostics; using System.Runtime.InteropServices; -namespace Microsoft.Interop +namespace Microsoft.Interop.SourceGeneration { // The following types are modeled to fit with the current prospective spec // for C# 10 discriminated unions. Once discriminated unions are released, // these should be updated to be implemented as a discriminated union. - public abstract record MarshallingInfo + internal abstract record MarshallingInfo { - // Add a constructor that can only be called by derived types in the same assembly - // to enforce that this type cannot be extended by users of this library. - private protected MarshallingInfo() - {} } - public sealed record NoMarshallingInfo : MarshallingInfo + internal sealed record NoMarshallingInfo : MarshallingInfo { public static readonly MarshallingInfo Instance = new NoMarshallingInfo(); @@ -28,7 +24,7 @@ private NoMarshallingInfo() { } /// /// Character encoding enumeration. /// - public enum CharEncoding + internal enum CharEncoding { Undefined, Utf8, @@ -40,20 +36,20 @@ public enum CharEncoding /// /// Details that are required when scenario supports strings. /// - public record MarshallingInfoStringSupport( + internal record MarshallingInfoStringSupport( CharEncoding CharEncoding ) : MarshallingInfo; /// /// Simple User-application of System.Runtime.InteropServices.MarshalAsAttribute /// - public record MarshalAsInfo( + internal record MarshalAsInfo( UnmanagedType UnmanagedType, CharEncoding CharEncoding) : MarshallingInfoStringSupport(CharEncoding) { } - public enum UnmanagedArrayType + internal enum UnmanagedArrayType { LPArray = UnmanagedType.LPArray, ByValArray = UnmanagedType.ByValArray @@ -62,7 +58,7 @@ public enum UnmanagedArrayType /// /// User-applied System.Runtime.InteropServices.MarshalAsAttribute with array marshalling info /// - public sealed record ArrayMarshalAsInfo( + internal sealed record ArrayMarshalAsInfo( UnmanagedArrayType UnmanagedArrayType, int ArraySizeConst, short ArraySizeParamIndex, @@ -77,10 +73,10 @@ public sealed record ArrayMarshalAsInfo( /// or System.Runtime.InteropServices.GeneratedMarshallingAttribute on a blittable type /// in source in this compilation. /// - public sealed record BlittableTypeAttributeInfo : MarshallingInfo; + internal sealed record BlittableTypeAttributeInfo : MarshallingInfo; [Flags] - public enum SupportedMarshallingMethods + internal enum SupportedMarshallingMethods { ManagedToNative = 0x1, NativeToManaged = 0x2, @@ -91,7 +87,7 @@ public enum SupportedMarshallingMethods /// /// User-applied System.Runtime.InteropServices.NativeMarshallingAttribute /// - public sealed record NativeMarshallingAttributeInfo( + internal sealed record NativeMarshallingAttributeInfo( ITypeSymbol NativeMarshallingType, ITypeSymbol? ValuePropertyType, SupportedMarshallingMethods MarshallingMethods, @@ -101,17 +97,17 @@ public sealed record NativeMarshallingAttributeInfo( /// User-applied System.Runtime.InteropServices.GeneratedMarshallingAttribute /// on a non-blittable type in source in this compilation. /// - public sealed record GeneratedNativeMarshallingAttributeInfo( + internal sealed record GeneratedNativeMarshallingAttributeInfo( string NativeMarshallingFullyQualifiedTypeName) : MarshallingInfo; /// /// The type of the element is a SafeHandle-derived type with no marshalling attributes. /// - public sealed record SafeHandleMarshallingInfo(bool AccessibleDefaultConstructor) : MarshallingInfo; + internal sealed record SafeHandleMarshallingInfo(bool AccessibleDefaultConstructor) : MarshallingInfo; /// /// Default marshalling for arrays /// - public sealed record ArrayMarshallingInfo(MarshallingInfo ElementMarshallingInfo) : MarshallingInfo; + internal sealed record ArrayMarshallingInfo(MarshallingInfo ElementMarshallingInfo) : MarshallingInfo; } diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj index 703bce87fd4f..159264372579 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj @@ -2,13 +2,15 @@ netstandard2.0 - false enable - Microsoft.Interop + Microsoft.Interop.SourceGeneration + false + True + true - + @@ -17,13 +19,13 @@ True True - - - Designer Resources.Designer.cs ResXFileCodeGenerator + Microsoft.Interop.SourceGenerationResources + + diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Resources.Designer.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Resources.Designer.cs index c451a2bece59..90121a74e5a1 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Resources.Designer.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Resources.Designer.cs @@ -8,7 +8,7 @@ // //------------------------------------------------------------------------------ -namespace Microsoft.Interop { +namespace Microsoft.Interop.SourceGeneration { using System; @@ -39,7 +39,7 @@ internal Resources() { internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.Interop.Resources", typeof(Resources).Assembly); + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.Interop.SourceGeneration.Resources", typeof(Resources).Assembly); resourceMan = temp; } return resourceMan; @@ -213,6 +213,15 @@ internal static string SafeHandleByRefMustBeConcrete { } } + /// + /// Looks up a localized string similar to . + /// + internal static string Test { + get { + return ResourceManager.GetString("Test", resourceCulture); + } + } + /// /// Looks up a localized string similar to Specified type is not supported by source-generated P/Invokes. /// diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Resources.resx b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Resources.resx index d21ad29d3da4..bf9eeca37c4f 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Resources.resx +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Resources.resx @@ -168,6 +168,9 @@ An abstract type derived from 'SafeHandle' cannot be marshalled by reference. The provided type must be concrete. + + + Specified type is not supported by source-generated P/Invokes diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/StubCodeContext.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/StubCodeContext.cs index 9b212d35735e..e6a2b6511480 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/StubCodeContext.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/StubCodeContext.cs @@ -1,8 +1,8 @@ using System; -namespace Microsoft.Interop +namespace Microsoft.Interop.SourceGeneration { - public abstract class StubCodeContext + internal abstract class StubCodeContext { /// /// Code generation stage diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/TypeNames.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/TypeNames.cs index 1a640a2c395e..d4b1f1d9d54c 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/TypeNames.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/TypeNames.cs @@ -4,7 +4,7 @@ using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.Interop; -namespace Microsoft.Interop +namespace Microsoft.Interop.SourceGeneration { static class TypeNames { diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/TypePositionInfo.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/TypePositionInfo.cs index 79ae33ec11f4..60a8de4bb073 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/TypePositionInfo.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/TypePositionInfo.cs @@ -7,12 +7,12 @@ using Microsoft.CodeAnalysis.CSharp; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -namespace Microsoft.Interop +namespace Microsoft.Interop.SourceGeneration { /// /// Type used to pass on default marshalling details. /// - public sealed record DefaultMarshallingInfo ( + internal sealed record DefaultMarshallingInfo ( CharEncoding CharEncoding ); @@ -23,7 +23,7 @@ CharEncoding CharEncoding /// contents of the managed array. /// [Flags] - public enum ByValueContentsMarshalKind + internal enum ByValueContentsMarshalKind { /// /// Marshal contents from managed to native only. @@ -48,7 +48,7 @@ public enum ByValueContentsMarshalKind /// /// Positional type information involved in unmanaged/managed scenarios. /// - public sealed record TypePositionInfo + internal sealed record TypePositionInfo { public const int UnsetIndex = int.MinValue; public const int ReturnIndex = UnsetIndex + 1; diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/TypeSymbolExtensions.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/TypeSymbolExtensions.cs index 92ae1214e31a..249471e3ca03 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/TypeSymbolExtensions.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/TypeSymbolExtensions.cs @@ -9,9 +9,9 @@ using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; -namespace Microsoft.Interop +namespace Microsoft.Interop.SourceGeneration { - public static class TypeSymbolExtensions + internal static class TypeSymbolExtensions { public static bool HasOnlyBlittableFields(this ITypeSymbol type) { From a31ac5ff23724b6706291d3ea3831a64bc5eb990 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Tue, 18 May 2021 10:55:56 -0700 Subject: [PATCH 06/12] Fix visibility and resource weirdness. --- .../DllImportGenerator/DllImportGenerator.csproj | 6 ++++-- .../DllImportGenerator/GeneratorDiagnostics.cs | 4 ++-- .../Microsoft.Interop.SourceGeneration.csproj | 1 - 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/DllImportGenerator/DllImportGenerator/DllImportGenerator.csproj b/DllImportGenerator/DllImportGenerator/DllImportGenerator.csproj index 3409e73485e4..544304fd71a4 100644 --- a/DllImportGenerator/DllImportGenerator/DllImportGenerator.csproj +++ b/DllImportGenerator/DllImportGenerator/DllImportGenerator.csproj @@ -28,8 +28,9 @@ - + + @@ -44,6 +45,7 @@ ResXFileCodeGenerator Resources.Designer.cs + Microsoft.Interop.Resources.resources diff --git a/DllImportGenerator/DllImportGenerator/GeneratorDiagnostics.cs b/DllImportGenerator/DllImportGenerator/GeneratorDiagnostics.cs index 73e674450514..ed5cf1d66787 100644 --- a/DllImportGenerator/DllImportGenerator/GeneratorDiagnostics.cs +++ b/DllImportGenerator/DllImportGenerator/GeneratorDiagnostics.cs @@ -10,7 +10,7 @@ namespace Microsoft.Interop /// /// Class for reporting diagnostics in the DLL import generator /// - internal class GeneratorDiagnostics : IGeneratorDiagnostics + public class GeneratorDiagnostics : IGeneratorDiagnostics { public class Ids { @@ -153,7 +153,7 @@ public void ReportConfigurationNotSupported( /// Method with the parameter/return /// Type info for the parameter/return /// [Optional] Specific reason for lack of support - public void ReportMarshallingNotSupported( + void IGeneratorDiagnostics.ReportMarshallingNotSupported( IMethodSymbol method, TypePositionInfo info, string? notSupportedDetails) diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj index 159264372579..02d8201acd88 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj @@ -23,7 +23,6 @@ Designer Resources.Designer.cs ResXFileCodeGenerator - Microsoft.Interop.SourceGenerationResources From 22a372ed0572306fb885de6d3ebdff7e36f93fae Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Tue, 18 May 2021 11:34:41 -0700 Subject: [PATCH 07/12] Add a non-boilerplate description for Ancillary.Interop to satisfy package analysis. --- DllImportGenerator/Ancillary.Interop/Ancillary.Interop.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/DllImportGenerator/Ancillary.Interop/Ancillary.Interop.csproj b/DllImportGenerator/Ancillary.Interop/Ancillary.Interop.csproj index 7af1a40c40bc..663c0cfee10b 100644 --- a/DllImportGenerator/Ancillary.Interop/Ancillary.Interop.csproj +++ b/DllImportGenerator/Ancillary.Interop/Ancillary.Interop.csproj @@ -7,6 +7,7 @@ System.Runtime.InteropServices enable true + APIs required for usage of the DllImportGenerator and related tools. From d2050fd100477512647dcab1e303b381e406caed Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Fri, 21 May 2021 13:23:25 -0700 Subject: [PATCH 08/12] Revert "Fix visibility and resource weirdness." This reverts commit a31ac5ff23724b6706291d3ea3831a64bc5eb990. --- .../DllImportGenerator/DllImportGenerator.csproj | 6 ++---- .../DllImportGenerator/GeneratorDiagnostics.cs | 4 ++-- .../Microsoft.Interop.SourceGeneration.csproj | 1 + 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/DllImportGenerator/DllImportGenerator/DllImportGenerator.csproj b/DllImportGenerator/DllImportGenerator/DllImportGenerator.csproj index 544304fd71a4..3409e73485e4 100644 --- a/DllImportGenerator/DllImportGenerator/DllImportGenerator.csproj +++ b/DllImportGenerator/DllImportGenerator/DllImportGenerator.csproj @@ -28,9 +28,8 @@ - - + @@ -45,7 +44,6 @@ ResXFileCodeGenerator Resources.Designer.cs - Microsoft.Interop.Resources.resources diff --git a/DllImportGenerator/DllImportGenerator/GeneratorDiagnostics.cs b/DllImportGenerator/DllImportGenerator/GeneratorDiagnostics.cs index ed5cf1d66787..73e674450514 100644 --- a/DllImportGenerator/DllImportGenerator/GeneratorDiagnostics.cs +++ b/DllImportGenerator/DllImportGenerator/GeneratorDiagnostics.cs @@ -10,7 +10,7 @@ namespace Microsoft.Interop /// /// Class for reporting diagnostics in the DLL import generator /// - public class GeneratorDiagnostics : IGeneratorDiagnostics + internal class GeneratorDiagnostics : IGeneratorDiagnostics { public class Ids { @@ -153,7 +153,7 @@ public void ReportConfigurationNotSupported( /// Method with the parameter/return /// Type info for the parameter/return /// [Optional] Specific reason for lack of support - void IGeneratorDiagnostics.ReportMarshallingNotSupported( + public void ReportMarshallingNotSupported( IMethodSymbol method, TypePositionInfo info, string? notSupportedDetails) diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj index 02d8201acd88..159264372579 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj @@ -23,6 +23,7 @@ Designer Resources.Designer.cs ResXFileCodeGenerator + Microsoft.Interop.SourceGenerationResources From 0a3354b9b4220ca5e800c922d64a514c3543f194 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Fri, 21 May 2021 13:23:35 -0700 Subject: [PATCH 09/12] Revert "Convert Microsoft.Interop.SourceGeneration to a source package." This reverts commit 458ccab3620fc0c1ff56c5de59dfcde7e20af5a7. --- DllImportGenerator/Directory.Build.props | 13 -------- .../ConvertToGeneratedDllImportAnalyzer.cs | 2 +- .../Analyzers/GeneratedDllImportAnalyzer.cs | 2 +- .../ManualTypeMarshallingAnalyzer.cs | 2 +- .../DllImportGenerator.csproj | 27 ++++++++++++++-- .../DllImportGenerator/DllImportStub.cs | 1 - .../ForwarderMarshallingGeneratorFactory.cs | 3 +- .../GeneratorDiagnostics.cs | 4 +-- .../DllImportGenerator/LanguageSupport.cs | 10 ++++++ ...oPreserveSigMarshallingGeneratorFactory.cs | 1 - .../PInvokeStubCodeGenerator.cs | 1 - .../ArrayMarshallingCodeContext.cs | 2 +- .../IGeneratorDiagnostics.cs | 8 ++--- .../InteropGenerationOptions.cs | 4 +-- .../ManualTypeMarshallingHelper.cs | 4 +-- .../Marshalling/BlittableArrayMarshaller.cs | 4 +-- .../Marshalling/BlittableMarshaller.cs | 4 +-- .../Marshalling/BoolMarshaller.cs | 10 +++--- .../Marshalling/CharMarshaller.cs | 4 +-- ...nditionalStackallocMarshallingGenerator.cs | 4 +-- .../Marshalling/CustomNativeTypeMarshaller.cs | 4 +-- .../Marshalling/DelegateMarshaller.cs | 4 +-- .../Marshalling/Forwarder.cs | 4 +-- .../Marshalling/HResultExceptionMarshaller.cs | 4 +-- .../Marshalling/MarshallerHelpers.cs | 4 +-- .../Marshalling/MarshallingGenerator.cs | 6 ++-- .../MarshallingGeneratorFactory.cs | 6 ++-- .../NonBlittableArrayMarshaller.cs | 4 +-- .../Marshalling/SafeHandleMarshaller.cs | 4 +-- .../Marshalling/StringMarshaller.Ansi.cs | 6 ++-- .../StringMarshaller.PlatformDefined.cs | 6 ++-- .../Marshalling/StringMarshaller.Utf16.cs | 6 ++-- .../Marshalling/StringMarshaller.Utf8.cs | 6 ++-- .../MarshallingAttributeInfo.cs | 32 +++++++++++-------- .../Microsoft.Interop.SourceGeneration.csproj | 14 ++++---- .../Resources.Designer.cs | 13 ++------ .../Resources.resx | 3 -- .../StubCodeContext.cs | 4 +-- .../TypeNames.cs | 2 +- .../TypePositionInfo.cs | 8 ++--- .../TypeSymbolExtensions.cs | 4 +-- 41 files changed, 129 insertions(+), 125 deletions(-) delete mode 100644 DllImportGenerator/Directory.Build.props create mode 100644 DllImportGenerator/DllImportGenerator/LanguageSupport.cs diff --git a/DllImportGenerator/Directory.Build.props b/DllImportGenerator/Directory.Build.props deleted file mode 100644 index 22565674b76a..000000000000 --- a/DllImportGenerator/Directory.Build.props +++ /dev/null @@ -1,13 +0,0 @@ - - - - Microsoft - https://github.com/dotnet/runtimelab/tree/feature/DllImportGenerator - https://github.com/dotnet/runtimelab/tree/feature/DllImportGenerator - false - DllImportGenerator - Summary of changes made in this release of the package. - Copyright - DllImportGenerator, analyzers - - \ No newline at end of file diff --git a/DllImportGenerator/DllImportGenerator/Analyzers/ConvertToGeneratedDllImportAnalyzer.cs b/DllImportGenerator/DllImportGenerator/Analyzers/ConvertToGeneratedDllImportAnalyzer.cs index 061205bb3f68..2df44242463e 100644 --- a/DllImportGenerator/DllImportGenerator/Analyzers/ConvertToGeneratedDllImportAnalyzer.cs +++ b/DllImportGenerator/DllImportGenerator/Analyzers/ConvertToGeneratedDllImportAnalyzer.cs @@ -4,7 +4,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.Interop.SourceGeneration; + using static Microsoft.Interop.Analyzers.AnalyzerDiagnostics; namespace Microsoft.Interop.Analyzers diff --git a/DllImportGenerator/DllImportGenerator/Analyzers/GeneratedDllImportAnalyzer.cs b/DllImportGenerator/DllImportGenerator/Analyzers/GeneratedDllImportAnalyzer.cs index 9f4146492583..3bedc018cf58 100644 --- a/DllImportGenerator/DllImportGenerator/Analyzers/GeneratedDllImportAnalyzer.cs +++ b/DllImportGenerator/DllImportGenerator/Analyzers/GeneratedDllImportAnalyzer.cs @@ -5,7 +5,7 @@ using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.Interop.SourceGeneration; + using static Microsoft.Interop.Analyzers.AnalyzerDiagnostics; namespace Microsoft.Interop.Analyzers diff --git a/DllImportGenerator/DllImportGenerator/Analyzers/ManualTypeMarshallingAnalyzer.cs b/DllImportGenerator/DllImportGenerator/Analyzers/ManualTypeMarshallingAnalyzer.cs index f618742ed9bf..97bc59387711 100644 --- a/DllImportGenerator/DllImportGenerator/Analyzers/ManualTypeMarshallingAnalyzer.cs +++ b/DllImportGenerator/DllImportGenerator/Analyzers/ManualTypeMarshallingAnalyzer.cs @@ -4,7 +4,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.Interop.SourceGeneration; + using static Microsoft.Interop.Analyzers.AnalyzerDiagnostics; namespace Microsoft.Interop.Analyzers diff --git a/DllImportGenerator/DllImportGenerator/DllImportGenerator.csproj b/DllImportGenerator/DllImportGenerator/DllImportGenerator.csproj index 3409e73485e4..c0c8bc14dbc4 100644 --- a/DllImportGenerator/DllImportGenerator/DllImportGenerator.csproj +++ b/DllImportGenerator/DllImportGenerator/DllImportGenerator.csproj @@ -9,7 +9,18 @@ true Preview enable - Microsoft.Interop.DllImportGenerator + Microsoft.Interop + + + + Microsoft + https://github.com/dotnet/runtimelab/tree/feature/DllImportGenerator + https://github.com/dotnet/runtimelab/tree/feature/DllImportGenerator + false + DllImportGenerator + Summary of changes made in this release of the package. + Copyright + DllImportGenerator, analyzers true @@ -28,8 +39,7 @@ - + @@ -46,4 +56,15 @@ Resources.Designer.cs + + + + + + + + + + + diff --git a/DllImportGenerator/DllImportGenerator/DllImportStub.cs b/DllImportGenerator/DllImportGenerator/DllImportStub.cs index 789e9a5308f6..ba336d36ed41 100644 --- a/DllImportGenerator/DllImportGenerator/DllImportStub.cs +++ b/DllImportGenerator/DllImportGenerator/DllImportStub.cs @@ -7,7 +7,6 @@ using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.Interop.SourceGeneration; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; namespace Microsoft.Interop diff --git a/DllImportGenerator/DllImportGenerator/ForwarderMarshallingGeneratorFactory.cs b/DllImportGenerator/DllImportGenerator/ForwarderMarshallingGeneratorFactory.cs index d6261c6fa464..60c85b4baba0 100644 --- a/DllImportGenerator/DllImportGenerator/ForwarderMarshallingGeneratorFactory.cs +++ b/DllImportGenerator/DllImportGenerator/ForwarderMarshallingGeneratorFactory.cs @@ -1,5 +1,4 @@ -using Microsoft.Interop.SourceGeneration; -using System; +using System; using System.Collections.Generic; using System.Text; diff --git a/DllImportGenerator/DllImportGenerator/GeneratorDiagnostics.cs b/DllImportGenerator/DllImportGenerator/GeneratorDiagnostics.cs index 73e674450514..6a103ccc71d4 100644 --- a/DllImportGenerator/DllImportGenerator/GeneratorDiagnostics.cs +++ b/DllImportGenerator/DllImportGenerator/GeneratorDiagnostics.cs @@ -1,5 +1,4 @@ using Microsoft.CodeAnalysis; -using Microsoft.Interop.SourceGeneration; using System; using System.Collections.Generic; using System.Diagnostics; @@ -7,10 +6,11 @@ namespace Microsoft.Interop { + /// /// Class for reporting diagnostics in the DLL import generator /// - internal class GeneratorDiagnostics : IGeneratorDiagnostics + public class GeneratorDiagnostics : IGeneratorDiagnostics { public class Ids { diff --git a/DllImportGenerator/DllImportGenerator/LanguageSupport.cs b/DllImportGenerator/DllImportGenerator/LanguageSupport.cs new file mode 100644 index 000000000000..ddf2c4203111 --- /dev/null +++ b/DllImportGenerator/DllImportGenerator/LanguageSupport.cs @@ -0,0 +1,10 @@ +// 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 + {} +} \ No newline at end of file diff --git a/DllImportGenerator/DllImportGenerator/NoPreserveSigMarshallingGeneratorFactory.cs b/DllImportGenerator/DllImportGenerator/NoPreserveSigMarshallingGeneratorFactory.cs index 9c771a5f39fc..d0ed18a3520a 100644 --- a/DllImportGenerator/DllImportGenerator/NoPreserveSigMarshallingGeneratorFactory.cs +++ b/DllImportGenerator/DllImportGenerator/NoPreserveSigMarshallingGeneratorFactory.cs @@ -1,6 +1,5 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.Interop.SourceGeneration; using System; using System.Collections.Generic; using System.Text; diff --git a/DllImportGenerator/DllImportGenerator/PInvokeStubCodeGenerator.cs b/DllImportGenerator/DllImportGenerator/PInvokeStubCodeGenerator.cs index d22e40197cbf..3bc4db993535 100644 --- a/DllImportGenerator/DllImportGenerator/PInvokeStubCodeGenerator.cs +++ b/DllImportGenerator/DllImportGenerator/PInvokeStubCodeGenerator.cs @@ -6,7 +6,6 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.Interop.SourceGeneration; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; namespace Microsoft.Interop diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/ArrayMarshallingCodeContext.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/ArrayMarshallingCodeContext.cs index 2b581ee77414..9e8d1ab5a200 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/ArrayMarshallingCodeContext.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/ArrayMarshallingCodeContext.cs @@ -8,7 +8,7 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -namespace Microsoft.Interop.SourceGeneration +namespace Microsoft.Interop { internal sealed class ArrayMarshallingCodeContext : StubCodeContext { diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/IGeneratorDiagnostics.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/IGeneratorDiagnostics.cs index 7a3e830e8311..fb01f60070d2 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/IGeneratorDiagnostics.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/IGeneratorDiagnostics.cs @@ -5,9 +5,9 @@ using Microsoft.CodeAnalysis; -namespace Microsoft.Interop.SourceGeneration +namespace Microsoft.Interop { - internal static class DiagnosticExtensions + public static class DiagnosticExtensions { public static Diagnostic CreateDiagnostic( this ISymbol symbol, @@ -42,7 +42,7 @@ public static Diagnostic CreateDiagnostic( } } - internal interface IGeneratorDiagnostics + public interface IGeneratorDiagnostics { /// /// Report diagnostic for marshalling of a parameter/return that is not supported @@ -67,7 +67,7 @@ void ReportConfigurationNotSupported( string? unsupportedValue); } - internal static class IGeneratorDiagnosticsExtensions + public static class IGeneratorDiagnosticsExtensions { public static void ReportConfigurationNotSupported(this IGeneratorDiagnostics diagnostics, AttributeData attributeData, string configurationName) => diagnostics.ReportConfigurationNotSupported(attributeData, configurationName, null); diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/InteropGenerationOptions.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/InteropGenerationOptions.cs index 014dacec09a6..d65ea4cb67ee 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/InteropGenerationOptions.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/InteropGenerationOptions.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Text; -namespace Microsoft.Interop.SourceGeneration +namespace Microsoft.Interop { - internal record InteropGenerationOptions(bool UseMarshalType); + public record InteropGenerationOptions(bool UseMarshalType); } diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/ManualTypeMarshallingHelper.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/ManualTypeMarshallingHelper.cs index bb8e3a5a6c23..7f86b833665c 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/ManualTypeMarshallingHelper.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/ManualTypeMarshallingHelper.cs @@ -2,9 +2,9 @@ using System.Linq; using Microsoft.CodeAnalysis; -namespace Microsoft.Interop.SourceGeneration +namespace Microsoft.Interop { - internal static class ManualTypeMarshallingHelper + public static class ManualTypeMarshallingHelper { public const string ValuePropertyName = "Value"; public const string GetPinnableReferenceName = "GetPinnableReference"; diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/BlittableArrayMarshaller.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/BlittableArrayMarshaller.cs index 57127a1d7c57..a1bba95c3932 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/BlittableArrayMarshaller.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/BlittableArrayMarshaller.cs @@ -5,9 +5,9 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -namespace Microsoft.Interop.SourceGeneration +namespace Microsoft.Interop { - internal sealed class BlittableArrayMarshaller : ConditionalStackallocMarshallingGenerator + public sealed class BlittableArrayMarshaller : ConditionalStackallocMarshallingGenerator { /// /// Stack-alloc threshold set to 256 bytes to enable small arrays to be passed on the stack. diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/BlittableMarshaller.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/BlittableMarshaller.cs index 551653e6b488..817734c0d38f 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/BlittableMarshaller.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/BlittableMarshaller.cs @@ -5,9 +5,9 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -namespace Microsoft.Interop.SourceGeneration +namespace Microsoft.Interop { - internal sealed class BlittableMarshaller : IMarshallingGenerator + public sealed class BlittableMarshaller : IMarshallingGenerator { public TypeSyntax AsNativeType(TypePositionInfo info) { diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/BoolMarshaller.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/BoolMarshaller.cs index 3ae9be4458a8..b20bf1e2e4ed 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/BoolMarshaller.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/BoolMarshaller.cs @@ -6,9 +6,9 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -namespace Microsoft.Interop.SourceGeneration +namespace Microsoft.Interop { - internal abstract class BoolMarshallerBase : IMarshallingGenerator + public abstract class BoolMarshallerBase : IMarshallingGenerator { private readonly PredefinedTypeSyntax _nativeType; private readonly int _trueValue; @@ -114,7 +114,7 @@ public IEnumerable Generate(TypePositionInfo info, StubCodeCont /// and C++, but those is implementation defined. /// Consult your compiler specification. /// - internal sealed class ByteBoolMarshaller : BoolMarshallerBase + public sealed class ByteBoolMarshaller : BoolMarshallerBase { public ByteBoolMarshaller() : base(PredefinedType(Token(SyntaxKind.ByteKeyword)), trueValue: 1, falseValue: 0, compareToTrue: false) @@ -128,7 +128,7 @@ public ByteBoolMarshaller() /// /// Corresponds to the definition of BOOL. /// - internal sealed class WinBoolMarshaller : BoolMarshallerBase + public sealed class WinBoolMarshaller : BoolMarshallerBase { public WinBoolMarshaller() : base(PredefinedType(Token(SyntaxKind.IntKeyword)), trueValue: 1, falseValue: 0, compareToTrue: false) @@ -139,7 +139,7 @@ public WinBoolMarshaller() /// /// Marshal a boolean value as a VARIANT_BOOL (Windows OLE/Automation type). /// - internal sealed class VariantBoolMarshaller : BoolMarshallerBase + public sealed class VariantBoolMarshaller : BoolMarshallerBase { private const short VARIANT_TRUE = -1; private const short VARIANT_FALSE = 0; diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/CharMarshaller.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/CharMarshaller.cs index ed43faac3f51..ba193ce4d802 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/CharMarshaller.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/CharMarshaller.cs @@ -7,9 +7,9 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -namespace Microsoft.Interop.SourceGeneration +namespace Microsoft.Interop { - internal sealed class Utf16CharMarshaller : IMarshallingGenerator + public sealed class Utf16CharMarshaller : IMarshallingGenerator { private static readonly PredefinedTypeSyntax NativeType = PredefinedType(Token(SyntaxKind.UShortKeyword)); diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/ConditionalStackallocMarshallingGenerator.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/ConditionalStackallocMarshallingGenerator.cs index 034322b1f6b9..f0bde9de1903 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/ConditionalStackallocMarshallingGenerator.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/ConditionalStackallocMarshallingGenerator.cs @@ -4,9 +4,9 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -namespace Microsoft.Interop.SourceGeneration +namespace Microsoft.Interop { - internal abstract class ConditionalStackallocMarshallingGenerator : IMarshallingGenerator + public abstract class ConditionalStackallocMarshallingGenerator : IMarshallingGenerator { protected static string GetAllocationMarkerIdentifier(string managedIdentifier) => $"{managedIdentifier}__allocated"; diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/CustomNativeTypeMarshaller.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/CustomNativeTypeMarshaller.cs index b3f0e5ce8996..155ad5e7a9bd 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/CustomNativeTypeMarshaller.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/CustomNativeTypeMarshaller.cs @@ -6,9 +6,9 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -namespace Microsoft.Interop.SourceGeneration +namespace Microsoft.Interop { - internal sealed class CustomNativeTypeMarshaller : IMarshallingGenerator + public sealed class CustomNativeTypeMarshaller : IMarshallingGenerator { private const string MarshalerLocalSuffix = "__marshaler"; private readonly TypeSyntax _nativeTypeSyntax; diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/DelegateMarshaller.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/DelegateMarshaller.cs index ee30df792973..45432ec384cf 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/DelegateMarshaller.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/DelegateMarshaller.cs @@ -4,9 +4,9 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -namespace Microsoft.Interop.SourceGeneration +namespace Microsoft.Interop { - internal sealed class DelegateMarshaller : IMarshallingGenerator + public sealed class DelegateMarshaller : IMarshallingGenerator { public TypeSyntax AsNativeType(TypePositionInfo info) { diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/Forwarder.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/Forwarder.cs index 31bf925be2e1..34c9c7119f06 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/Forwarder.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/Forwarder.cs @@ -4,9 +4,9 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -namespace Microsoft.Interop.SourceGeneration +namespace Microsoft.Interop { - internal sealed class Forwarder : IMarshallingGenerator + public sealed class Forwarder : IMarshallingGenerator { public TypeSyntax AsNativeType(TypePositionInfo info) { diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/HResultExceptionMarshaller.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/HResultExceptionMarshaller.cs index 3d6994c2ee77..360d2b26216e 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/HResultExceptionMarshaller.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/HResultExceptionMarshaller.cs @@ -7,9 +7,9 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -namespace Microsoft.Interop.SourceGeneration +namespace Microsoft.Interop { - internal sealed class HResultExceptionMarshaller : IMarshallingGenerator + public sealed class HResultExceptionMarshaller : IMarshallingGenerator { private static readonly TypeSyntax NativeType = PredefinedType(Token(SyntaxKind.IntKeyword)); diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallerHelpers.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallerHelpers.cs index 30361975a20a..e4145d3e9bb8 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallerHelpers.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallerHelpers.cs @@ -3,9 +3,9 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -namespace Microsoft.Interop.SourceGeneration +namespace Microsoft.Interop { - internal static class MarshallerHelpers + public static class MarshallerHelpers { public static readonly ExpressionSyntax IsWindows = InvocationExpression( MemberAccessExpression( diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGenerator.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGenerator.cs index b2205f2136ec..63653d2884ce 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGenerator.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGenerator.cs @@ -3,12 +3,12 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; -namespace Microsoft.Interop.SourceGeneration +namespace Microsoft.Interop { /// /// Interface for generation of marshalling code for P/Invoke stubs /// - internal interface IMarshallingGenerator + public interface IMarshallingGenerator { /// /// Get the native type syntax for @@ -71,7 +71,7 @@ internal interface IMarshallingGenerator /// /// Exception used to indicate marshalling isn't supported. /// - internal sealed class MarshallingNotSupportedException : Exception + public sealed class MarshallingNotSupportedException : Exception { /// /// Construct a new instance. diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGeneratorFactory.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGeneratorFactory.cs index 2576edc57273..fa6b66a1d966 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGeneratorFactory.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGeneratorFactory.cs @@ -5,9 +5,9 @@ using Microsoft.CodeAnalysis.Diagnostics; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -namespace Microsoft.Interop.SourceGeneration +namespace Microsoft.Interop { - internal interface IMarshallingGeneratorFactory + public interface IMarshallingGeneratorFactory { /// /// Create an instance for marshalling the supplied type in the given position. @@ -20,7 +20,7 @@ public IMarshallingGenerator Create( StubCodeContext context); } - internal sealed class DefaultMarshallingGeneratorFactory : IMarshallingGeneratorFactory + public sealed class DefaultMarshallingGeneratorFactory : IMarshallingGeneratorFactory { private static readonly ByteBoolMarshaller ByteBool = new(); private static readonly WinBoolMarshaller WinBool = new(); diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/NonBlittableArrayMarshaller.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/NonBlittableArrayMarshaller.cs index 70136cd85d5a..9c1755ab9341 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/NonBlittableArrayMarshaller.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/NonBlittableArrayMarshaller.cs @@ -6,9 +6,9 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -namespace Microsoft.Interop.SourceGeneration +namespace Microsoft.Interop { - internal sealed class NonBlittableArrayMarshaller : ConditionalStackallocMarshallingGenerator + public sealed class NonBlittableArrayMarshaller : ConditionalStackallocMarshallingGenerator { /// /// Stack-alloc threshold set to 256 bytes to enable small arrays to be passed on the stack. diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/SafeHandleMarshaller.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/SafeHandleMarshaller.cs index 54d2100b42f5..b4536cbcfe39 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/SafeHandleMarshaller.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/SafeHandleMarshaller.cs @@ -6,9 +6,9 @@ using Microsoft.CodeAnalysis.Diagnostics; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -namespace Microsoft.Interop.SourceGeneration +namespace Microsoft.Interop { - internal sealed class SafeHandleMarshaller : IMarshallingGenerator + public sealed class SafeHandleMarshaller : IMarshallingGenerator { private static readonly TypeSyntax NativeType = ParseTypeName("global::System.IntPtr"); diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Ansi.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Ansi.cs index 7edc11aba2d0..16e1f026606d 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Ansi.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Ansi.cs @@ -5,11 +5,11 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -using static Microsoft.Interop.SourceGeneration.MarshallerHelpers; +using static Microsoft.Interop.MarshallerHelpers; -namespace Microsoft.Interop.SourceGeneration +namespace Microsoft.Interop { - internal sealed class AnsiStringMarshaller : ConditionalStackallocMarshallingGenerator + public sealed class AnsiStringMarshaller : ConditionalStackallocMarshallingGenerator { private static readonly TypeSyntax NativeType = PointerType(PredefinedType(Token(SyntaxKind.ByteKeyword))); diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.PlatformDefined.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.PlatformDefined.cs index 02ee37d53c91..3de4c48a724b 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.PlatformDefined.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.PlatformDefined.cs @@ -6,11 +6,11 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -using static Microsoft.Interop.SourceGeneration.MarshallerHelpers; +using static Microsoft.Interop.MarshallerHelpers; -namespace Microsoft.Interop.SourceGeneration +namespace Microsoft.Interop { - internal sealed class PlatformDefinedStringMarshaller : ConditionalStackallocMarshallingGenerator + public sealed class PlatformDefinedStringMarshaller : ConditionalStackallocMarshallingGenerator { private static readonly TypeSyntax NativeType = PointerType(PredefinedType(Token(SyntaxKind.VoidKeyword))); diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Utf16.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Utf16.cs index 38b77525c3d1..9623967cf6e4 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Utf16.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Utf16.cs @@ -4,11 +4,11 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -using static Microsoft.Interop.SourceGeneration.MarshallerHelpers; +using static Microsoft.Interop.MarshallerHelpers; -namespace Microsoft.Interop.SourceGeneration +namespace Microsoft.Interop { - internal sealed class Utf16StringMarshaller : ConditionalStackallocMarshallingGenerator + public sealed class Utf16StringMarshaller : ConditionalStackallocMarshallingGenerator { // [Compat] Equivalent of MAX_PATH on Windows to match built-in system // The assumption is file paths are the most common case for marshalling strings, diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Utf8.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Utf8.cs index c082cccbefea..2a4801e8d3c3 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Utf8.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Utf8.cs @@ -4,11 +4,11 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -using static Microsoft.Interop.SourceGeneration.MarshallerHelpers; +using static Microsoft.Interop.MarshallerHelpers; -namespace Microsoft.Interop.SourceGeneration +namespace Microsoft.Interop { - internal sealed class Utf8StringMarshaller : ConditionalStackallocMarshallingGenerator + public sealed class Utf8StringMarshaller : ConditionalStackallocMarshallingGenerator { // [Compat] Equivalent of MAX_PATH on Windows to match built-in system // The assumption is file paths are the most common case for marshalling strings, diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/MarshallingAttributeInfo.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/MarshallingAttributeInfo.cs index 7a7790d5be54..88c378919ea0 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/MarshallingAttributeInfo.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/MarshallingAttributeInfo.cs @@ -4,17 +4,21 @@ using System.Diagnostics; using System.Runtime.InteropServices; -namespace Microsoft.Interop.SourceGeneration +namespace Microsoft.Interop { // The following types are modeled to fit with the current prospective spec // for C# 10 discriminated unions. Once discriminated unions are released, // these should be updated to be implemented as a discriminated union. - internal abstract record MarshallingInfo + public abstract record MarshallingInfo { + // Add a constructor that can only be called by derived types in the same assembly + // to enforce that this type cannot be extended by users of this library. + private protected MarshallingInfo() + {} } - internal sealed record NoMarshallingInfo : MarshallingInfo + public sealed record NoMarshallingInfo : MarshallingInfo { public static readonly MarshallingInfo Instance = new NoMarshallingInfo(); @@ -24,7 +28,7 @@ private NoMarshallingInfo() { } /// /// Character encoding enumeration. /// - internal enum CharEncoding + public enum CharEncoding { Undefined, Utf8, @@ -36,20 +40,20 @@ internal enum CharEncoding /// /// Details that are required when scenario supports strings. /// - internal record MarshallingInfoStringSupport( + public record MarshallingInfoStringSupport( CharEncoding CharEncoding ) : MarshallingInfo; /// /// Simple User-application of System.Runtime.InteropServices.MarshalAsAttribute /// - internal record MarshalAsInfo( + public record MarshalAsInfo( UnmanagedType UnmanagedType, CharEncoding CharEncoding) : MarshallingInfoStringSupport(CharEncoding) { } - internal enum UnmanagedArrayType + public enum UnmanagedArrayType { LPArray = UnmanagedType.LPArray, ByValArray = UnmanagedType.ByValArray @@ -58,7 +62,7 @@ internal enum UnmanagedArrayType /// /// User-applied System.Runtime.InteropServices.MarshalAsAttribute with array marshalling info /// - internal sealed record ArrayMarshalAsInfo( + public sealed record ArrayMarshalAsInfo( UnmanagedArrayType UnmanagedArrayType, int ArraySizeConst, short ArraySizeParamIndex, @@ -73,10 +77,10 @@ internal sealed record ArrayMarshalAsInfo( /// or System.Runtime.InteropServices.GeneratedMarshallingAttribute on a blittable type /// in source in this compilation. /// - internal sealed record BlittableTypeAttributeInfo : MarshallingInfo; + public sealed record BlittableTypeAttributeInfo : MarshallingInfo; [Flags] - internal enum SupportedMarshallingMethods + public enum SupportedMarshallingMethods { ManagedToNative = 0x1, NativeToManaged = 0x2, @@ -87,7 +91,7 @@ internal enum SupportedMarshallingMethods /// /// User-applied System.Runtime.InteropServices.NativeMarshallingAttribute /// - internal sealed record NativeMarshallingAttributeInfo( + public sealed record NativeMarshallingAttributeInfo( ITypeSymbol NativeMarshallingType, ITypeSymbol? ValuePropertyType, SupportedMarshallingMethods MarshallingMethods, @@ -97,17 +101,17 @@ internal sealed record NativeMarshallingAttributeInfo( /// User-applied System.Runtime.InteropServices.GeneratedMarshallingAttribute /// on a non-blittable type in source in this compilation. /// - internal sealed record GeneratedNativeMarshallingAttributeInfo( + public sealed record GeneratedNativeMarshallingAttributeInfo( string NativeMarshallingFullyQualifiedTypeName) : MarshallingInfo; /// /// The type of the element is a SafeHandle-derived type with no marshalling attributes. /// - internal sealed record SafeHandleMarshallingInfo(bool AccessibleDefaultConstructor) : MarshallingInfo; + public sealed record SafeHandleMarshallingInfo(bool AccessibleDefaultConstructor) : MarshallingInfo; /// /// Default marshalling for arrays /// - internal sealed record ArrayMarshallingInfo(MarshallingInfo ElementMarshallingInfo) : MarshallingInfo; + public sealed record ArrayMarshallingInfo(MarshallingInfo ElementMarshallingInfo) : MarshallingInfo; } diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj index 159264372579..703bce87fd4f 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj @@ -2,15 +2,13 @@ netstandard2.0 + false enable - Microsoft.Interop.SourceGeneration - false - True - true + Microsoft.Interop - + @@ -19,13 +17,13 @@ True True + + + Designer Resources.Designer.cs ResXFileCodeGenerator - Microsoft.Interop.SourceGenerationResources - - diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Resources.Designer.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Resources.Designer.cs index 90121a74e5a1..c451a2bece59 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Resources.Designer.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Resources.Designer.cs @@ -8,7 +8,7 @@ // //------------------------------------------------------------------------------ -namespace Microsoft.Interop.SourceGeneration { +namespace Microsoft.Interop { using System; @@ -39,7 +39,7 @@ internal Resources() { internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.Interop.SourceGeneration.Resources", typeof(Resources).Assembly); + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.Interop.Resources", typeof(Resources).Assembly); resourceMan = temp; } return resourceMan; @@ -213,15 +213,6 @@ internal static string SafeHandleByRefMustBeConcrete { } } - /// - /// Looks up a localized string similar to . - /// - internal static string Test { - get { - return ResourceManager.GetString("Test", resourceCulture); - } - } - /// /// Looks up a localized string similar to Specified type is not supported by source-generated P/Invokes. /// diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Resources.resx b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Resources.resx index bf9eeca37c4f..d21ad29d3da4 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Resources.resx +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Resources.resx @@ -168,9 +168,6 @@ An abstract type derived from 'SafeHandle' cannot be marshalled by reference. The provided type must be concrete. - - - Specified type is not supported by source-generated P/Invokes diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/StubCodeContext.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/StubCodeContext.cs index e6a2b6511480..9b212d35735e 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/StubCodeContext.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/StubCodeContext.cs @@ -1,8 +1,8 @@ using System; -namespace Microsoft.Interop.SourceGeneration +namespace Microsoft.Interop { - internal abstract class StubCodeContext + public abstract class StubCodeContext { /// /// Code generation stage diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/TypeNames.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/TypeNames.cs index d4b1f1d9d54c..1a640a2c395e 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/TypeNames.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/TypeNames.cs @@ -4,7 +4,7 @@ using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.Interop; -namespace Microsoft.Interop.SourceGeneration +namespace Microsoft.Interop { static class TypeNames { diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/TypePositionInfo.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/TypePositionInfo.cs index 865ea7cfc2ea..0a81f0e320f5 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/TypePositionInfo.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/TypePositionInfo.cs @@ -7,12 +7,12 @@ using Microsoft.CodeAnalysis.CSharp; using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; -namespace Microsoft.Interop.SourceGeneration +namespace Microsoft.Interop { /// /// Type used to pass on default marshalling details. /// - internal sealed record DefaultMarshallingInfo ( + public sealed record DefaultMarshallingInfo ( CharEncoding CharEncoding ); @@ -23,7 +23,7 @@ CharEncoding CharEncoding /// contents of the managed array. /// [Flags] - internal enum ByValueContentsMarshalKind + public enum ByValueContentsMarshalKind { /// /// Marshal contents from managed to native only. @@ -48,7 +48,7 @@ internal enum ByValueContentsMarshalKind /// /// Positional type information involved in unmanaged/managed scenarios. /// - internal sealed record TypePositionInfo + public sealed record TypePositionInfo { public const int UnsetIndex = int.MinValue; public const int ReturnIndex = UnsetIndex + 1; diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/TypeSymbolExtensions.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/TypeSymbolExtensions.cs index 652192811ce8..7555c11bb611 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/TypeSymbolExtensions.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/TypeSymbolExtensions.cs @@ -9,9 +9,9 @@ using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; -namespace Microsoft.Interop.SourceGeneration +namespace Microsoft.Interop { - internal static class TypeSymbolExtensions + public static class TypeSymbolExtensions { public static bool HasOnlyBlittableFields(this ITypeSymbol type) => HasOnlyBlittableFields(type, new HashSet(SymbolEqualityComparer.Default)); From 7df4da24e1ffca649fd3406ca0897dab09871f81 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Mon, 24 May 2021 15:43:39 -0700 Subject: [PATCH 10/12] Update CodeAnalysisAnalyzers version. --- eng/Versions.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/Versions.props b/eng/Versions.props index a6cc7f1a1ec1..ad8be0668e05 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -21,7 +21,7 @@ 3.10.0-3.21229.26 1.0.1-beta1.20478.1 - 3.3.3-beta1.21268.3 + 3.3.3-beta1.21274.1 2.0.0-beta1.21118.1 1.8.0 From 2af6835f163e0f12ad5676fd89bf36dd45720adf Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Mon, 24 May 2021 16:39:07 -0700 Subject: [PATCH 11/12] Reference CodeAnalysis.Analyzers from the shared code package. --- .../Microsoft.Interop.SourceGeneration.csproj | 1 + eng/Versions.props | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj index 703bce87fd4f..8317b0a45f8e 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj @@ -9,6 +9,7 @@ + diff --git a/eng/Versions.props b/eng/Versions.props index ad8be0668e05..a6cc7f1a1ec1 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -21,7 +21,7 @@ 3.10.0-3.21229.26 1.0.1-beta1.20478.1 - 3.3.3-beta1.21274.1 + 3.3.3-beta1.21268.3 2.0.0-beta1.21118.1 1.8.0 From a11f0f7ed30ab216f2ed7ed63ea59c8f1e0b7dd2 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Thu, 17 Jun 2021 16:49:21 -0700 Subject: [PATCH 12/12] Refactor out the new marshalling model into its own IMarshallingGeneratorFactory implementation to enable more localized handling of collection element marshalling support with the decorator pattern. --- .../DllImportGenerator/DllImportStub.cs | 8 +- ...ributedMarshallingModelGeneratorFactory.cs | 301 +++++++++++++++++ .../ByValueContentsMarshalKindValidator.cs | 51 +++ .../MarshallingGeneratorFactory.cs | 314 +----------------- 4 files changed, 361 insertions(+), 313 deletions(-) create mode 100644 DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/AttributedMarshallingModelGeneratorFactory.cs create mode 100644 DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/ByValueContentsMarshalKindValidator.cs diff --git a/DllImportGenerator/DllImportGenerator/DllImportStub.cs b/DllImportGenerator/DllImportGenerator/DllImportStub.cs index bfdd5fec0d6e..163c83414abe 100644 --- a/DllImportGenerator/DllImportGenerator/DllImportStub.cs +++ b/DllImportGenerator/DllImportGenerator/DllImportStub.cs @@ -189,7 +189,10 @@ public static DllImportStub Create( } else { - generatorFactory = new DefaultMarshallingGeneratorFactory(new InteropGenerationOptions(env.Options.UseMarshalType, env.Options.UseInternalUnsafeType)); + InteropGenerationOptions options = new(env.Options.UseMarshalType, env.Options.UseInternalUnsafeType); + var attributedMarshallingFactory = new AttributedMarshallingModelGeneratorFactory( + new DefaultMarshallingGeneratorFactory(options), options); + generatorFactory = attributedMarshallingFactory; // Do not manually handle PreserveSig when generating forwarders. // We want the runtime to handle everything. @@ -220,6 +223,9 @@ public static DllImportStub Create( paramsTypeInfo.Add(nativeOutInfo); } } + + generatorFactory = new ByValueContentsMarshalKindValidator(generatorFactory); + attributedMarshallingFactory.ElementMarshallingGeneratorFactory = generatorFactory; } // Generate stub code diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/AttributedMarshallingModelGeneratorFactory.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/AttributedMarshallingModelGeneratorFactory.cs new file mode 100644 index 000000000000..2b86198b9587 --- /dev/null +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/AttributedMarshallingModelGeneratorFactory.cs @@ -0,0 +1,301 @@ +using Microsoft.CodeAnalysis.CSharp; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.CodeAnalysis; + +namespace Microsoft.Interop +{ + public class AttributedMarshallingModelGeneratorFactory : IMarshallingGeneratorFactory + { + private static readonly BlittableMarshaller Blittable = new BlittableMarshaller(); + private static readonly Forwarder Forwarder = new Forwarder(); + + private readonly IMarshallingGeneratorFactory innerMarshallingGenerator; + + public AttributedMarshallingModelGeneratorFactory(IMarshallingGeneratorFactory innerMarshallingGenerator, InteropGenerationOptions options) + { + Options = options; + this.innerMarshallingGenerator = innerMarshallingGenerator; + ElementMarshallingGeneratorFactory = this; + } + + public InteropGenerationOptions Options { get; } + + /// + /// The to use for collection elements. + /// This property is settable to enable decorating factories to ensure that element marshalling also goes through the decorator support. + /// + public IMarshallingGeneratorFactory ElementMarshallingGeneratorFactory { get; set; } + + public IMarshallingGenerator Create(TypePositionInfo info, StubCodeContext context) + { + return info.MarshallingAttributeInfo switch + { + NativeMarshallingAttributeInfo marshalInfo => CreateCustomNativeTypeMarshaller(info, context, marshalInfo), + BlittableTypeAttributeInfo => Blittable, + GeneratedNativeMarshallingAttributeInfo => Forwarder, + _ => innerMarshallingGenerator.Create(info, context) + }; + } + + + private ExpressionSyntax GetNumElementsExpressionFromMarshallingInfo(TypePositionInfo info, CountInfo count, StubCodeContext context) + { + return count switch + { + SizeAndParamIndexInfo(int size, SizeAndParamIndexInfo.UnspecifiedData) => GetConstSizeExpression(size), + ConstSizeCountInfo(int size) => GetConstSizeExpression(size), + SizeAndParamIndexInfo(SizeAndParamIndexInfo.UnspecifiedData, int paramIndex) => CheckedExpression(SyntaxKind.CheckedExpression, GetExpressionForParam(context.GetTypePositionInfoForManagedIndex(paramIndex))), + SizeAndParamIndexInfo(int size, int paramIndex) => CheckedExpression(SyntaxKind.CheckedExpression, BinaryExpression(SyntaxKind.AddExpression, GetConstSizeExpression(size), GetExpressionForParam(context.GetTypePositionInfoForManagedIndex(paramIndex)))), + CountElementCountInfo(TypePositionInfo elementInfo) => CheckedExpression(SyntaxKind.CheckedExpression, GetExpressionForParam(elementInfo)), + _ => throw new MarshallingNotSupportedException(info, context) + { + NotSupportedDetails = Resources.ArraySizeMustBeSpecified + }, + }; + + static LiteralExpressionSyntax GetConstSizeExpression(int size) + { + return LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(size)); + } + + ExpressionSyntax GetExpressionForParam(TypePositionInfo? paramInfo) + { + if (paramInfo is null) + { + throw new MarshallingNotSupportedException(info, context) + { + NotSupportedDetails = Resources.ArraySizeParamIndexOutOfRange + }; + } + else + { + ExpressionSyntax numElementsExpression = GetIndexedNumElementsExpression( + context, + paramInfo, + out int numIndirectionLevels); + + ITypeSymbol type = paramInfo.ManagedType; + MarshallingInfo marshallingInfo = paramInfo.MarshallingAttributeInfo; + + for (int i = 0; i < numIndirectionLevels; i++) + { + if (marshallingInfo is NativeContiguousCollectionMarshallingInfo collectionInfo) + { + type = collectionInfo.ElementType; + marshallingInfo = collectionInfo.ElementMarshallingInfo; + } + else + { + throw new MarshallingNotSupportedException(info, context) + { + NotSupportedDetails = Resources.CollectionSizeParamTypeMustBeIntegral + }; + } + } + + if (!type.IsIntegralType()) + { + throw new MarshallingNotSupportedException(info, context) + { + NotSupportedDetails = Resources.CollectionSizeParamTypeMustBeIntegral + }; + } + + return CastExpression( + PredefinedType(Token(SyntaxKind.IntKeyword)), + ParenthesizedExpression(numElementsExpression)); + } + } + + static ExpressionSyntax GetIndexedNumElementsExpression(StubCodeContext context, TypePositionInfo numElementsInfo, out int numIndirectionLevels) + { + Stack indexerStack = new(); + + StubCodeContext? currentContext = context; + StubCodeContext lastContext = null!; + + while (currentContext is not null) + { + if (currentContext is ContiguousCollectionElementMarshallingCodeContext collectionContext) + { + indexerStack.Push(collectionContext.IndexerIdentifier); + } + lastContext = currentContext; + currentContext = currentContext.ParentContext; + } + + numIndirectionLevels = indexerStack.Count; + + ExpressionSyntax indexedNumElements = IdentifierName(lastContext.GetIdentifiers(numElementsInfo).managed); + while (indexerStack.Count > 0) + { + NameSyntax indexer = IdentifierName(indexerStack.Pop()); + indexedNumElements = ElementAccessExpression(indexedNumElements) + .AddArgumentListArguments(Argument(indexer)); + } + + return indexedNumElements; + } + } + + private IMarshallingGenerator CreateCustomNativeTypeMarshaller(TypePositionInfo info, StubCodeContext context, NativeMarshallingAttributeInfo marshalInfo) + { + ValidateCustomNativeTypeMarshallingSupported(info, context, marshalInfo); + + ICustomNativeTypeMarshallingStrategy marshallingStrategy = new SimpleCustomNativeTypeMarshalling(marshalInfo.NativeMarshallingType.AsTypeSyntax()); + + if ((marshalInfo.MarshallingMethods & SupportedMarshallingMethods.ManagedToNativeStackalloc) != 0) + { + marshallingStrategy = new StackallocOptimizationMarshalling(marshallingStrategy); + } + + if (ManualTypeMarshallingHelper.HasFreeNativeMethod(marshalInfo.NativeMarshallingType)) + { + marshallingStrategy = new FreeNativeCleanupStrategy(marshallingStrategy); + } + + // Collections have extra configuration, so handle them here. + if (marshalInfo is NativeContiguousCollectionMarshallingInfo collectionMarshallingInfo) + { + return CreateNativeCollectionMarshaller(info, context, collectionMarshallingInfo, marshallingStrategy); + } + + if (marshalInfo.ValuePropertyType is not null) + { + marshallingStrategy = DecorateWithValuePropertyStrategy(marshalInfo, marshallingStrategy); + } + + IMarshallingGenerator marshallingGenerator = new CustomNativeTypeMarshallingGenerator(marshallingStrategy, enableByValueContentsMarshalling: false); + + if ((marshalInfo.MarshallingMethods & SupportedMarshallingMethods.Pinning) != 0) + { + return new PinnableManagedValueMarshaller(marshallingGenerator); + } + + return marshallingGenerator; + } + + private static void ValidateCustomNativeTypeMarshallingSupported(TypePositionInfo info, StubCodeContext context, NativeMarshallingAttributeInfo marshalInfo) + { + // The marshalling method for this type doesn't support marshalling from native to managed, + // but our scenario requires marshalling from native to managed. + if ((info.RefKind == RefKind.Ref || info.RefKind == RefKind.Out || info.IsManagedReturnPosition) + && (marshalInfo.MarshallingMethods & SupportedMarshallingMethods.NativeToManaged) == 0) + { + throw new MarshallingNotSupportedException(info, context) + { + NotSupportedDetails = string.Format(Resources.CustomTypeMarshallingNativeToManagedUnsupported, marshalInfo.NativeMarshallingType.ToDisplayString()) + }; + } + // The marshalling method for this type doesn't support marshalling from managed to native by value, + // but our scenario requires marshalling from managed to native by value. + else if (!info.IsByRef + && (marshalInfo.MarshallingMethods & SupportedMarshallingMethods.ManagedToNative) == 0 + && (context.SingleFrameSpansNativeContext && (marshalInfo.MarshallingMethods & (SupportedMarshallingMethods.Pinning | SupportedMarshallingMethods.ManagedToNativeStackalloc)) == 0)) + { + throw new MarshallingNotSupportedException(info, context) + { + NotSupportedDetails = string.Format(Resources.CustomTypeMarshallingManagedToNativeUnsupported, marshalInfo.NativeMarshallingType.ToDisplayString()) + }; + } + // The marshalling method for this type doesn't support marshalling from managed to native by reference, + // but our scenario requires marshalling from managed to native by reference. + // "in" byref supports stack marshalling. + else if (info.RefKind == RefKind.In + && (marshalInfo.MarshallingMethods & SupportedMarshallingMethods.ManagedToNative) == 0 + && !(context.SingleFrameSpansNativeContext && (marshalInfo.MarshallingMethods & SupportedMarshallingMethods.ManagedToNativeStackalloc) != 0)) + { + throw new MarshallingNotSupportedException(info, context) + { + NotSupportedDetails = string.Format(Resources.CustomTypeMarshallingManagedToNativeUnsupported, marshalInfo.NativeMarshallingType.ToDisplayString()) + }; + } + // The marshalling method for this type doesn't support marshalling from managed to native by reference, + // but our scenario requires marshalling from managed to native by reference. + // "ref" byref marshalling doesn't support stack marshalling + else if (info.RefKind == RefKind.Ref + && (marshalInfo.MarshallingMethods & SupportedMarshallingMethods.ManagedToNative) == 0) + { + throw new MarshallingNotSupportedException(info, context) + { + NotSupportedDetails = string.Format(Resources.CustomTypeMarshallingManagedToNativeUnsupported, marshalInfo.NativeMarshallingType.ToDisplayString()) + }; + } + } + + private static ICustomNativeTypeMarshallingStrategy DecorateWithValuePropertyStrategy(NativeMarshallingAttributeInfo marshalInfo, ICustomNativeTypeMarshallingStrategy nativeTypeMarshaller) + { + TypeSyntax valuePropertyTypeSyntax = marshalInfo.ValuePropertyType!.AsTypeSyntax(); + if (ManualTypeMarshallingHelper.FindGetPinnableReference(marshalInfo.NativeMarshallingType) is not null) + { + return new PinnableMarshallerTypeMarshalling(nativeTypeMarshaller, valuePropertyTypeSyntax); + } + + return new CustomNativeTypeWithValuePropertyMarshalling(nativeTypeMarshaller, valuePropertyTypeSyntax); + } + + private IMarshallingGenerator CreateNativeCollectionMarshaller( + TypePositionInfo info, + StubCodeContext context, + NativeContiguousCollectionMarshallingInfo collectionInfo, + ICustomNativeTypeMarshallingStrategy marshallingStrategy) + { + var elementInfo = TypePositionInfo.CreateForType(collectionInfo.ElementType, collectionInfo.ElementMarshallingInfo) with { ManagedIndex = info.ManagedIndex }; + var elementMarshaller = ElementMarshallingGeneratorFactory.Create( + elementInfo, + new ContiguousCollectionElementMarshallingCodeContext(StubCodeContext.Stage.Setup, string.Empty, context)); + var elementType = elementMarshaller.AsNativeType(elementInfo); + + bool isBlittable = elementMarshaller is BlittableMarshaller; + + if (isBlittable) + { + marshallingStrategy = new ContiguousBlittableElementCollectionMarshalling(marshallingStrategy, collectionInfo.ElementType.AsTypeSyntax()); + } + else + { + marshallingStrategy = new ContiguousNonBlittableElementCollectionMarshalling(marshallingStrategy, elementMarshaller, elementInfo); + } + + // Explicitly insert the Value property handling here (before numElements handling) so that the numElements handling will be emitted before the Value property handling in unmarshalling. + if (collectionInfo.ValuePropertyType is not null) + { + marshallingStrategy = DecorateWithValuePropertyStrategy(collectionInfo, marshallingStrategy); + } + + ExpressionSyntax numElementsExpression = LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(0)); + if (info.IsManagedReturnPosition || (info.IsByRef && info.RefKind != RefKind.In)) + { + // In this case, we need a numElementsExpression supplied from metadata, so we'll calculate it here. + numElementsExpression = GetNumElementsExpressionFromMarshallingInfo(info, collectionInfo.ElementCountInfo, context); + } + + marshallingStrategy = new NumElementsExpressionMarshalling( + marshallingStrategy, + numElementsExpression, + SizeOfExpression(elementType)); + + if (collectionInfo.UseDefaultMarshalling && info.ManagedType is IArrayTypeSymbol { IsSZArray: true }) + { + return new ArrayMarshaller( + new CustomNativeTypeMarshallingGenerator(marshallingStrategy, enableByValueContentsMarshalling: true), + elementType, + isBlittable, + Options); + } + + IMarshallingGenerator marshallingGenerator = new CustomNativeTypeMarshallingGenerator(marshallingStrategy, enableByValueContentsMarshalling: false); + + if ((collectionInfo.MarshallingMethods & SupportedMarshallingMethods.Pinning) != 0) + { + return new PinnableManagedValueMarshaller(marshallingGenerator); + } + + return marshallingGenerator; + } + } +} diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/ByValueContentsMarshalKindValidator.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/ByValueContentsMarshalKindValidator.cs new file mode 100644 index 000000000000..dc9f64fde908 --- /dev/null +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/ByValueContentsMarshalKindValidator.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Microsoft.Interop +{ + /// + /// An implementation that wraps an inner instance and validates that the on the provided is valid in the current marshalling scenario. + /// + public class ByValueContentsMarshalKindValidator : IMarshallingGeneratorFactory + { + private readonly IMarshallingGeneratorFactory inner; + + public ByValueContentsMarshalKindValidator(IMarshallingGeneratorFactory inner) + { + this.inner = inner; + } + + public IMarshallingGenerator Create(TypePositionInfo info, StubCodeContext context) + { + return ValidateByValueMarshalKind(info, context, inner.Create(info, context)); + } + + private static IMarshallingGenerator ValidateByValueMarshalKind(TypePositionInfo info, StubCodeContext context, IMarshallingGenerator generator) + { + if (info.IsByRef && info.ByValueContentsMarshalKind != ByValueContentsMarshalKind.Default) + { + throw new MarshallingNotSupportedException(info, context) + { + NotSupportedDetails = Resources.InOutAttributeByRefNotSupported + }; + } + else if (info.ByValueContentsMarshalKind == ByValueContentsMarshalKind.In) + { + throw new MarshallingNotSupportedException(info, context) + { + NotSupportedDetails = Resources.InAttributeNotSupportedWithoutOut + }; + } + else if (info.ByValueContentsMarshalKind != ByValueContentsMarshalKind.Default + && !generator.SupportsByValueMarshalKind(info.ByValueContentsMarshalKind, context)) + { + throw new MarshallingNotSupportedException(info, context) + { + NotSupportedDetails = Resources.InOutAttributeMarshalerNotSupported + }; + } + return generator; + } + } +} diff --git a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGeneratorFactory.cs b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGeneratorFactory.cs index 4ccf9585eba2..9974e966ec72 100644 --- a/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGeneratorFactory.cs +++ b/DllImportGenerator/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGeneratorFactory.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Runtime.InteropServices; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; @@ -53,46 +54,6 @@ public DefaultMarshallingGeneratorFactory(InteropGenerationOptions options) public IMarshallingGenerator Create( TypePositionInfo info, StubCodeContext context) - { - return ValidateByValueMarshalKind(context, info, CreateCore(info, context)); - } - - private IMarshallingGenerator ValidateByValueMarshalKind(StubCodeContext context, TypePositionInfo info, IMarshallingGenerator generator) - { - if (info.IsByRef && info.ByValueContentsMarshalKind != ByValueContentsMarshalKind.Default) - { - throw new MarshallingNotSupportedException(info, context) - { - NotSupportedDetails = Resources.InOutAttributeByRefNotSupported - }; - } - else if (info.ByValueContentsMarshalKind == ByValueContentsMarshalKind.In) - { - throw new MarshallingNotSupportedException(info, context) - { - NotSupportedDetails = Resources.InAttributeNotSupportedWithoutOut - }; - } - else if (info.ByValueContentsMarshalKind != ByValueContentsMarshalKind.Default - && !generator.SupportsByValueMarshalKind(info.ByValueContentsMarshalKind, context)) - { - throw new MarshallingNotSupportedException(info, context) - { - NotSupportedDetails = Resources.InOutAttributeMarshalerNotSupported - }; - } - return generator; - } - - /// - /// Create an instance to marshalling the supplied type. - /// - /// Type details - /// Metadata about the stub the type is associated with - /// A instance. - private IMarshallingGenerator CreateCore( - TypePositionInfo info, - StubCodeContext context) { switch (info) { @@ -155,21 +116,6 @@ private IMarshallingGenerator CreateCore( } return SafeHandle; - // Marshalling in new model. - // Must go before the cases that do not explicitly check for marshalling info to support - // the user overridding the default marshalling rules with a MarshalUsing attribute. - case { MarshallingAttributeInfo: NativeMarshallingAttributeInfo marshalInfo }: - return CreateCustomNativeTypeMarshaller(info, context, marshalInfo); - - case { MarshallingAttributeInfo: BlittableTypeAttributeInfo }: - return Blittable; - - // Simple generated marshalling with new attribute model, only have type name. - case { MarshallingAttributeInfo: GeneratedNativeMarshallingAttributeInfo(string nativeTypeName) }: - return Forwarder; - - // Cases that just match on type must come after the checks that match only on marshalling attribute info. - // The checks below do not account for generic marshalling overrides like [MarshalUsing], so those checks must come first. case { ManagedType: { SpecialType: SpecialType.System_Char } }: return CreateCharMarshaller(info, context); @@ -271,261 +217,5 @@ private IMarshallingGenerator CreateStringMarshaller(TypePositionInfo info, Stub throw new MarshallingNotSupportedException(info, context); } - - private ExpressionSyntax GetNumElementsExpressionFromMarshallingInfo(TypePositionInfo info, CountInfo count, StubCodeContext context) - { - return count switch - { - SizeAndParamIndexInfo(int size, SizeAndParamIndexInfo.UnspecifiedData) => GetConstSizeExpression(size), - ConstSizeCountInfo(int size) => GetConstSizeExpression(size), - SizeAndParamIndexInfo(SizeAndParamIndexInfo.UnspecifiedData, int paramIndex) => CheckedExpression(SyntaxKind.CheckedExpression, GetExpressionForParam(context.GetTypePositionInfoForManagedIndex(paramIndex))), - SizeAndParamIndexInfo(int size, int paramIndex) => CheckedExpression(SyntaxKind.CheckedExpression, BinaryExpression(SyntaxKind.AddExpression, GetConstSizeExpression(size), GetExpressionForParam(context.GetTypePositionInfoForManagedIndex(paramIndex)))), - CountElementCountInfo(TypePositionInfo elementInfo) => CheckedExpression(SyntaxKind.CheckedExpression, GetExpressionForParam(elementInfo)), - _ => throw new MarshallingNotSupportedException(info, context) - { - NotSupportedDetails = Resources.ArraySizeMustBeSpecified - }, - }; - - static LiteralExpressionSyntax GetConstSizeExpression(int size) - { - return LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(size)); - } - - ExpressionSyntax GetExpressionForParam(TypePositionInfo? paramInfo) - { - if (paramInfo is null) - { - throw new MarshallingNotSupportedException(info, context) - { - NotSupportedDetails = Resources.ArraySizeParamIndexOutOfRange - }; - } - else - { - ExpressionSyntax numElementsExpression = GetIndexedNumElementsExpression( - context, - paramInfo, - out int numIndirectionLevels); - - ITypeSymbol type = paramInfo.ManagedType; - MarshallingInfo marshallingInfo = paramInfo.MarshallingAttributeInfo; - - for (int i = 0; i < numIndirectionLevels; i++) - { - if (marshallingInfo is NativeContiguousCollectionMarshallingInfo collectionInfo) - { - type = collectionInfo.ElementType; - marshallingInfo = collectionInfo.ElementMarshallingInfo; - } - else - { - throw new MarshallingNotSupportedException(info, context) - { - NotSupportedDetails = Resources.CollectionSizeParamTypeMustBeIntegral - }; - } - } - - if (!type.IsIntegralType()) - { - throw new MarshallingNotSupportedException(info, context) - { - NotSupportedDetails = Resources.CollectionSizeParamTypeMustBeIntegral - }; - } - - return CastExpression( - PredefinedType(Token(SyntaxKind.IntKeyword)), - ParenthesizedExpression(numElementsExpression)); - } - } - - static ExpressionSyntax GetIndexedNumElementsExpression(StubCodeContext context, TypePositionInfo numElementsInfo, out int numIndirectionLevels) - { - Stack indexerStack = new(); - - StubCodeContext? currentContext = context; - StubCodeContext lastContext = null!; - - while (currentContext is not null) - { - if (currentContext is ContiguousCollectionElementMarshallingCodeContext collectionContext) - { - indexerStack.Push(collectionContext.IndexerIdentifier); - } - lastContext = currentContext; - currentContext = currentContext.ParentContext; - } - - numIndirectionLevels = indexerStack.Count; - - ExpressionSyntax indexedNumElements = IdentifierName(lastContext.GetIdentifiers(numElementsInfo).managed); - while (indexerStack.Count > 0) - { - NameSyntax indexer = IdentifierName(indexerStack.Pop()); - indexedNumElements = ElementAccessExpression(indexedNumElements) - .AddArgumentListArguments(Argument(indexer)); - } - - return indexedNumElements; - } - } - - private IMarshallingGenerator CreateCustomNativeTypeMarshaller(TypePositionInfo info, StubCodeContext context, NativeMarshallingAttributeInfo marshalInfo) - { - ValidateCustomNativeTypeMarshallingSupported(info, context, marshalInfo); - - ICustomNativeTypeMarshallingStrategy marshallingStrategy = new SimpleCustomNativeTypeMarshalling(marshalInfo.NativeMarshallingType.AsTypeSyntax()); - - if ((marshalInfo.MarshallingMethods & SupportedMarshallingMethods.ManagedToNativeStackalloc) != 0) - { - marshallingStrategy = new StackallocOptimizationMarshalling(marshallingStrategy); - } - - if (ManualTypeMarshallingHelper.HasFreeNativeMethod(marshalInfo.NativeMarshallingType)) - { - marshallingStrategy = new FreeNativeCleanupStrategy(marshallingStrategy); - } - - // Collections have extra configuration, so handle them here. - if (marshalInfo is NativeContiguousCollectionMarshallingInfo collectionMarshallingInfo) - { - return CreateNativeCollectionMarshaller(info, context, collectionMarshallingInfo, marshallingStrategy); - } - - if (marshalInfo.ValuePropertyType is not null) - { - marshallingStrategy = DecorateWithValuePropertyStrategy(marshalInfo, marshallingStrategy); - } - - IMarshallingGenerator marshallingGenerator = new CustomNativeTypeMarshallingGenerator(marshallingStrategy, enableByValueContentsMarshalling: false); - - if ((marshalInfo.MarshallingMethods & SupportedMarshallingMethods.Pinning) != 0) - { - return new PinnableManagedValueMarshaller(marshallingGenerator); - } - - return marshallingGenerator; - } - - private static void ValidateCustomNativeTypeMarshallingSupported(TypePositionInfo info, StubCodeContext context, NativeMarshallingAttributeInfo marshalInfo) - { - // The marshalling method for this type doesn't support marshalling from native to managed, - // but our scenario requires marshalling from native to managed. - if ((info.RefKind == RefKind.Ref || info.RefKind == RefKind.Out || info.IsManagedReturnPosition) - && (marshalInfo.MarshallingMethods & SupportedMarshallingMethods.NativeToManaged) == 0) - { - throw new MarshallingNotSupportedException(info, context) - { - NotSupportedDetails = string.Format(Resources.CustomTypeMarshallingNativeToManagedUnsupported, marshalInfo.NativeMarshallingType.ToDisplayString()) - }; - } - // The marshalling method for this type doesn't support marshalling from managed to native by value, - // but our scenario requires marshalling from managed to native by value. - else if (!info.IsByRef - && (marshalInfo.MarshallingMethods & SupportedMarshallingMethods.ManagedToNative) == 0 - && (context.SingleFrameSpansNativeContext && (marshalInfo.MarshallingMethods & (SupportedMarshallingMethods.Pinning | SupportedMarshallingMethods.ManagedToNativeStackalloc)) == 0)) - { - throw new MarshallingNotSupportedException(info, context) - { - NotSupportedDetails = string.Format(Resources.CustomTypeMarshallingManagedToNativeUnsupported, marshalInfo.NativeMarshallingType.ToDisplayString()) - }; - } - // The marshalling method for this type doesn't support marshalling from managed to native by reference, - // but our scenario requires marshalling from managed to native by reference. - // "in" byref supports stack marshalling. - else if (info.RefKind == RefKind.In - && (marshalInfo.MarshallingMethods & SupportedMarshallingMethods.ManagedToNative) == 0 - && !(context.SingleFrameSpansNativeContext && (marshalInfo.MarshallingMethods & SupportedMarshallingMethods.ManagedToNativeStackalloc) != 0)) - { - throw new MarshallingNotSupportedException(info, context) - { - NotSupportedDetails = string.Format(Resources.CustomTypeMarshallingManagedToNativeUnsupported, marshalInfo.NativeMarshallingType.ToDisplayString()) - }; - } - // The marshalling method for this type doesn't support marshalling from managed to native by reference, - // but our scenario requires marshalling from managed to native by reference. - // "ref" byref marshalling doesn't support stack marshalling - else if (info.RefKind == RefKind.Ref - && (marshalInfo.MarshallingMethods & SupportedMarshallingMethods.ManagedToNative) == 0) - { - throw new MarshallingNotSupportedException(info, context) - { - NotSupportedDetails = string.Format(Resources.CustomTypeMarshallingManagedToNativeUnsupported, marshalInfo.NativeMarshallingType.ToDisplayString()) - }; - } - } - - private static ICustomNativeTypeMarshallingStrategy DecorateWithValuePropertyStrategy(NativeMarshallingAttributeInfo marshalInfo, ICustomNativeTypeMarshallingStrategy nativeTypeMarshaller) - { - TypeSyntax valuePropertyTypeSyntax = marshalInfo.ValuePropertyType!.AsTypeSyntax(); - if (ManualTypeMarshallingHelper.FindGetPinnableReference(marshalInfo.NativeMarshallingType) is not null) - { - return new PinnableMarshallerTypeMarshalling(nativeTypeMarshaller, valuePropertyTypeSyntax); - } - - return new CustomNativeTypeWithValuePropertyMarshalling(nativeTypeMarshaller, valuePropertyTypeSyntax); - } - - private IMarshallingGenerator CreateNativeCollectionMarshaller( - TypePositionInfo info, - StubCodeContext context, - NativeContiguousCollectionMarshallingInfo collectionInfo, - ICustomNativeTypeMarshallingStrategy marshallingStrategy) - { - var elementInfo = TypePositionInfo.CreateForType(collectionInfo.ElementType, collectionInfo.ElementMarshallingInfo) with { ManagedIndex = info.ManagedIndex }; - var elementMarshaller = Create( - elementInfo, - new ContiguousCollectionElementMarshallingCodeContext(StubCodeContext.Stage.Setup, string.Empty, context)); - var elementType = elementMarshaller.AsNativeType(elementInfo); - - bool isBlittable = elementMarshaller == Blittable; - - if (isBlittable) - { - marshallingStrategy = new ContiguousBlittableElementCollectionMarshalling(marshallingStrategy, collectionInfo.ElementType.AsTypeSyntax()); - } - else - { - marshallingStrategy = new ContiguousNonBlittableElementCollectionMarshalling(marshallingStrategy, elementMarshaller, elementInfo); - } - - // Explicitly insert the Value property handling here (before numElements handling) so that the numElements handling will be emitted before the Value property handling in unmarshalling. - if (collectionInfo.ValuePropertyType is not null) - { - marshallingStrategy = DecorateWithValuePropertyStrategy(collectionInfo, marshallingStrategy); - } - - ExpressionSyntax numElementsExpression = LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(0)); - if (info.IsManagedReturnPosition || (info.IsByRef && info.RefKind != RefKind.In)) - { - // In this case, we need a numElementsExpression supplied from metadata, so we'll calculate it here. - numElementsExpression = GetNumElementsExpressionFromMarshallingInfo(info, collectionInfo.ElementCountInfo, context); - } - - marshallingStrategy = new NumElementsExpressionMarshalling( - marshallingStrategy, - numElementsExpression, - SizeOfExpression(elementType)); - - if (collectionInfo.UseDefaultMarshalling && info.ManagedType is IArrayTypeSymbol { IsSZArray: true }) - { - return new ArrayMarshaller( - new CustomNativeTypeMarshallingGenerator(marshallingStrategy, enableByValueContentsMarshalling: true), - elementType, - isBlittable, - Options); - } - - IMarshallingGenerator marshallingGenerator = new CustomNativeTypeMarshallingGenerator(marshallingStrategy, enableByValueContentsMarshalling: false); - - if ((collectionInfo.MarshallingMethods & SupportedMarshallingMethods.Pinning) != 0) - { - return new PinnableManagedValueMarshaller(marshallingGenerator); - } - - return marshallingGenerator; - } } }