Skip to content

Commit 6242573

Browse files
authored
Merge pull request #937 from microsoft/metadataUpdate
Update metadata to 52.0.65-preview
2 parents 343140c + 9e5a298 commit 6242573

File tree

15 files changed

+302
-25
lines changed

15 files changed

+302
-25
lines changed

Directory.Packages.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
55
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
66

7-
<MetadataVersion>51.0.33-preview</MetadataVersion>
7+
<MetadataVersion>52.0.65-preview</MetadataVersion>
88
<!-- <DiaMetadataVersion>0.2.185-preview-g7e1e6a442c</DiaMetadataVersion> -->
99
<ApiDocsVersion>0.1.41-alpha</ApiDocsVersion>
1010

src/Microsoft.Windows.CsWin32/FastSyntaxFactory.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,8 @@ internal static SyntaxToken XmlTextNewLine(string text, bool continueXmlDocument
263263

264264
internal static MethodDeclarationSyntax MethodDeclaration(TypeSyntax returnType, SyntaxToken identifier) => SyntaxFactory.MethodDeclaration(default(SyntaxList<AttributeListSyntax>), default(SyntaxTokenList), returnType.WithTrailingTrivia(TriviaList(Space)), null, identifier, null, ParameterList(), default(SyntaxList<TypeParameterConstraintClauseSyntax>), null, null, default(SyntaxToken));
265265

266+
internal static LocalFunctionStatementSyntax LocalFunctionStatement(TypeSyntax returnType, SyntaxToken identifier) => SyntaxFactory.LocalFunctionStatement(default(SyntaxList<AttributeListSyntax>), default(SyntaxTokenList), returnType, identifier, null, ParameterList(), default(SyntaxList<TypeParameterConstraintClauseSyntax>), null, null);
267+
266268
internal static MethodDeclarationSyntax MethodDeclaration(SyntaxList<AttributeListSyntax> attributeLists, SyntaxTokenList modifiers, TypeSyntax returnType, ExplicitInterfaceSpecifierSyntax? explicitInterfaceSpecifier, SyntaxToken identifier, TypeParameterListSyntax? typeParameterList, ParameterListSyntax parameterList, SyntaxList<TypeParameterConstraintClauseSyntax> constraintClauses, BlockSyntax body, SyntaxToken semicolonToken) => SyntaxFactory.MethodDeclaration(attributeLists, modifiers, returnType.WithTrailingTrivia(TriviaList(Space)), explicitInterfaceSpecifier!, identifier, typeParameterList!, parameterList, constraintClauses, body, semicolonToken);
267269

268270
internal static MemberDeclarationSyntax? ParseMemberDeclaration(string text, ParseOptions? options) => SyntaxFactory.ParseMemberDeclaration(text, options: options);

src/Microsoft.Windows.CsWin32/Generator.Extern.cs

Lines changed: 100 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ public bool TryGenerateExternMethod(string possiblyQualifiedName, out IReadOnlyL
121121
this.RequestExternMethod(methodDefHandle);
122122
});
123123

124-
string methodNamespace = this.Reader.GetString(this.Reader.GetTypeDefinition(methodDef.GetDeclaringType()).Namespace);
124+
string methodNamespace = this.GetMethodNamespace(methodDef);
125125
preciseApi = ImmutableList.Create($"{methodNamespace}.{methodName}");
126126
return true;
127127
}
@@ -168,6 +168,8 @@ private static bool IsLibraryAllowedAppLocal(string libraryName)
168168
return false;
169169
}
170170

171+
private string GetMethodNamespace(MethodDefinition methodDef) => this.Reader.GetString(this.Reader.GetTypeDefinition(methodDef.GetDeclaringType()).Namespace);
172+
171173
private void DeclareExternMethod(MethodDefinitionHandle methodDefinitionHandle)
172174
{
173175
MethodDefinition methodDefinition = this.Reader.GetMethodDefinition(methodDefinitionHandle);
@@ -204,43 +206,123 @@ private void DeclareExternMethod(MethodDefinitionHandle methodDefinitionHandle)
204206
CustomAttributeHandleCollection? returnTypeAttributes = this.GetReturnTypeCustomAttributes(methodDefinition);
205207
TypeSyntaxAndMarshaling returnType = signature.ReturnType.ToTypeSyntax(typeSettings, returnTypeAttributes, ParameterAttributes.Out);
206208

207-
MethodDeclarationSyntax methodDeclaration = MethodDeclaration(
208-
List<AttributeListSyntax>()
209-
.Add(AttributeList()
210-
.WithCloseBracketToken(TokenWithLineFeed(SyntaxKind.CloseBracketToken))
211-
.AddAttributes(DllImport(import, moduleName, entrypoint, requiresUnicodeCharSet ? CharSet.Unicode : CharSet.Ansi))),
212-
modifiers: TokenList(TokenWithSpace(this.Visibility), TokenWithSpace(SyntaxKind.StaticKeyword), TokenWithSpace(SyntaxKind.ExternKeyword)),
209+
// Search for any enum substitutions.
210+
TypeSyntax? returnTypeEnumName = this.FindAssociatedEnum(returnTypeAttributes);
211+
TypeSyntax?[]? parameterEnumType = null;
212+
foreach (ParameterHandle parameterHandle in methodDefinition.GetParameters())
213+
{
214+
Parameter parameter = this.Reader.GetParameter(parameterHandle);
215+
if (parameter.SequenceNumber == 0)
216+
{
217+
continue;
218+
}
219+
220+
if (this.FindAssociatedEnum(parameter.GetCustomAttributes()) is IdentifierNameSyntax parameterEnumName)
221+
{
222+
parameterEnumType ??= new TypeSyntax?[signature.ParameterTypes.Length];
223+
parameterEnumType[parameter.SequenceNumber - 1] = parameterEnumName;
224+
}
225+
}
226+
227+
AttributeListSyntax CreateDllImportAttributeList() => AttributeList()
228+
.WithCloseBracketToken(TokenWithLineFeed(SyntaxKind.CloseBracketToken))
229+
.AddAttributes(DllImport(import, moduleName, entrypoint, requiresUnicodeCharSet ? CharSet.Unicode : CharSet.Ansi));
230+
231+
MethodDeclarationSyntax externDeclaration = MethodDeclaration(
232+
List<AttributeListSyntax>().Add(CreateDllImportAttributeList()),
233+
modifiers: TokenList(TokenWithSpace(SyntaxKind.StaticKeyword), TokenWithSpace(SyntaxKind.ExternKeyword)),
213234
returnType.Type.WithTrailingTrivia(TriviaList(Space)),
214235
explicitInterfaceSpecifier: null!,
215236
SafeIdentifier(methodName),
216237
null!,
217-
FixTrivia(this.CreateParameterList(methodDefinition, signature, typeSettings)),
238+
this.CreateParameterList(methodDefinition, signature, typeSettings),
218239
List<TypeParameterConstraintClauseSyntax>(),
219240
body: null!,
220241
TokenWithLineFeed(SyntaxKind.SemicolonToken));
221-
methodDeclaration = returnType.AddReturnMarshalAs(methodDeclaration);
242+
externDeclaration = returnType.AddReturnMarshalAs(externDeclaration);
222243

223244
if (this.generateDefaultDllImportSearchPathsAttribute)
224245
{
225-
methodDeclaration = methodDeclaration.AddAttributeLists(
246+
externDeclaration = externDeclaration.AddAttributeLists(
226247
IsLibraryAllowedAppLocal(moduleName) ? DefaultDllImportSearchPathsAllowAppDirAttributeList : DefaultDllImportSearchPathsAttributeList);
227248
}
228249

229-
if (this.GetSupportedOSPlatformAttribute(methodDefinition.GetCustomAttributes()) is AttributeSyntax supportedOSPlatformAttribute)
250+
bool requiresUnsafe = RequiresUnsafe(externDeclaration.ReturnType) || externDeclaration.ParameterList.Parameters.Any(p => RequiresUnsafe(p.Type));
251+
if (requiresUnsafe)
230252
{
231-
methodDeclaration = methodDeclaration.AddAttributeLists(AttributeList().AddAttributes(supportedOSPlatformAttribute));
253+
externDeclaration = externDeclaration.AddModifiers(TokenWithSpace(SyntaxKind.UnsafeKeyword));
232254
}
233255

234-
// Add documentation if we can find it.
235-
methodDeclaration = this.AddApiDocumentation(entrypoint ?? methodName, methodDeclaration);
256+
MethodDeclarationSyntax exposedMethod;
257+
if (returnTypeEnumName is null && parameterEnumType is null)
258+
{
259+
// No need for wrapping the extern method, so just expose it directly.
260+
exposedMethod = externDeclaration.WithModifiers(externDeclaration.Modifiers.Insert(0, TokenWithSpace(this.Visibility)));
261+
}
262+
else
263+
{
264+
string ns = this.GetMethodNamespace(methodDefinition);
265+
NameSyntax nsSyntax = ParseName(ReplaceCommonNamespaceWithAlias(this, ns));
266+
ParameterListSyntax exposedParameterList = this.CreateParameterList(methodDefinition, signature, typeSettings);
267+
static SyntaxToken RefInOutKeyword(ParameterSyntax p) =>
268+
p.Modifiers.Any(SyntaxKind.OutKeyword) ? TokenWithSpace(SyntaxKind.OutKeyword) :
269+
p.Modifiers.Any(SyntaxKind.RefKeyword) ? TokenWithSpace(SyntaxKind.RefKeyword) :
270+
default;
271+
ArgumentListSyntax argumentList = exposedParameterList.Parameters.Aggregate(ArgumentList(), (list, p) => list.AddArguments(Argument(IdentifierName(p.Identifier.ValueText)).WithRefKindKeyword(RefInOutKeyword(p))));
272+
if (parameterEnumType is not null)
273+
{
274+
for (int i = 0; i < parameterEnumType.Length; i++)
275+
{
276+
if (parameterEnumType[i] is TypeSyntax parameterType)
277+
{
278+
NameSyntax qualifiedParameterType = QualifiedName(nsSyntax, (SimpleNameSyntax)parameterType);
279+
exposedParameterList = exposedParameterList.ReplaceNode(exposedParameterList.Parameters[i], exposedParameterList.Parameters[i].WithType(qualifiedParameterType.WithTrailingTrivia(Space)));
280+
this.RequestInteropType(ns, parameterEnumType[i]!.ToString(), this.DefaultContext);
281+
argumentList = argumentList.ReplaceNode(argumentList.Arguments[i], argumentList.Arguments[i].WithExpression(CastExpression(externDeclaration.ParameterList.Parameters[i].Type!.WithTrailingTrivia(default(SyntaxTriviaList)), argumentList.Arguments[i].Expression)));
282+
}
283+
}
284+
}
285+
286+
// We need to specify Entrypoint because our local function will have a different name.
287+
// It must have a unique name because some functions will have the same signature as our exposed method except for the return type.
288+
entrypoint ??= methodName;
289+
IdentifierNameSyntax localExternFunctionName = IdentifierName("LocalExternFunction");
290+
ExpressionSyntax invocation = InvocationExpression(localExternFunctionName, argumentList);
291+
292+
if (returnTypeEnumName is not null)
293+
{
294+
this.RequestInteropType(ns, returnTypeEnumName.ToString(), this.DefaultContext);
295+
returnTypeEnumName = QualifiedName(nsSyntax, (SimpleNameSyntax)returnTypeEnumName);
296+
invocation = CastExpression(returnTypeEnumName, invocation);
297+
}
298+
299+
StatementSyntax forwardingStatement = returnType.Type is PredefinedTypeSyntax { Keyword.RawKind: (int)SyntaxKind.VoidKeyword } ? ExpressionStatement(invocation) : ReturnStatement(invocation);
300+
LocalFunctionStatementSyntax externFunction = LocalFunctionStatement(externDeclaration.ReturnType, localExternFunctionName.Identifier)
301+
.AddAttributeLists(CreateDllImportAttributeList().WithOpenBracketToken(Token(SyntaxKind.OpenBracketToken).WithLeadingTrivia(LineFeed)))
302+
.WithModifiers(externDeclaration.Modifiers)
303+
.WithParameterList(externDeclaration.ParameterList)
304+
.WithSemicolonToken(SemicolonWithLineFeed);
305+
306+
exposedMethod = MethodDeclaration(returnTypeEnumName ?? returnType.Type, externDeclaration.Identifier)
307+
.AddModifiers(TokenWithSpace(this.Visibility), TokenWithSpace(SyntaxKind.StaticKeyword))
308+
.WithParameterList(exposedParameterList)
309+
.AddBodyStatements(forwardingStatement, externFunction);
310+
if (requiresUnsafe)
311+
{
312+
exposedMethod = exposedMethod.AddModifiers(TokenWithSpace(SyntaxKind.UnsafeKeyword));
313+
}
314+
}
236315

237-
if (RequiresUnsafe(methodDeclaration.ReturnType) || methodDeclaration.ParameterList.Parameters.Any(p => RequiresUnsafe(p.Type)))
316+
if (this.GetSupportedOSPlatformAttribute(methodDefinition.GetCustomAttributes()) is AttributeSyntax supportedOSPlatformAttribute)
238317
{
239-
methodDeclaration = methodDeclaration.AddModifiers(TokenWithSpace(SyntaxKind.UnsafeKeyword));
318+
exposedMethod = exposedMethod.AddAttributeLists(AttributeList().AddAttributes(supportedOSPlatformAttribute));
240319
}
241320

242-
this.volatileCode.AddMemberToModule(moduleName, this.DeclareFriendlyOverloads(methodDefinition, methodDeclaration, this.methodsAndConstantsClassName, FriendlyOverloadOf.ExternMethod, this.injectedPInvokeHelperMethods));
243-
this.volatileCode.AddMemberToModule(moduleName, methodDeclaration);
321+
// Add documentation if we can find it.
322+
exposedMethod = this.AddApiDocumentation(entrypoint ?? methodName, exposedMethod);
323+
324+
this.volatileCode.AddMemberToModule(moduleName, this.DeclareFriendlyOverloads(methodDefinition, exposedMethod, this.methodsAndConstantsClassName, FriendlyOverloadOf.ExternMethod, this.injectedPInvokeHelperMethods));
325+
this.volatileCode.AddMemberToModule(moduleName, exposedMethod);
244326
}
245327
catch (Exception ex)
246328
{

src/Microsoft.Windows.CsWin32/Generator.Invariants.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ public partial class Generator
1010
internal const string MemorySizeAttribute = "MemorySizeAttribute";
1111
internal const string RAIIFreeAttribute = "RAIIFreeAttribute";
1212
internal const string DoNotReleaseAttribute = "DoNotReleaseAttribute";
13+
internal const string AssociatedEnumAttribute = "AssociatedEnumAttribute";
1314
internal const string GlobalNamespacePrefix = "global::";
1415
internal const string GlobalWinmdRootNamespaceAlias = "winmdroot";
1516
internal const string WinRTCustomMarshalerClass = "WinRTCustomMarshaler";

src/Microsoft.Windows.CsWin32/Generator.MetadataHelpers.cs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ namespace Microsoft.Windows.CsWin32;
55

66
public partial class Generator
77
{
8-
internal bool IsAttribute(CustomAttribute attribute, string ns, string name) => MetadataUtilities.IsAttribute(this.Reader, attribute, ns, name);
9-
108
internal NativeArrayInfo? FindNativeArrayInfoAttribute(CustomAttributeHandleCollection customAttributeHandles)
119
{
1210
return this.FindInteropDecorativeAttribute(customAttributeHandles, NativeArrayInfoAttribute) is CustomAttribute att
@@ -20,6 +18,17 @@ public partial class Generator
2018
internal CustomAttribute? FindAttribute(CustomAttributeHandleCollection? customAttributeHandles, string attributeNamespace, string attributeName)
2119
=> MetadataUtilities.FindAttribute(this.Reader, customAttributeHandles, attributeNamespace, attributeName);
2220

21+
internal IdentifierNameSyntax? FindAssociatedEnum(CustomAttributeHandleCollection? customAttributeHandles)
22+
{
23+
if (this.FindAttribute(customAttributeHandles, InteropDecorationNamespace, AssociatedEnumAttribute) is CustomAttribute att)
24+
{
25+
CustomAttributeValue<TypeSyntax> args = att.DecodeValue(CustomAttributeTypeProvider.Instance);
26+
return IdentifierName((string)args.FixedArguments[0].Value!);
27+
}
28+
29+
return null;
30+
}
31+
2332
internal bool TryGetTypeDefHandle(TypeReferenceHandle typeRefHandle, out QualifiedTypeDefinitionHandle typeDefHandle)
2433
{
2534
if (this.SuperGenerator is object)

src/Microsoft.Windows.CsWin32/Generator.Struct.cs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,32 @@ private StructDeclarationSyntax DeclareStruct(TypeDefinitionHandle typeDefHandle
7474
(TypeSyntax FieldType, SyntaxList<MemberDeclarationSyntax> AdditionalMembers, AttributeSyntax? MarshalAsAttribute) fieldInfo = this.ReinterpretFieldType(fieldDef, fieldTypeSyntax.Type, fieldAttributes, context);
7575
additionalMembers = additionalMembers.AddRange(fieldInfo.AdditionalMembers);
7676

77-
field = FieldDeclaration(VariableDeclaration(fieldInfo.FieldType).AddVariables(fieldDeclarator))
78-
.AddModifiers(TokenWithSpace(this.Visibility));
77+
PropertyDeclarationSyntax? property = null;
78+
if (this.FindAssociatedEnum(fieldAttributes) is { } propertyType)
79+
{
80+
// Keep the field with its original type, but then add a property that returns the enum type.
81+
fieldDeclarator = VariableDeclarator(SafeIdentifier($"_{fieldName}"));
82+
field = FieldDeclaration(VariableDeclaration(fieldInfo.FieldType).AddVariables(fieldDeclarator))
83+
.AddModifiers(TokenWithSpace(SyntaxKind.PrivateKeyword));
84+
85+
// internal EnumType FieldName {
86+
// get => (EnumType)this._fieldName;
87+
// set => this._fieldName = (UnderlyingType)value;
88+
// }
89+
this.RequestInteropType(this.Reader.GetString(typeDef.Namespace), propertyType.Identifier.ValueText, context);
90+
ExpressionSyntax fieldAccess = MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, ThisExpression(), IdentifierName(fieldDeclarator.Identifier));
91+
property = PropertyDeclaration(propertyType.WithTrailingTrivia(Space), Identifier(fieldName).WithTrailingTrivia(LineFeed))
92+
.AddModifiers(TokenWithSpace(this.Visibility))
93+
.WithAccessorList(AccessorList().AddAccessors(
94+
AccessorDeclaration(SyntaxKind.GetAccessorDeclaration).WithExpressionBody(ArrowExpressionClause(CastExpression(propertyType, fieldAccess))).WithSemicolonToken(Semicolon),
95+
AccessorDeclaration(SyntaxKind.SetAccessorDeclaration).WithExpressionBody(ArrowExpressionClause(AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, fieldAccess, CastExpression(fieldInfo.FieldType, IdentifierName("value"))))).WithSemicolonToken(Semicolon)));
96+
additionalMembers = additionalMembers.Add(property);
97+
}
98+
else
99+
{
100+
field = FieldDeclaration(VariableDeclaration(fieldInfo.FieldType).AddVariables(fieldDeclarator))
101+
.AddModifiers(TokenWithSpace(this.Visibility));
102+
}
79103

80104
if (fieldInfo.MarshalAsAttribute is object)
81105
{
@@ -85,6 +109,7 @@ private StructDeclarationSyntax DeclareStruct(TypeDefinitionHandle typeDefHandle
85109
if (this.HasObsoleteAttribute(fieldDef.GetCustomAttributes()))
86110
{
87111
field = field.AddAttributeLists(AttributeList().AddAttributes(ObsoleteAttributeSyntax));
112+
property = property?.AddAttributeLists(AttributeList().AddAttributes(ObsoleteAttributeSyntax));
88113
}
89114

90115
if (fieldInfo.FieldType is PointerTypeSyntax || fieldInfo.FieldType is FunctionPointerTypeSyntax)

0 commit comments

Comments
 (0)