From 818f7d148589a32ab99cc3b390ae40db26a26ac9 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Fri, 1 Jul 2022 21:11:37 -0600 Subject: [PATCH 1/2] Add test for inline arrays without marshaling Test for #597 --- .../GeneratorTests.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs b/test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs index 70ed74ab..3b7c9866 100644 --- a/test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs +++ b/test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs @@ -1397,6 +1397,20 @@ internal static partial class InlineArrayIndexerExtensions this.AssertGeneratedType("MainAVIHeader", expected, expectedIndexer); } + [Theory, PairwiseData] + public void FixedLengthInlineArrayIn_MODULEENTRY32(bool allowMarshaling) + { + this.generator = this.CreateGenerator(new GeneratorOptions { AllowMarshaling = allowMarshaling }); + Assert.True(this.generator.TryGenerate("MODULEENTRY32", CancellationToken.None)); + this.CollectGeneratedCode(this.generator); + this.AssertNoDiagnostics(); + var decl = (StructDeclarationSyntax)Assert.Single(this.FindGeneratedType("MODULEENTRY32")); + var field = this.FindFieldDeclaration(decl, "szModule"); + Assert.True(field.HasValue); + var fieldType = Assert.IsType(field!.Value.Field.Declaration.Type); + Assert.IsType(Assert.Single(this.FindGeneratedType(fieldType.Identifier.ValueText))); + } + [Fact] public void InOutPWSTRGetsRefSpanCharFriendlyOverload() { From 97dfb78c86bbf06ac8b0f3398468c65b724858f8 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Tue, 5 Jul 2022 15:32:18 -0600 Subject: [PATCH 2/2] Fix inline arrays when marshaling is off Fixes #597 --- .../ArrayTypeHandleInfo.cs | 2 +- src/Microsoft.Windows.CsWin32/Generator.cs | 18 ++++++++++++++++-- .../TypeSyntaxSettings.cs | 2 +- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.Windows.CsWin32/ArrayTypeHandleInfo.cs b/src/Microsoft.Windows.CsWin32/ArrayTypeHandleInfo.cs index 3ed2c876..82a7ebdc 100644 --- a/src/Microsoft.Windows.CsWin32/ArrayTypeHandleInfo.cs +++ b/src/Microsoft.Windows.CsWin32/ArrayTypeHandleInfo.cs @@ -17,7 +17,7 @@ internal record ArrayTypeHandleInfo(TypeHandleInfo ElementType, ArrayShape Shape internal override TypeSyntaxAndMarshaling ToTypeSyntax(TypeSyntaxSettings inputs, CustomAttributeHandleCollection? customAttributes, ParameterAttributes parameterAttributes) { TypeSyntaxAndMarshaling element = this.ElementType.ToTypeSyntax(inputs, customAttributes); - if (inputs.AllowMarshaling) + if (inputs.AllowMarshaling || inputs.IsField) { ArrayTypeSyntax arrayType = ArrayType(element.Type, SingletonList(ArrayRankSpecifier().AddSizes(this.Shape.Sizes.Select(size => LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(size))).ToArray()))); MarshalAsAttribute? marshalAs = element.MarshalAsAttribute is object ? new MarshalAsAttribute(UnmanagedType.LPArray) { ArraySubType = element.MarshalAsAttribute.Value } : null; diff --git a/src/Microsoft.Windows.CsWin32/Generator.cs b/src/Microsoft.Windows.CsWin32/Generator.cs index 1c0dad93..335be3dc 100644 --- a/src/Microsoft.Windows.CsWin32/Generator.cs +++ b/src/Microsoft.Windows.CsWin32/Generator.cs @@ -389,7 +389,7 @@ public Generator(string metadataLibraryPath, Docs? docs, GeneratorOptions option PreferMarshaledTypes: false, AllowMarshaling: options.AllowMarshaling, QualifyNames: false); - this.fieldTypeSettings = this.generalTypeSettings with { QualifyNames = true }; + this.fieldTypeSettings = this.generalTypeSettings with { QualifyNames = true, IsField = true }; this.delegateSignatureTypeSettings = this.generalTypeSettings with { QualifyNames = true }; this.enumTypeSettings = this.generalTypeSettings; this.fieldOfHandleTypeDefTypeSettings = this.generalTypeSettings with { PreferNativeInt = false }; @@ -5324,7 +5324,21 @@ private ParameterSyntax CreateParameter(TypeHandleInfo parameterInfo, Parameter IdentifierNameSyntax indexParamName = IdentifierName("index"); IdentifierNameSyntax p0 = IdentifierName("p0"); IdentifierNameSyntax atThis = IdentifierName("@this"); - TypeSyntax qualifiedElementType = elementType == IntPtrTypeSyntax ? elementType : ((ArrayTypeSyntax)fieldTypeHandleInfo.ToTypeSyntax(this.extensionMethodSignatureTypeSettings, customAttributes).Type).ElementType; + TypeSyntax qualifiedElementType; + if (elementType == IntPtrTypeSyntax) + { + qualifiedElementType = elementType; + } + else + { + qualifiedElementType = fieldTypeHandleInfo.ToTypeSyntax(this.extensionMethodSignatureTypeSettings, customAttributes).Type switch + { + ArrayTypeSyntax at => at.ElementType, + PointerTypeSyntax ptrType => ptrType.ElementType, + _ => throw new GenerationFailedException($"Unexpected runtime type."), + }; + } + TypeSyntaxSettings extensionMethodSignatureTypeSettings = context.Filter(this.extensionMethodSignatureTypeSettings); ////internal static unsafe ref readonly uint ReadOnlyItemRef(this in MainAVIHeader.__dwReserved_4 @this, int index) diff --git a/src/Microsoft.Windows.CsWin32/TypeSyntaxSettings.cs b/src/Microsoft.Windows.CsWin32/TypeSyntaxSettings.cs index a31a13c8..3395ded8 100644 --- a/src/Microsoft.Windows.CsWin32/TypeSyntaxSettings.cs +++ b/src/Microsoft.Windows.CsWin32/TypeSyntaxSettings.cs @@ -3,6 +3,6 @@ namespace Microsoft.Windows.CsWin32; -internal record TypeSyntaxSettings(Generator? Generator, bool PreferNativeInt, bool PreferMarshaledTypes, bool AllowMarshaling, bool QualifyNames) +internal record TypeSyntaxSettings(Generator? Generator, bool PreferNativeInt, bool PreferMarshaledTypes, bool AllowMarshaling, bool QualifyNames, bool IsField = false) { }