Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update metadata to 52.0.65-preview #937

Merged
merged 2 commits into from
May 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>

<MetadataVersion>51.0.33-preview</MetadataVersion>
<MetadataVersion>52.0.65-preview</MetadataVersion>
<!-- <DiaMetadataVersion>0.2.185-preview-g7e1e6a442c</DiaMetadataVersion> -->
<ApiDocsVersion>0.1.41-alpha</ApiDocsVersion>

Expand Down
2 changes: 2 additions & 0 deletions src/Microsoft.Windows.CsWin32/FastSyntaxFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,8 @@ internal static SyntaxToken XmlTextNewLine(string text, bool continueXmlDocument

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));

internal static LocalFunctionStatementSyntax LocalFunctionStatement(TypeSyntax returnType, SyntaxToken identifier) => SyntaxFactory.LocalFunctionStatement(default(SyntaxList<AttributeListSyntax>), default(SyntaxTokenList), returnType, identifier, null, ParameterList(), default(SyntaxList<TypeParameterConstraintClauseSyntax>), null, null);

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);

internal static MemberDeclarationSyntax? ParseMemberDeclaration(string text, ParseOptions? options) => SyntaxFactory.ParseMemberDeclaration(text, options: options);
Expand Down
118 changes: 100 additions & 18 deletions src/Microsoft.Windows.CsWin32/Generator.Extern.cs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ public bool TryGenerateExternMethod(string possiblyQualifiedName, out IReadOnlyL
this.RequestExternMethod(methodDefHandle);
});

string methodNamespace = this.Reader.GetString(this.Reader.GetTypeDefinition(methodDef.GetDeclaringType()).Namespace);
string methodNamespace = this.GetMethodNamespace(methodDef);
preciseApi = ImmutableList.Create($"{methodNamespace}.{methodName}");
return true;
}
Expand Down Expand Up @@ -168,6 +168,8 @@ private static bool IsLibraryAllowedAppLocal(string libraryName)
return false;
}

private string GetMethodNamespace(MethodDefinition methodDef) => this.Reader.GetString(this.Reader.GetTypeDefinition(methodDef.GetDeclaringType()).Namespace);

private void DeclareExternMethod(MethodDefinitionHandle methodDefinitionHandle)
{
MethodDefinition methodDefinition = this.Reader.GetMethodDefinition(methodDefinitionHandle);
Expand Down Expand Up @@ -204,43 +206,123 @@ private void DeclareExternMethod(MethodDefinitionHandle methodDefinitionHandle)
CustomAttributeHandleCollection? returnTypeAttributes = this.GetReturnTypeCustomAttributes(methodDefinition);
TypeSyntaxAndMarshaling returnType = signature.ReturnType.ToTypeSyntax(typeSettings, returnTypeAttributes, ParameterAttributes.Out);

MethodDeclarationSyntax methodDeclaration = MethodDeclaration(
List<AttributeListSyntax>()
.Add(AttributeList()
.WithCloseBracketToken(TokenWithLineFeed(SyntaxKind.CloseBracketToken))
.AddAttributes(DllImport(import, moduleName, entrypoint, requiresUnicodeCharSet ? CharSet.Unicode : CharSet.Ansi))),
modifiers: TokenList(TokenWithSpace(this.Visibility), TokenWithSpace(SyntaxKind.StaticKeyword), TokenWithSpace(SyntaxKind.ExternKeyword)),
// Search for any enum substitutions.
TypeSyntax? returnTypeEnumName = this.FindAssociatedEnum(returnTypeAttributes);
TypeSyntax?[]? parameterEnumType = null;
foreach (ParameterHandle parameterHandle in methodDefinition.GetParameters())
{
Parameter parameter = this.Reader.GetParameter(parameterHandle);
if (parameter.SequenceNumber == 0)
{
continue;
}

if (this.FindAssociatedEnum(parameter.GetCustomAttributes()) is IdentifierNameSyntax parameterEnumName)
{
parameterEnumType ??= new TypeSyntax?[signature.ParameterTypes.Length];
parameterEnumType[parameter.SequenceNumber - 1] = parameterEnumName;
}
}

AttributeListSyntax CreateDllImportAttributeList() => AttributeList()
.WithCloseBracketToken(TokenWithLineFeed(SyntaxKind.CloseBracketToken))
.AddAttributes(DllImport(import, moduleName, entrypoint, requiresUnicodeCharSet ? CharSet.Unicode : CharSet.Ansi));

MethodDeclarationSyntax externDeclaration = MethodDeclaration(
List<AttributeListSyntax>().Add(CreateDllImportAttributeList()),
modifiers: TokenList(TokenWithSpace(SyntaxKind.StaticKeyword), TokenWithSpace(SyntaxKind.ExternKeyword)),
returnType.Type.WithTrailingTrivia(TriviaList(Space)),
explicitInterfaceSpecifier: null!,
SafeIdentifier(methodName),
null!,
FixTrivia(this.CreateParameterList(methodDefinition, signature, typeSettings)),
this.CreateParameterList(methodDefinition, signature, typeSettings),
List<TypeParameterConstraintClauseSyntax>(),
body: null!,
TokenWithLineFeed(SyntaxKind.SemicolonToken));
methodDeclaration = returnType.AddReturnMarshalAs(methodDeclaration);
externDeclaration = returnType.AddReturnMarshalAs(externDeclaration);

if (this.generateDefaultDllImportSearchPathsAttribute)
{
methodDeclaration = methodDeclaration.AddAttributeLists(
externDeclaration = externDeclaration.AddAttributeLists(
IsLibraryAllowedAppLocal(moduleName) ? DefaultDllImportSearchPathsAllowAppDirAttributeList : DefaultDllImportSearchPathsAttributeList);
}

if (this.GetSupportedOSPlatformAttribute(methodDefinition.GetCustomAttributes()) is AttributeSyntax supportedOSPlatformAttribute)
bool requiresUnsafe = RequiresUnsafe(externDeclaration.ReturnType) || externDeclaration.ParameterList.Parameters.Any(p => RequiresUnsafe(p.Type));
if (requiresUnsafe)
{
methodDeclaration = methodDeclaration.AddAttributeLists(AttributeList().AddAttributes(supportedOSPlatformAttribute));
externDeclaration = externDeclaration.AddModifiers(TokenWithSpace(SyntaxKind.UnsafeKeyword));
}

// Add documentation if we can find it.
methodDeclaration = this.AddApiDocumentation(entrypoint ?? methodName, methodDeclaration);
MethodDeclarationSyntax exposedMethod;
if (returnTypeEnumName is null && parameterEnumType is null)
{
// No need for wrapping the extern method, so just expose it directly.
exposedMethod = externDeclaration.WithModifiers(externDeclaration.Modifiers.Insert(0, TokenWithSpace(this.Visibility)));
}
else
{
string ns = this.GetMethodNamespace(methodDefinition);
NameSyntax nsSyntax = ParseName(ReplaceCommonNamespaceWithAlias(this, ns));
ParameterListSyntax exposedParameterList = this.CreateParameterList(methodDefinition, signature, typeSettings);
static SyntaxToken RefInOutKeyword(ParameterSyntax p) =>
p.Modifiers.Any(SyntaxKind.OutKeyword) ? TokenWithSpace(SyntaxKind.OutKeyword) :
p.Modifiers.Any(SyntaxKind.RefKeyword) ? TokenWithSpace(SyntaxKind.RefKeyword) :
default;
ArgumentListSyntax argumentList = exposedParameterList.Parameters.Aggregate(ArgumentList(), (list, p) => list.AddArguments(Argument(IdentifierName(p.Identifier.ValueText)).WithRefKindKeyword(RefInOutKeyword(p))));
if (parameterEnumType is not null)
{
for (int i = 0; i < parameterEnumType.Length; i++)
{
if (parameterEnumType[i] is TypeSyntax parameterType)
{
NameSyntax qualifiedParameterType = QualifiedName(nsSyntax, (SimpleNameSyntax)parameterType);
exposedParameterList = exposedParameterList.ReplaceNode(exposedParameterList.Parameters[i], exposedParameterList.Parameters[i].WithType(qualifiedParameterType.WithTrailingTrivia(Space)));
this.RequestInteropType(ns, parameterEnumType[i]!.ToString(), this.DefaultContext);
argumentList = argumentList.ReplaceNode(argumentList.Arguments[i], argumentList.Arguments[i].WithExpression(CastExpression(externDeclaration.ParameterList.Parameters[i].Type!.WithTrailingTrivia(default(SyntaxTriviaList)), argumentList.Arguments[i].Expression)));
}
}
}

// We need to specify Entrypoint because our local function will have a different name.
// It must have a unique name because some functions will have the same signature as our exposed method except for the return type.
entrypoint ??= methodName;
IdentifierNameSyntax localExternFunctionName = IdentifierName("LocalExternFunction");
ExpressionSyntax invocation = InvocationExpression(localExternFunctionName, argumentList);

if (returnTypeEnumName is not null)
{
this.RequestInteropType(ns, returnTypeEnumName.ToString(), this.DefaultContext);
returnTypeEnumName = QualifiedName(nsSyntax, (SimpleNameSyntax)returnTypeEnumName);
invocation = CastExpression(returnTypeEnumName, invocation);
}

StatementSyntax forwardingStatement = returnType.Type is PredefinedTypeSyntax { Keyword.RawKind: (int)SyntaxKind.VoidKeyword } ? ExpressionStatement(invocation) : ReturnStatement(invocation);
LocalFunctionStatementSyntax externFunction = LocalFunctionStatement(externDeclaration.ReturnType, localExternFunctionName.Identifier)
.AddAttributeLists(CreateDllImportAttributeList().WithOpenBracketToken(Token(SyntaxKind.OpenBracketToken).WithLeadingTrivia(LineFeed)))
.WithModifiers(externDeclaration.Modifiers)
.WithParameterList(externDeclaration.ParameterList)
.WithSemicolonToken(SemicolonWithLineFeed);

exposedMethod = MethodDeclaration(returnTypeEnumName ?? returnType.Type, externDeclaration.Identifier)
.AddModifiers(TokenWithSpace(this.Visibility), TokenWithSpace(SyntaxKind.StaticKeyword))
.WithParameterList(exposedParameterList)
.AddBodyStatements(forwardingStatement, externFunction);
if (requiresUnsafe)
{
exposedMethod = exposedMethod.AddModifiers(TokenWithSpace(SyntaxKind.UnsafeKeyword));
}
}

if (RequiresUnsafe(methodDeclaration.ReturnType) || methodDeclaration.ParameterList.Parameters.Any(p => RequiresUnsafe(p.Type)))
if (this.GetSupportedOSPlatformAttribute(methodDefinition.GetCustomAttributes()) is AttributeSyntax supportedOSPlatformAttribute)
{
methodDeclaration = methodDeclaration.AddModifiers(TokenWithSpace(SyntaxKind.UnsafeKeyword));
exposedMethod = exposedMethod.AddAttributeLists(AttributeList().AddAttributes(supportedOSPlatformAttribute));
}

this.volatileCode.AddMemberToModule(moduleName, this.DeclareFriendlyOverloads(methodDefinition, methodDeclaration, this.methodsAndConstantsClassName, FriendlyOverloadOf.ExternMethod, this.injectedPInvokeHelperMethods));
this.volatileCode.AddMemberToModule(moduleName, methodDeclaration);
// Add documentation if we can find it.
exposedMethod = this.AddApiDocumentation(entrypoint ?? methodName, exposedMethod);

this.volatileCode.AddMemberToModule(moduleName, this.DeclareFriendlyOverloads(methodDefinition, exposedMethod, this.methodsAndConstantsClassName, FriendlyOverloadOf.ExternMethod, this.injectedPInvokeHelperMethods));
this.volatileCode.AddMemberToModule(moduleName, exposedMethod);
}
catch (Exception ex)
{
Expand Down
1 change: 1 addition & 0 deletions src/Microsoft.Windows.CsWin32/Generator.Invariants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public partial class Generator
internal const string MemorySizeAttribute = "MemorySizeAttribute";
internal const string RAIIFreeAttribute = "RAIIFreeAttribute";
internal const string DoNotReleaseAttribute = "DoNotReleaseAttribute";
internal const string AssociatedEnumAttribute = "AssociatedEnumAttribute";
internal const string GlobalNamespacePrefix = "global::";
internal const string GlobalWinmdRootNamespaceAlias = "winmdroot";
internal const string WinRTCustomMarshalerClass = "WinRTCustomMarshaler";
Expand Down
13 changes: 11 additions & 2 deletions src/Microsoft.Windows.CsWin32/Generator.MetadataHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ namespace Microsoft.Windows.CsWin32;

public partial class Generator
{
internal bool IsAttribute(CustomAttribute attribute, string ns, string name) => MetadataUtilities.IsAttribute(this.Reader, attribute, ns, name);

internal NativeArrayInfo? FindNativeArrayInfoAttribute(CustomAttributeHandleCollection customAttributeHandles)
{
return this.FindInteropDecorativeAttribute(customAttributeHandles, NativeArrayInfoAttribute) is CustomAttribute att
Expand All @@ -20,6 +18,17 @@ public partial class Generator
internal CustomAttribute? FindAttribute(CustomAttributeHandleCollection? customAttributeHandles, string attributeNamespace, string attributeName)
=> MetadataUtilities.FindAttribute(this.Reader, customAttributeHandles, attributeNamespace, attributeName);

internal IdentifierNameSyntax? FindAssociatedEnum(CustomAttributeHandleCollection? customAttributeHandles)
{
if (this.FindAttribute(customAttributeHandles, InteropDecorationNamespace, AssociatedEnumAttribute) is CustomAttribute att)
{
CustomAttributeValue<TypeSyntax> args = att.DecodeValue(CustomAttributeTypeProvider.Instance);
return IdentifierName((string)args.FixedArguments[0].Value!);
}

return null;
}

internal bool TryGetTypeDefHandle(TypeReferenceHandle typeRefHandle, out QualifiedTypeDefinitionHandle typeDefHandle)
{
if (this.SuperGenerator is object)
Expand Down
29 changes: 27 additions & 2 deletions src/Microsoft.Windows.CsWin32/Generator.Struct.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,32 @@ private StructDeclarationSyntax DeclareStruct(TypeDefinitionHandle typeDefHandle
(TypeSyntax FieldType, SyntaxList<MemberDeclarationSyntax> AdditionalMembers, AttributeSyntax? MarshalAsAttribute) fieldInfo = this.ReinterpretFieldType(fieldDef, fieldTypeSyntax.Type, fieldAttributes, context);
additionalMembers = additionalMembers.AddRange(fieldInfo.AdditionalMembers);

field = FieldDeclaration(VariableDeclaration(fieldInfo.FieldType).AddVariables(fieldDeclarator))
.AddModifiers(TokenWithSpace(this.Visibility));
PropertyDeclarationSyntax? property = null;
if (this.FindAssociatedEnum(fieldAttributes) is { } propertyType)
{
// Keep the field with its original type, but then add a property that returns the enum type.
fieldDeclarator = VariableDeclarator(SafeIdentifier($"_{fieldName}"));
field = FieldDeclaration(VariableDeclaration(fieldInfo.FieldType).AddVariables(fieldDeclarator))
.AddModifiers(TokenWithSpace(SyntaxKind.PrivateKeyword));

// internal EnumType FieldName {
// get => (EnumType)this._fieldName;
// set => this._fieldName = (UnderlyingType)value;
// }
this.RequestInteropType(this.Reader.GetString(typeDef.Namespace), propertyType.Identifier.ValueText, context);
ExpressionSyntax fieldAccess = MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, ThisExpression(), IdentifierName(fieldDeclarator.Identifier));
property = PropertyDeclaration(propertyType.WithTrailingTrivia(Space), Identifier(fieldName).WithTrailingTrivia(LineFeed))
.AddModifiers(TokenWithSpace(this.Visibility))
.WithAccessorList(AccessorList().AddAccessors(
AccessorDeclaration(SyntaxKind.GetAccessorDeclaration).WithExpressionBody(ArrowExpressionClause(CastExpression(propertyType, fieldAccess))).WithSemicolonToken(Semicolon),
AccessorDeclaration(SyntaxKind.SetAccessorDeclaration).WithExpressionBody(ArrowExpressionClause(AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, fieldAccess, CastExpression(fieldInfo.FieldType, IdentifierName("value"))))).WithSemicolonToken(Semicolon)));
additionalMembers = additionalMembers.Add(property);
}
else
{
field = FieldDeclaration(VariableDeclaration(fieldInfo.FieldType).AddVariables(fieldDeclarator))
.AddModifiers(TokenWithSpace(this.Visibility));
}

if (fieldInfo.MarshalAsAttribute is object)
{
Expand All @@ -85,6 +109,7 @@ private StructDeclarationSyntax DeclareStruct(TypeDefinitionHandle typeDefHandle
if (this.HasObsoleteAttribute(fieldDef.GetCustomAttributes()))
{
field = field.AddAttributeLists(AttributeList().AddAttributes(ObsoleteAttributeSyntax));
property = property?.AddAttributeLists(AttributeList().AddAttributes(ObsoleteAttributeSyntax));
}

if (fieldInfo.FieldType is PointerTypeSyntax || fieldInfo.FieldType is FunctionPointerTypeSyntax)
Expand Down
Loading