diff --git a/src/Microsoft.Windows.CsWin32/Generator.cs b/src/Microsoft.Windows.CsWin32/Generator.cs
index 0415e48e..76c55ad1 100644
--- a/src/Microsoft.Windows.CsWin32/Generator.cs
+++ b/src/Microsoft.Windows.CsWin32/Generator.cs
@@ -96,6 +96,9 @@ public class Generator : IDisposable
///
");
+ private static readonly XmlTextSyntax DocCommentStart = XmlText(" ").WithLeadingTrivia(DocumentationCommentExterior("///"));
+ private static readonly XmlTextSyntax DocCommentEnd = XmlText(XmlTextNewLine("\r\n", continueXmlDocumentationComment: false));
+
private static readonly IdentifierNameSyntax ConstantsClassName = IdentifierName("Constants");
private static readonly IdentifierNameSyntax InlineArrayIndexerExtensionsClassName = IdentifierName("InlineArrayIndexerExtensions");
private static readonly TypeSyntax SafeHandleTypeSyntax = IdentifierName("SafeHandle");
@@ -3158,9 +3161,13 @@ ExpressionSyntax GetHiddenFieldAccess() => MemberAccessExpression(
elementType = IntPtrTypeSyntax;
}
- // private struct __TheStruct_Count
+ var lengthLiteralSyntax = LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(length));
+
+ // internal struct __TheStruct_Count
// {
- // private TheStruct _0, _1, _2, _3, _4, _5, _6, _7, _8;
+ // internal TheStruct _0, _1, _2, _3, _4, _5, _6, _7, _8;
+ // /// Always 8.
+ // internal int Length => 8;
// ...
IdentifierNameSyntax fixedLengthStructName = IdentifierName($"__{fieldName}_{length}");
var fixedLengthStruct = StructDeclaration(fixedLengthStructName.Identifier)
@@ -3168,7 +3175,20 @@ ExpressionSyntax GetHiddenFieldAccess() => MemberAccessExpression(
.AddMembers(
FieldDeclaration(VariableDeclaration(elementType)
.AddVariables(Enumerable.Range(0, length).Select(n => VariableDeclarator($"_{n}")).ToArray()))
- .AddModifiers(Token(this.Visibility)));
+ .AddModifiers(Token(this.Visibility)),
+ PropertyDeclaration(PredefinedType(Token(SyntaxKind.IntKeyword)), "Length")
+ .AddModifiers(Token(this.Visibility))
+ .WithExpressionBody(ArrowExpressionClause(lengthLiteralSyntax))
+ .WithSemicolonToken(Token(SyntaxKind.SemicolonToken))
+ .WithLeadingTrivia(Trivia(DocumentationCommentTrivia(SyntaxKind.SingleLineDocumentationCommentTrivia).AddContent(
+ DocCommentStart,
+ XmlElement("summary", List(new XmlNodeSyntax[]
+ {
+ XmlText("Always "),
+ XmlElement("c", List(new XmlNodeSyntax[] { XmlText(length.ToString(CultureInfo.InvariantCulture)) })),
+ XmlText("."),
+ })),
+ DocCommentEnd))));
var firstElementFieldName = IdentifierName("_0");
if (this.canCallCreateSpan)
@@ -3192,7 +3212,7 @@ ExpressionSyntax GetHiddenFieldAccess() => MemberAccessExpression(
InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, IdentifierName("MemoryMarshal"), IdentifierName("CreateSpan")))
.AddArgumentListArguments(
Argument(nameColon: null, Token(SyntaxKind.RefKeyword), firstElementFieldName),
- Argument(LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(length))))))
+ Argument(lengthLiteralSyntax))))
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken))
.WithLeadingTrivia(InlineArrayUnsafeAsSpanComment));
}
diff --git a/test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs b/test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs
index 651b5147..b8a40831 100644
--- a/test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs
+++ b/test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs
@@ -399,6 +399,8 @@ internal partial struct MainAVIHeader
internal struct __dwReserved_4
{
internal uint _0, _1, _2, _3;
+ /// Always 4.
+ internal int Length => 4;
}
}
";
@@ -446,6 +448,8 @@ internal partial struct MainAVIHeader
internal struct __dwReserved_4
{
internal uint _0, _1, _2, _3;
+ /// Always 4.
+ internal int Length => 4;
///
/// Gets a ref to an individual element of the inline array.
/// ⚠ Important ⚠: When this struct is on the stack, do not let the returned reference outlive the stack frame that defines it.