diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/AttributeInfo.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/AttributeInfo.cs
index fed18f1eb50a6f..7f4b487ad976f6 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/AttributeInfo.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/AttributeInfo.cs
@@ -4,27 +4,17 @@
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
-using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
namespace Microsoft.Interop
{
///
/// Provides the info necessary for copying an attribute from user code to generated code.
///
- internal sealed record AttributeInfo(ManagedTypeInfo Type, SequenceEqualImmutableArray Arguments)
+ internal sealed record AttributeInfo(string Type, SequenceEqualImmutableArray Arguments)
{
- internal AttributeSyntax GenerateSyntax()
- {
- return Attribute((NameSyntax)Type.Syntax, AttributeArgumentList(SeparatedList(Arguments.Select(arg => AttributeArgument(ParseExpression(arg))))));
- }
- internal AttributeListSyntax GenerateAttributeList()
- {
- return AttributeList(SingletonSeparatedList(GenerateSyntax()));
- }
internal static AttributeInfo From(AttributeData attribute)
{
- var type = ManagedTypeInfo.CreateTypeInfoForTypeSymbol(attribute.AttributeClass);
+ var type = attribute.AttributeClass.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
var args = attribute.ConstructorArguments.Select(ca => ca.ToCSharpString());
return new(type, args.ToSequenceEqualImmutableArray());
}
diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.cs
index 116ee786fb86cd..dad35781688f1a 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
+using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
@@ -12,27 +13,12 @@
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
-using static Microsoft.Interop.SyntaxFactoryExtensions;
namespace Microsoft.Interop
{
[Generator]
public sealed partial class ComInterfaceGenerator : IIncrementalGenerator
{
- public static class StepNames
- {
- public const string CalculateStubInformation = nameof(CalculateStubInformation);
- public const string GenerateManagedToNativeStub = nameof(GenerateManagedToNativeStub);
- public const string GenerateNativeToManagedStub = nameof(GenerateNativeToManagedStub);
- public const string GenerateManagedToNativeInterfaceImplementation = nameof(GenerateManagedToNativeInterfaceImplementation);
- public const string GenerateNativeToManagedVTableMethods = nameof(GenerateNativeToManagedVTableMethods);
- public const string GenerateNativeToManagedVTableStruct = nameof(GenerateNativeToManagedVTableStruct);
- public const string GenerateNativeToManagedVTable = nameof(GenerateNativeToManagedVTable);
- public const string GenerateInterfaceInformation = nameof(GenerateInterfaceInformation);
- public const string GenerateIUnknownDerivedAttribute = nameof(GenerateIUnknownDerivedAttribute);
- public const string GenerateShadowingMethods = nameof(GenerateShadowingMethods);
- }
-
public void Initialize(IncrementalGeneratorInitializationContext context)
{
var stubEnvironment = context.CreateStubEnvironmentProvider();
@@ -143,99 +129,37 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
.SelectMany(static (data, ct) =>
GroupComContextsForInterfaceGeneration(data.Left.Array, data.Right, ct));
- // Generate the code for the managed-to-unmanaged stubs.
- var syntaxes = interfaceAndMethodsContexts
- .Select(static (x, ct) => new ItemAndSyntaxes(x,
- [
- GenerateImplementationInterface(x, ct).NormalizeWhitespace(),
- GenerateInterfaceImplementationVtable(x, ct).NormalizeWhitespace(),
- GenerateImplementationVTableMethods(x, ct).NormalizeWhitespace(),
- GenerateShadowingMethodsInterface(x),
- GenerateImplementationVTable(x, ct).NormalizeWhitespace(),
- GenerateInterfaceInformation(x.Interface.Info, ct).NormalizeWhitespace(),
- GenerateIUnknownDerivedAttributeApplication(x.Interface.Info, ct).NormalizeWhitespace()
- ]));
-
- var filesToGenerate = syntaxes
- .Select(static (methodSyntaxes, ct) =>
+ context.RegisterSourceOutput(interfaceAndMethodsContexts, static (context, data) =>
+ {
+ ComInterfaceContext interfaceContext = data.Interface;
+
+ using StringWriter sw = new();
+ using IndentedTextWriter writer = new(sw);
+ writer.WriteLine("// ");
+ writer.WriteLine("#pragma warning disable CS0612, CS0618, CS0649, CS1591"); // Suppress warnings about [Obsolete], "lack of assignment", and missing XML documentation in generated code.
+
+ // If the user has specified 'ManagedObjectWrapper', it means that the COM interface will never be used to marshal a native
+ // object as an RCW (eg. the IDIC vtable will also not be generated, nor any additional supporting code). To reduce binary
+ // size, we're not emitting the interface methods on the implementation interface that has '[DynamicInterfaceCastableImplementation]'
+ // on it. However, doing so will cause the CA2256 warning to be produced. We can't remove the attribute, as that would cause
+ // the wrong exception to be thrown when trying an IDIC cast with this interface (not 'InvalidCastException'). Because this is
+ // a niche scenario, and we don't want to regress perf or size, we can just disable the warning instead.
+ if (interfaceContext.Options is ComInterfaceOptions.ManagedObjectWrapper)
{
- var interfaceContext = methodSyntaxes.Context.Interface;
- var managedToNativeInterfaceImplementations = (InterfaceDeclarationSyntax)methodSyntaxes[0];
- var nativeToManagedVtableStructs = (StructDeclarationSyntax)methodSyntaxes[1];
- var nativeToManagedStubs = (InterfaceDeclarationSyntax)methodSyntaxes[2];
- var shadowingMethod = (MemberDeclarationSyntax)methodSyntaxes[3];
- var nativeToManagedVtable = (InterfaceDeclarationSyntax)methodSyntaxes[4];
- var interfaceInfo = (ClassDeclarationSyntax)methodSyntaxes[5];
- var iUnknownDerivedAttribute = (MemberDeclarationSyntax)methodSyntaxes[6];
-
- using StringWriter source = new();
- source.WriteLine("// ");
- source.WriteLine("#pragma warning disable CS0612, CS0618, CS0649, CS1591"); // Suppress warnings about [Obsolete], "lack of assignment", and missing XML documentation in generated code.
-
- // If the user has specified 'ManagedObjectWrapper', it means that the COM interface will never be used to marshal a native
- // object as an RCW (eg. the IDIC vtable will also not be generated, nor any additional supporting code). To reduce binary
- // size, we're not emitting the interface methods on the implementation interface that has '[DynamicInterfaceCastableImplementation]'
- // on it. However, doing so will cause the CA2256 warning to be produced. We can't remove the attribute, as that would cause
- // the wrong exception to be thrown when trying an IDIC cast with this interface (not 'InvalidCastException'). Because this is
- // a niche scenario, and we don't want to regress perf or size, we can just disable the warning instead.
- if (interfaceContext.Options is ComInterfaceOptions.ManagedObjectWrapper)
- {
- source.WriteLine("#pragma warning disable CA2256");
- }
+ writer.WriteLine("#pragma warning disable CA2256");
+ }
- interfaceInfo.WriteTo(source);
- // Two newlines looks cleaner than one
- source.WriteLine();
- source.WriteLine();
- // TODO: Merge the three InterfaceImplementation partials? We have them all right here.
- managedToNativeInterfaceImplementations.WriteTo(source);
- source.WriteLine();
- source.WriteLine();
- nativeToManagedStubs.WriteTo(source);
- source.WriteLine();
- source.WriteLine();
- nativeToManagedVtableStructs.WriteTo(source);
- source.WriteLine();
- source.WriteLine();
- nativeToManagedVtable.WriteTo(source);
- source.WriteLine();
- source.WriteLine();
- iUnknownDerivedAttribute.WriteTo(source);
- source.WriteLine();
- source.WriteLine();
- shadowingMethod.WriteTo(source);
- return new { TypeName = interfaceContext.Info.Type.FullTypeName, Source = source.ToString() };
- });
-
- context.RegisterSourceOutput(filesToGenerate, static (context, data) =>
- {
- context.AddSource(data.TypeName.Replace(TypeNames.GlobalAlias, ""), data.Source);
- });
- }
+ sw.WriteLine();
+ WriteImplementationVTableStruct(writer, data);
+ sw.WriteLine();
+ WriteInterfaceInformation(writer, interfaceContext.Info);
+ sw.WriteLine();
+ WriteInterfaceImplementation(writer, data);
+ sw.WriteLine();
+ WriteIUnknownDerivedOriginalInterfacePart(writer, data);
- private static readonly AttributeSyntax s_iUnknownDerivedAttributeTemplate =
- Attribute(
- GenericName(TypeNames.GlobalAlias + TypeNames.IUnknownDerivedAttribute)
- .AddTypeArgumentListArguments(
- IdentifierName("InterfaceInformation"),
- IdentifierName("InterfaceImplementation")));
-
- private static MemberDeclarationSyntax GenerateIUnknownDerivedAttributeApplication(ComInterfaceInfo context, CancellationToken _)
- => context.TypeDefinitionContext.WrapMemberInContainingSyntaxWithUnsafeModifier(
- TypeDeclaration(context.ContainingSyntax.TypeKind, context.ContainingSyntax.Identifier)
- .WithModifiers(context.ContainingSyntax.Modifiers)
- .WithTypeParameterList(context.ContainingSyntax.TypeParameters)
- .AddAttributeLists(AttributeList(SingletonSeparatedList(s_iUnknownDerivedAttributeTemplate))));
-
- private static MemberDeclarationSyntax GenerateShadowingMethodsInterface(ComInterfaceAndMethodsContext interfaceMethods)
- {
- var containingSyntax = interfaceMethods.Interface.Info.ContainingSyntax;
- return interfaceMethods.Interface.Info.TypeDefinitionContext.WrapMemberInContainingSyntaxWithUnsafeModifier(
- TypeDeclaration(containingSyntax.TypeKind, containingSyntax.Identifier)
- .WithModifiers(containingSyntax.Modifiers.AddToModifiers(SyntaxKind.UnsafeKeyword))
- .WithTypeParameterList(containingSyntax.TypeParameters)
- .WithMembers(List(interfaceMethods.ShadowingMethods.Select(m => m.Shadow))))
- .NormalizeWhitespace();
+ context.AddSource(interfaceContext.Info.Type.FullTypeName.Replace(TypeNames.GlobalAlias, ""), sw.ToString());
+ });
}
private static bool IsHResultLikeType(ManagedTypeInfo type)
@@ -542,108 +466,15 @@ static bool MethodEquals(ComMethodContext a, ComMethodContext b)
}
}
- private static readonly InterfaceDeclarationSyntax ImplementationInterfaceTemplate = InterfaceDeclaration("InterfaceImplementation")
- .WithModifiers(TokenList(Token(SyntaxKind.FileKeyword), Token(SyntaxKind.UnsafeKeyword), Token(SyntaxKind.PartialKeyword)));
-
- private static InterfaceDeclarationSyntax GenerateImplementationInterface(ComInterfaceAndMethodsContext interfaceGroup, CancellationToken _)
- {
- var definingType = interfaceGroup.Interface.Info.Type;
- var shadowImplementations = interfaceGroup.InheritedMethods.Where(m => !m.IsExternallyDefined).Select(m => (Method: m, ManagedToUnmanagedStub: m.ManagedToUnmanagedStub))
- .Where(p => p.ManagedToUnmanagedStub is GeneratedStubCodeContext)
- .Select(ctx => ((GeneratedStubCodeContext)ctx.ManagedToUnmanagedStub).Stub.Node
- .WithExplicitInterfaceSpecifier(
- ExplicitInterfaceSpecifier(ParseName(definingType.FullTypeName))));
- var inheritedStubs = interfaceGroup.InheritedMethods.Where(m => !m.IsExternallyDefined).Select(m => m.UnreachableExceptionStub);
- return ImplementationInterfaceTemplate
- .AddBaseListTypes(SimpleBaseType(definingType.Syntax))
- .WithMembers(
- List(
- interfaceGroup.DeclaredMethods
- .Select(m => m.ManagedToUnmanagedStub)
- .OfType()
- .Select(ctx => ctx.Stub.Node)
- .Concat(shadowImplementations)
- .Concat(inheritedStubs)))
- .AddAttributeLists(AttributeList(SingletonSeparatedList(Attribute(NameSyntaxes.System_Runtime_InteropServices_DynamicInterfaceCastableImplementationAttribute))));
- }
-
- private static InterfaceDeclarationSyntax GenerateImplementationVTableMethods(ComInterfaceAndMethodsContext comInterfaceAndMethods, CancellationToken _)
+ private static void WriteImplementationVTableStruct(IndentedTextWriter writer, ComInterfaceAndMethodsContext interfaceMethods)
{
- return ImplementationInterfaceTemplate
- .WithMembers(
- List(
- comInterfaceAndMethods.DeclaredMethods
- .Select(m => m.UnmanagedToManagedStub)
- .OfType()
- .Where(context => context.Diagnostics.All(diag => diag.Descriptor.DefaultSeverity != DiagnosticSeverity.Error))
- .Select(context => context.Stub.Node)));
- }
-
- private static readonly StructDeclarationSyntax InterfaceImplementationVtableTemplate = StructDeclaration("InterfaceImplementationVtable")
- .WithModifiers(TokenList(Token(SyntaxKind.FileKeyword), Token(SyntaxKind.UnsafeKeyword)));
-
- private static StructDeclarationSyntax GenerateInterfaceImplementationVtable(ComInterfaceAndMethodsContext interfaceMethods, CancellationToken _)
- {
- StructDeclarationSyntax vtableDeclaration =
- InterfaceImplementationVtableTemplate
- .AddMembers(
- FieldDeclaration(
- VariableDeclaration(
- FunctionPointerType(
- FunctionPointerCallingConvention(
- Token(SyntaxKind.UnmanagedKeyword),
- FunctionPointerUnmanagedCallingConventionList(
- SingletonSeparatedList(
- FunctionPointerUnmanagedCallingConvention(Identifier("MemberFunction"))))),
- FunctionPointerParameterList(
- SeparatedList([
- FunctionPointerParameter(TypeSyntaxes.VoidStar),
- FunctionPointerParameter(PointerType(TypeSyntaxes.System_Guid)),
- FunctionPointerParameter(TypeSyntaxes.VoidStarStar),
- FunctionPointerParameter(ParseTypeName("int"))]))))
- .AddVariables(VariableDeclarator("QueryInterface_0")))
- .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword))),
- FieldDeclaration(
- VariableDeclaration(
- FunctionPointerType(
- FunctionPointerCallingConvention(
- Token(SyntaxKind.UnmanagedKeyword),
- FunctionPointerUnmanagedCallingConventionList(
- SingletonSeparatedList(
- FunctionPointerUnmanagedCallingConvention(Identifier("MemberFunction"))))),
- FunctionPointerParameterList(
- SeparatedList([
- FunctionPointerParameter(TypeSyntaxes.VoidStar),
- FunctionPointerParameter(ParseTypeName("uint"))]))))
- .AddVariables(VariableDeclarator("AddRef_1")))
- .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword))),
- FieldDeclaration(
- VariableDeclaration(
- FunctionPointerType(
- FunctionPointerCallingConvention(
- Token(SyntaxKind.UnmanagedKeyword),
- FunctionPointerUnmanagedCallingConventionList(
- SingletonSeparatedList(
- FunctionPointerUnmanagedCallingConvention(Identifier("MemberFunction"))))),
- FunctionPointerParameterList(
- SeparatedList([
- FunctionPointerParameter(TypeSyntaxes.VoidStar),
- FunctionPointerParameter(ParseTypeName("uint"))]))))
- .AddVariables(VariableDeclarator("Release_2")))
- .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword))))
- .AddAttributeLists(
- AttributeList(
- SingletonSeparatedList(
- Attribute(
- NameSyntaxes.System_Runtime_InteropServices_StructLayoutAttribute,
- AttributeArgumentList(
- SingletonSeparatedList(
- AttributeArgument(
- MemberAccessExpression(
- SyntaxKind.SimpleMemberAccessExpression,
- TypeSyntaxes.System_Runtime_InteropServices_LayoutKind,
- IdentifierName("Sequential")))))))));
-
+ writer.WriteLine("[global::System.Runtime.InteropServices.StructLayoutAttribute(global::System.Runtime.InteropServices.LayoutKind.Sequential)]");
+ writer.WriteLine("file unsafe struct InterfaceImplementationVtable");
+ writer.WriteLine('{');
+ writer.Indent++;
+ writer.WriteLine("public delegate* unmanaged[MemberFunction] QueryInterface_0;");
+ writer.WriteLine("public delegate* unmanaged[MemberFunction] AddRef_1;");
+ writer.WriteLine("public delegate* unmanaged[MemberFunction] Release_2;");
if (interfaceMethods.Interface.Base is not null)
{
foreach (ComMethodContext inheritedMethod in interfaceMethods.InheritedMethods)
@@ -652,239 +483,168 @@ private static StructDeclarationSyntax GenerateInterfaceImplementationVtable(Com
inheritedMethod.GenerationContext,
ComInterfaceGeneratorHelpers.GetGeneratorResolver);
- vtableDeclaration = vtableDeclaration
- .AddMembers(
- FieldDeclaration(
- VariableDeclaration(functionPointerType)
- .AddVariables(VariableDeclarator($"{inheritedMethod.MethodInfo.MethodName}_{inheritedMethod.GenerationContext.VtableIndexData.Index}")))
- .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword))));
+ writer.WriteLine($"public {functionPointerType.NormalizeWhitespace()} {inheritedMethod.MethodInfo.MethodName}_{inheritedMethod.GenerationContext.VtableIndexData.Index};");
}
}
foreach (ComMethodContext declaredMethod in
interfaceMethods.DeclaredMethods
- .Where(context => context.UnmanagedToManagedStub.Diagnostics.All(diag => diag.Descriptor.DefaultSeverity != DiagnosticSeverity.Error)))
+ .Where(context => context.UnmanagedToManagedStub.Diagnostics.All(diag => diag.Descriptor.DefaultSeverity != DiagnosticSeverity.Error)))
{
FunctionPointerTypeSyntax functionPointerType = VirtualMethodPointerStubGenerator.GenerateUnmanagedFunctionPointerTypeForMethod(
- declaredMethod.GenerationContext,
- ComInterfaceGeneratorHelpers.GetGeneratorResolver);
+ declaredMethod.GenerationContext,
+ ComInterfaceGeneratorHelpers.GetGeneratorResolver);
- vtableDeclaration = vtableDeclaration
- .AddMembers(
- FieldDeclaration(
- VariableDeclaration(functionPointerType)
- .AddVariables(VariableDeclarator($"{declaredMethod.MethodInfo.MethodName}_{declaredMethod.GenerationContext.VtableIndexData.Index}")))
- .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword))));
+ writer.WriteLine($"public {functionPointerType.NormalizeWhitespace()} {declaredMethod.MethodInfo.MethodName}_{declaredMethod.GenerationContext.VtableIndexData.Index};");
}
- return vtableDeclaration;
+ writer.Indent--;
+ writer.WriteLine('}');
}
- private static InterfaceDeclarationSyntax GenerateImplementationVTable(ComInterfaceAndMethodsContext interfaceMethods, CancellationToken _)
+ private static void WriteInterfaceInformation(IndentedTextWriter writer, ComInterfaceInfo interfaceInfo)
{
- if (!interfaceMethods.Interface.Options.HasFlag(ComInterfaceOptions.ManagedObjectWrapper))
- {
- return ImplementationInterfaceTemplate;
- }
+ writer.WriteLine("file unsafe sealed class InterfaceInformation : global::System.Runtime.InteropServices.Marshalling.IIUnknownInterfaceType");
+ writer.WriteLine('{');
+ writer.Indent++;
+ writer.WriteLine($"public static global::System.Guid Iid {{ get; }} = new([{string.Join(", ", interfaceInfo.InterfaceId.ToByteArray())}]);");
+ writer.WriteLine($"public static void** ManagedVirtualMethodTable => {(interfaceInfo.Options.HasFlag(ComInterfaceOptions.ManagedObjectWrapper) ? "(void**)global::System.Runtime.CompilerServices.Unsafe.AsPointer(in InterfaceImplementation.Vtable)" : "null")};");
+ writer.Indent--;
+ writer.WriteLine('}');
+ }
- BlockSyntax fillBaseInterfaceSlots;
+ private static void WriteInterfaceImplementation(IndentedTextWriter writer, ComInterfaceAndMethodsContext data)
+ {
+ writer.WriteLine("[global::System.Runtime.InteropServices.DynamicInterfaceCastableImplementationAttribute]");
+ writer.WriteLine($"file unsafe interface InterfaceImplementation : {data.Interface.Info.Type.FullTypeName}");
+ writer.WriteLine('{');
+ writer.Indent++;
- if (interfaceMethods.Interface.Base is null)
+ if (data.Interface.Options.HasFlag(ComInterfaceOptions.ManagedObjectWrapper))
{
- // If we don't have a base interface, we need to manually fill in the base iUnknown slots.
- fillBaseInterfaceSlots = Block()
- .AddStatements(
- // ComWrappers.GetIUnknownImpl(
- // out *(nint*)&((InterfaceImplementationVtable*)Unsafe.AsPointer(ref Vtable))->QueryInterface_0,
- // out *(nint*)&((InterfaceImplementationVtable*)Unsafe.AsPointer(ref Vtable))->AddRef_1,
- // out *(nint*)&((InterfaceImplementationVtable*)Unsafe.AsPointer(ref Vtable))->Release_2);
- MethodInvocationStatement(
- TypeSyntaxes.System_Runtime_InteropServices_ComWrappers,
- IdentifierName("GetIUnknownImpl"),
- OutArgument(
- PrefixUnaryExpression(
- SyntaxKind.PointerIndirectionExpression,
- CastExpression(
- PointerType(ParseTypeName("nint")),
- PrefixUnaryExpression(
- SyntaxKind.AddressOfExpression,
- MemberAccessExpression(
- SyntaxKind.PointerMemberAccessExpression,
- ParenthesizedExpression(
- CastExpression(
- PointerType(ParseTypeName("InterfaceImplementationVtable")),
- InvocationExpression(
- MemberAccessExpression(
- SyntaxKind.SimpleMemberAccessExpression,
- TypeSyntaxes.System_Runtime_CompilerServices_Unsafe,
- IdentifierName("AsPointer")))
- .AddArgumentListArguments(
- Argument(
- RefExpression(IdentifierName("Vtable")))))),
- IdentifierName("QueryInterface_0")))))),
- OutArgument(
- PrefixUnaryExpression(
- SyntaxKind.PointerIndirectionExpression,
- CastExpression(
- PointerType(ParseTypeName("nint")),
- PrefixUnaryExpression(
- SyntaxKind.AddressOfExpression,
- MemberAccessExpression(
- SyntaxKind.PointerMemberAccessExpression,
- ParenthesizedExpression(
- CastExpression(
- PointerType(ParseTypeName("InterfaceImplementationVtable")),
- InvocationExpression(
- MemberAccessExpression(
- SyntaxKind.SimpleMemberAccessExpression,
- TypeSyntaxes.System_Runtime_CompilerServices_Unsafe,
- IdentifierName("AsPointer")))
- .AddArgumentListArguments(
- Argument(
- RefExpression(IdentifierName("Vtable")))))),
- IdentifierName("AddRef_1")))))),
- OutArgument(
- PrefixUnaryExpression(
- SyntaxKind.PointerIndirectionExpression,
- CastExpression(
- PointerType(ParseTypeName("nint")),
- PrefixUnaryExpression(
- SyntaxKind.AddressOfExpression,
- MemberAccessExpression(
- SyntaxKind.PointerMemberAccessExpression,
- ParenthesizedExpression(
- CastExpression(
- PointerType(ParseTypeName("InterfaceImplementationVtable")),
- InvocationExpression(
- MemberAccessExpression(
- SyntaxKind.SimpleMemberAccessExpression,
- TypeSyntaxes.System_Runtime_CompilerServices_Unsafe,
- IdentifierName("AsPointer")))
- .AddArgumentListArguments(
- Argument(
- RefExpression(IdentifierName("Vtable")))))),
- IdentifierName("Release_2"))))))));
+ writer.WriteLine("[global::System.Runtime.CompilerServices.FixedAddressValueTypeAttribute]");
+ writer.WriteLine("public static readonly InterfaceImplementationVtable Vtable;");
+ writer.InnerWriter.WriteLine();
+ writer.WriteLine("static InterfaceImplementation()");
+ writer.WriteLine('{');
+ writer.Indent++;
+
+ if (data.Interface.Base is { } baseInterface)
+ {
+ writer.WriteLine("global::System.Runtime.InteropServices.NativeMemory.Copy(");
+ writer.Indent++;
+ writer.WriteLine($"global::System.Runtime.InteropServices.Marshalling.StrategyBasedComWrappers.DefaultIUnknownInterfaceDetailsStrategy.GetIUnknownDerivedDetails(typeof({baseInterface.Info.Type.FullTypeName}).TypeHandle).ManagedVirtualMethodTable,");
+ writer.WriteLine("global::System.Runtime.CompilerServices.Unsafe.AsPointer(ref Vtable),");
+ writer.WriteLine($"(nuint)(sizeof(void*) * {data.BaseVTableSize}));");
+ writer.Indent--;
+ }
+ else
+ {
+ // If we don't have a base interface, we need to manually fill in the base IUnknown slots.
+ writer.WriteLine("global::System.Runtime.InteropServices.ComWrappers.GetIUnknownImpl(");
+ writer.Indent++;
+ writer.WriteLine("out *(nint*)&((InterfaceImplementationVtable*)global::System.Runtime.CompilerServices.Unsafe.AsPointer(ref Vtable))->QueryInterface_0,");
+ writer.WriteLine("out *(nint*)&((InterfaceImplementationVtable*)global::System.Runtime.CompilerServices.Unsafe.AsPointer(ref Vtable))->AddRef_1,");
+ writer.WriteLine("out *(nint*)&((InterfaceImplementationVtable*)global::System.Runtime.CompilerServices.Unsafe.AsPointer(ref Vtable))->Release_2);");
+ writer.Indent--;
+ }
+
+ writer.InnerWriter.WriteLine();
+
+ foreach (ComMethodContext declaredMethodContext in data.DeclaredMethods
+ .Where(context => context.UnmanagedToManagedStub.Diagnostics.All(diag => diag.Descriptor.DefaultSeverity != DiagnosticSeverity.Error)))
+ {
+ writer.WriteLine($"Vtable.{declaredMethodContext.MethodInfo.MethodName}_{declaredMethodContext.GenerationContext.VtableIndexData.Index} = &ABI_{((SourceAvailableIncrementalMethodStubGenerationContext)declaredMethodContext.GenerationContext).StubMethodSyntaxTemplate.Identifier};");
+ }
+
+ writer.Indent--;
+ writer.WriteLine('}');
}
- else
+
+ foreach (ComMethodContext declaredMethod in data.DeclaredMethods)
{
- // NativeMemory.Copy(StrategyBasedComWrappers.DefaultIUnknownInterfaceDetailsStrategy.GetIUnknownDerivedDetails(typeof().TypeHandle).ManagedVirtualMethodTable, vtable, (nuint)(sizeof(void*) * ));
- fillBaseInterfaceSlots = Block(
- MethodInvocationStatement(
- TypeSyntaxes.System_Runtime_InteropServices_NativeMemory,
- IdentifierName("Copy"),
- Argument(
- MethodInvocation(
- TypeSyntaxes.StrategyBasedComWrappers
- .Dot(IdentifierName("DefaultIUnknownInterfaceDetailsStrategy")),
- IdentifierName("GetIUnknownDerivedDetails"),
- Argument(
- TypeOfExpression(ParseTypeName(interfaceMethods.Interface.Base.Info.Type.FullTypeName))
- .Dot(IdentifierName("TypeHandle"))))
- .Dot(IdentifierName("ManagedVirtualMethodTable"))),
- Argument(
- InvocationExpression(
- MemberAccessExpression(
- SyntaxKind.SimpleMemberAccessExpression,
- TypeSyntaxes.System_Runtime_CompilerServices_Unsafe,
- IdentifierName("AsPointer")))
- .AddArgumentListArguments(
- Argument(
- RefExpression(IdentifierName("Vtable"))))),
- Argument(CastExpression(IdentifierName("nuint"),
- ParenthesizedExpression(
- BinaryExpression(SyntaxKind.MultiplyExpression,
- SizeOfExpression(PointerType(PredefinedType(Token(SyntaxKind.VoidKeyword)))),
- LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(interfaceMethods.BaseVTableSize))))))));
+ if (declaredMethod.ManagedToUnmanagedStub is GeneratedStubCodeContext managedToUnmanagedContext)
+ {
+ writer.InnerWriter.WriteLine();
+ writer.WriteMultilineNode(managedToUnmanagedContext.Stub.Node.NormalizeWhitespace());
+ }
+
+ if (declaredMethod.UnmanagedToManagedStub is GeneratedStubCodeContext unmanagedToManagedContext &&
+ unmanagedToManagedContext.Diagnostics.All(static d => d.Descriptor.DefaultSeverity != DiagnosticSeverity.Error))
+ {
+ writer.InnerWriter.WriteLine();
+ writer.WriteMultilineNode(unmanagedToManagedContext.Stub.Node.NormalizeWhitespace());
+ }
}
- var validDeclaredMethods = interfaceMethods.DeclaredMethods
- .Where(context => context.UnmanagedToManagedStub.Diagnostics.All(diag => diag.Descriptor.DefaultSeverity != DiagnosticSeverity.Error));
+ foreach (ComMethodContext inheritedStub in data.InheritedMethods)
+ {
+ if (inheritedStub is not { IsExternallyDefined: false, ManagedToUnmanagedStub: GeneratedStubCodeContext shadowImplementationContextContext })
+ {
+ continue;
+ }
+
+ MethodDeclarationSyntax preparedNode = shadowImplementationContextContext.Stub.Node
+ .WithExplicitInterfaceSpecifier(
+ ExplicitInterfaceSpecifier(ParseName(data.Interface.Info.Type.FullTypeName)))
+ .NormalizeWhitespace();
- System.Collections.Generic.List statements = new();
+ writer.InnerWriter.WriteLine();
+ writer.WriteMultilineNode(preparedNode);
+ }
- foreach (var declaredMethodContext in validDeclaredMethods)
+ foreach (ComMethodContext inheritedStub in data.InheritedMethods)
{
- statements.Add(
- ExpressionStatement(
- AssignmentExpression(
- SyntaxKind.SimpleAssignmentExpression,
- MemberAccessExpression(
- SyntaxKind.SimpleMemberAccessExpression,
- IdentifierName("Vtable"),
- IdentifierName($"{declaredMethodContext.MethodInfo.MethodName}_{declaredMethodContext.GenerationContext.VtableIndexData.Index}")),
- PrefixUnaryExpression(
- SyntaxKind.AddressOfExpression,
- IdentifierName($"ABI_{((SourceAvailableIncrementalMethodStubGenerationContext)declaredMethodContext.GenerationContext).StubMethodSyntaxTemplate.Identifier}")))));
+ if (inheritedStub.IsExternallyDefined)
+ {
+ continue;
+ }
+
+ writer.InnerWriter.WriteLine();
+ writer.Write($"{inheritedStub.GenerationContext.SignatureContext.StubReturnType} {inheritedStub.OriginalDeclaringInterface.Info.Type.FullTypeName}.{inheritedStub.MethodInfo.MethodName}");
+ writer.Write($"({string.Join(", ", inheritedStub.GenerationContext.SignatureContext.StubParameters.Select(p => p.NormalizeWhitespace().ToString()))})");
+ writer.WriteLine(" => throw new global::System.Diagnostics.UnreachableException();");
}
- return ImplementationInterfaceTemplate
- .AddMembers(
- FieldDeclaration(
- VariableDeclaration(ParseTypeName("InterfaceImplementationVtable"))
- .AddVariables(VariableDeclarator("Vtable")))
- .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.StaticKeyword), Token(SyntaxKind.ReadOnlyKeyword)))
- .AddAttributeLists(
- AttributeList(
- SingletonSeparatedList(
- Attribute(NameSyntaxes.System_Runtime_CompilerServices_FixedAddressValueTypeAttribute)))),
- ConstructorDeclaration("InterfaceImplementation")
- .AddModifiers(Token(SyntaxKind.StaticKeyword))
- .WithBody(
- Block(
- fillBaseInterfaceSlots,
- Block(statements))));
+ writer.Indent--;
+ writer.WriteLine('}');
}
- private static readonly ClassDeclarationSyntax InterfaceInformationTypeTemplate =
- ClassDeclaration("InterfaceInformation")
- .AddModifiers(Token(SyntaxKind.FileKeyword), Token(SyntaxKind.UnsafeKeyword))
- .AddBaseListTypes(SimpleBaseType(TypeSyntaxes.IIUnknownInterfaceType));
-
- private static ClassDeclarationSyntax GenerateInterfaceInformation(ComInterfaceInfo context, CancellationToken _)
+ private static void WriteIUnknownDerivedOriginalInterfacePart(IndentedTextWriter writer, ComInterfaceAndMethodsContext data)
{
- ClassDeclarationSyntax interfaceInformationType = InterfaceInformationTypeTemplate
- .AddMembers(
- // public static System.Guid Iid { get; } = new();
- PropertyDeclaration(TypeSyntaxes.System_Guid, "Iid")
- .AddModifiers(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.StaticKeyword))
- .AddAccessorListAccessors(
- AccessorDeclaration(SyntaxKind.GetAccessorDeclaration).WithSemicolonToken(Token(SyntaxKind.SemicolonToken)))
- .WithInitializer(
- EqualsValueClause(
- ImplicitObjectCreationExpression()
- .AddArgumentListArguments(
- Argument(ComInterfaceGeneratorHelpers.CreateEmbeddedDataBlobCreationStatement(context.InterfaceId.ToByteArray())))))
- .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)));
-
- if (context.Options.HasFlag(ComInterfaceOptions.ManagedObjectWrapper))
+ data.Interface.Info.TypeDefinitionContext.WriteToWithUnsafeModifier(writer, (data.Interface.Info.ContainingSyntax, data.ShadowingMethods), static (writer, data) =>
{
- return interfaceInformationType.AddMembers(
- // public static void** VirtualMethodTableManagedImplementation => (void**)System.Runtime.CompilerServices.Unsafe.AsPointer(in InterfaceImplementation.Vtable);
- PropertyDeclaration(TypeSyntaxes.VoidStarStar, "ManagedVirtualMethodTable")
- .AddModifiers(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.StaticKeyword))
- .WithExpressionBody(
- ArrowExpressionClause(
- CastExpression(
- PointerType(PointerType(ParseTypeName("void"))),
- InvocationExpression(
- MemberAccessExpression(
- SyntaxKind.SimpleMemberAccessExpression,
- TypeSyntaxes.System_Runtime_CompilerServices_Unsafe,
- IdentifierName("AsPointer")))
- .AddArgumentListArguments(
- InArgument(
- MemberAccessExpression(
- SyntaxKind.SimpleMemberAccessExpression,
- IdentifierName("InterfaceImplementation"),
- IdentifierName("Vtable")))))))
- .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)));
- }
+ (ContainingSyntax syntax, IEnumerable? shadowingMethods) = data;
+
+ writer.WriteLine("[global::System.Runtime.InteropServices.Marshalling.IUnknownDerivedAttribute]");
+ writer.WriteLine($"{string.Join(" ", syntax.Modifiers.AddToModifiers(SyntaxKind.UnsafeKeyword))} {syntax.TypeKind.GetDeclarationKeyword()} {syntax.Identifier}{syntax.TypeParameters}");
+ writer.WriteLine('{');
+ writer.Indent++;
+
+ foreach (ComMethodContext shadow in shadowingMethods)
+ {
+ IncrementalMethodStubGenerationContext generationContext = shadow.GenerationContext;
+ SignatureContext sigContext = generationContext.SignatureContext;
+
+ foreach (AttributeListSyntax additionalAttr in sigContext.AdditionalAttributes)
+ {
+ writer.WriteLine(additionalAttr.NormalizeWhitespace().ToString());
+ }
+
+ foreach (AttributeInfo attrInfo in shadow.MethodInfo.Attributes)
+ {
+ writer.WriteLine($"[{attrInfo.Type}({string.Join(", ", attrInfo.Arguments)})]");
+ }
+
+ writer.Write($"new {sigContext.StubReturnType} {shadow.MethodInfo.MethodName}");
+ writer.Write($"({string.Join(", ", sigContext.StubParameters.Select(p => p.NormalizeWhitespace().ToString()))})");
+ writer.Write($" => (({shadow.OriginalDeclaringInterface.Info.Type.FullTypeName})this).{shadow.MethodInfo.MethodName}");
+ writer.WriteLine($"({string.Join(", ", sigContext.ManagedParameters.Select(mp => $"{(mp.IsByRef ? $"{MarshallerHelpers.GetManagedArgumentRefKindKeyword(mp)} " : "")}{mp.InstanceIdentifier}"))});");
+ }
- return interfaceInformationType.AddMembers(
- PropertyDeclaration(TypeSyntaxes.VoidStarStar, "ManagedVirtualMethodTable")
- .AddModifiers(Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.StaticKeyword))
- .WithExpressionBody(ArrowExpressionClause(LiteralExpression(SyntaxKind.NullLiteralExpression)))
- .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)));
+ writer.Indent--;
+ writer.WriteLine('}');
+ });
}
}
}
diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComMethodContext.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComMethodContext.cs
index d2327e0cafdb34..a9d55aab0649e1 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComMethodContext.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComMethodContext.cs
@@ -6,10 +6,6 @@
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
-using Microsoft.CodeAnalysis;
-using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
-using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
namespace Microsoft.Interop
{
@@ -113,57 +109,6 @@ private GeneratedMethodContextBase CreateUnmanagedToManagedStub()
return new GeneratedStubCodeContext(sourceAvailableContext.OriginalDefiningType, sourceAvailableContext.ContainingSyntaxContext, new(methodStub), new(diagnostics));
}
- private MethodDeclarationSyntax? _unreachableExceptionStub;
-
- public MethodDeclarationSyntax UnreachableExceptionStub => _unreachableExceptionStub ??= CreateUnreachableExceptionStub();
-
- private MethodDeclarationSyntax CreateUnreachableExceptionStub()
- {
- // DeclarationCopiedFromBaseDeclaration() => throw new UnreachableException();
- return MethodInfo.Syntax
- .WithReturnType(GenerationContext.SignatureContext.StubReturnType)
- .WithModifiers(TokenList())
- .WithAttributeLists(List())
- .WithExplicitInterfaceSpecifier(ExplicitInterfaceSpecifier(
- ParseName(OriginalDeclaringInterface.Info.Type.FullTypeName)))
- .WithParameterList(ParameterList(SeparatedList(GenerationContext.SignatureContext.StubParameters)))
- .WithExpressionBody(ArrowExpressionClause(
- ThrowExpression(
- ObjectCreationExpression(
- TypeSyntaxes.UnreachableException)
- .WithArgumentList(ArgumentList()))));
- }
-
- private MethodDeclarationSyntax? _shadow;
-
- public MethodDeclarationSyntax Shadow => _shadow ??= GenerateShadow();
-
- private MethodDeclarationSyntax GenerateShadow()
- {
- // DeclarationCopiedFromBaseDeclaration()
- // => (()this).();
- return MethodDeclaration(GenerationContext.SignatureContext.StubReturnType, MethodInfo.MethodName)
- .WithModifiers(TokenList(Token(SyntaxKind.NewKeyword)))
- .WithAttributeLists(List(GenerationContext.SignatureContext.AdditionalAttributes.Concat(MethodInfo.Attributes.Select(a => a.GenerateAttributeList()))))
- .WithParameterList(ParameterList(SeparatedList(GenerationContext.SignatureContext.StubParameters)))
- .WithExpressionBody(
- ArrowExpressionClause(
- InvocationExpression(
- MemberAccessExpression(
- SyntaxKind.SimpleMemberAccessExpression,
- ParenthesizedExpression(
- CastExpression(OriginalDeclaringInterface.Info.Type.Syntax, IdentifierName("this"))),
- IdentifierName(MethodInfo.MethodName)),
- ArgumentList(
- SeparatedList(GenerationContext.SignatureContext.ManagedParameters.Select(GenerateArgument))))))
- .WithSemicolonToken(Token(SyntaxKind.SemicolonToken));
-
- static ArgumentSyntax GenerateArgument(TypePositionInfo info)
- => info.IsByRef
- ? Argument(IdentifierName(info.InstanceIdentifier)).WithRefKindKeyword(MarshallerHelpers.GetManagedArgumentRefKindKeyword(info))
- : Argument(IdentifierName(info.InstanceIdentifier));
- }
-
///
/// Returns a flat list of and its owning interface that represents all declared methods and inherited methods.
/// Guarantees the output will be sorted by order of interface input order, then by vtable order.
diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ItemAndSyntaxes.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ItemAndSyntaxes.cs
deleted file mode 100644
index c3cc57e84bd510..00000000000000
--- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ItemAndSyntaxes.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System;
-using System.Collections.Generic;
-using System.Collections.Immutable;
-using System.Text;
-using Microsoft.CodeAnalysis;
-
-namespace Microsoft.Interop
-{
- internal sealed class ItemAndSyntaxes : IEquatable>
- {
- private T _item;
- private ImmutableArray _syntaxNodes;
- public SyntaxNode this[int index] => _syntaxNodes[index];
- public ItemAndSyntaxes(T item, params ImmutableArray nodes)
- {
- _item = item;
- _syntaxNodes = nodes;
- }
-
- public T Context => _item;
-
- public bool Equals(ItemAndSyntaxes other)
- {
- if (other is null) return false;
- if (!other._item.Equals(_item)) return false;
- if (other._syntaxNodes.Length != _syntaxNodes.Length) return false;
- for (int i = 0; i < _syntaxNodes.Length; i++)
- {
- var item = _syntaxNodes[i];
- var otherItem = other._syntaxNodes[i];
-
- if (!SyntaxEquivalentComparer.Instance.Equals(item, otherItem))
- {
- return false;
- }
- }
- return true;
- }
-
- public override bool Equals(object obj)
- {
- return Equals(obj as ItemAndSyntaxes);
- }
-
- public override int GetHashCode()
- {
- return _item.GetHashCode();
- }
- }
-}
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ContainingSyntaxContext.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ContainingSyntaxContext.cs
index 832be0b79db305..5c8b8a6635be16 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ContainingSyntaxContext.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ContainingSyntaxContext.cs
@@ -169,17 +169,7 @@ public void WriteToWithUnsafeModifier(IndentedTextWriter writer, TState
{
ContainingSyntax syntax = ContainingSyntax[i];
- string declarationKeyword = syntax.TypeKind switch
- {
- SyntaxKind.ClassDeclaration => "class",
- SyntaxKind.StructDeclaration => "struct",
- SyntaxKind.InterfaceDeclaration => "interface",
- SyntaxKind.RecordDeclaration => "record",
- SyntaxKind.RecordStructDeclaration => "record struct",
- _ => throw new UnreachableException(),
- };
-
- writer.WriteLine($"{string.Join(" ", syntax.Modifiers.AddToModifiers(SyntaxKind.UnsafeKeyword))} {declarationKeyword} {syntax.Identifier}{syntax.TypeParameters}");
+ writer.WriteLine($"{string.Join(" ", syntax.Modifiers.AddToModifiers(SyntaxKind.UnsafeKeyword))} {syntax.TypeKind.GetDeclarationKeyword()} {syntax.Identifier}{syntax.TypeParameters}");
writer.WriteLine('{');
writer.Indent++;
}
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/IndentedTextWriterExtensions.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/IndentedTextWriterExtensions.cs
new file mode 100644
index 00000000000000..4a4af2ef394260
--- /dev/null
+++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/IndentedTextWriterExtensions.cs
@@ -0,0 +1,43 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.CodeDom.Compiler;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+
+namespace Microsoft.Interop;
+
+public static class IndentedTextWriterExtensions
+{
+ public static void WriteMultilineNode(this IndentedTextWriter writer, SyntaxNode node)
+ {
+ foreach (SyntaxToken token in node.DescendantTokens())
+ {
+ foreach (SyntaxTrivia leadingTrivia in token.LeadingTrivia)
+ {
+ if (leadingTrivia.IsKind(SyntaxKind.EndOfLineTrivia))
+ {
+ writer.WriteLine();
+ continue;
+ }
+
+ writer.Write(leadingTrivia.ToString());
+ }
+
+ writer.Write(token.Text);
+
+ foreach (SyntaxTrivia trailingTrivia in token.TrailingTrivia)
+ {
+ if (trailingTrivia.IsKind(SyntaxKind.EndOfLineTrivia))
+ {
+ writer.WriteLine();
+ continue;
+ }
+
+ writer.Write(trailingTrivia.ToString());
+ }
+ }
+
+ writer.WriteLine();
+ }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/SyntaxKindExtensions.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/SyntaxKindExtensions.cs
new file mode 100644
index 00000000000000..da80fd6089f7c8
--- /dev/null
+++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/SyntaxKindExtensions.cs
@@ -0,0 +1,19 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Microsoft.CodeAnalysis.CSharp;
+
+namespace Microsoft.Interop;
+
+public static class SyntaxKindExtensions
+{
+ public static string GetDeclarationKeyword(this SyntaxKind syntaxKind) => syntaxKind switch
+ {
+ SyntaxKind.ClassDeclaration => "class",
+ SyntaxKind.StructDeclaration => "struct",
+ SyntaxKind.InterfaceDeclaration => "interface",
+ SyntaxKind.RecordDeclaration => "record",
+ SyntaxKind.RecordStructDeclaration => "record struct",
+ _ => throw new UnreachableException(),
+ };
+}
diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeNames.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeNames.cs
index f906e506bdec31..56be4847f6feee 100644
--- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeNames.cs
+++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeNames.cs
@@ -37,11 +37,6 @@ public static class NameSyntaxes
private static NameSyntax? _WasmImportLinkageAttribute;
public static NameSyntax WasmImportLinkageAttribute => _WasmImportLinkageAttribute ??= ParseName(TypeNames.GlobalAlias + TypeNames.WasmImportLinkageAttribute);
- private static NameSyntax? _System_Runtime_CompilerServices_FixedAddressValueTypeAttribute;
- public static NameSyntax System_Runtime_CompilerServices_FixedAddressValueTypeAttribute => _System_Runtime_CompilerServices_FixedAddressValueTypeAttribute ??= ParseName(TypeNames.GlobalAlias + TypeNames.System_Runtime_CompilerServices_FixedAddressValueTypeAttribute);
-
- private static NameSyntax? _System_Runtime_InteropServices_StructLayoutAttribute;
- public static NameSyntax System_Runtime_InteropServices_StructLayoutAttribute => _System_Runtime_InteropServices_StructLayoutAttribute ??= ParseName(TypeNames.GlobalAlias + TypeNames.System_Runtime_InteropServices_StructLayoutAttribute);
private static NameSyntax? _System_Diagnostics_StackTraceHiddenAttribute;
public static NameSyntax System_Diagnostics_StackTraceHiddenAttribute => _System_Diagnostics_StackTraceHiddenAttribute ??= ParseName(TypeNames.GlobalAlias + TypeNames.System_Diagnostics_StackTraceHiddenAttribute);
}
@@ -50,35 +45,18 @@ public static class TypeSyntaxes
{
public static TypeSyntax VoidStar { get; } = PointerType(PredefinedType(Token(SyntaxKind.VoidKeyword)));
- public static TypeSyntax VoidStarStar { get; } = PointerType(PointerType(PredefinedType(Token(SyntaxKind.VoidKeyword))));
-
- private static TypeSyntax? _System_Runtime_InteropServices_NativeMemory;
- public static TypeSyntax System_Runtime_InteropServices_NativeMemory => _System_Runtime_InteropServices_NativeMemory ??= ParseTypeName(TypeNames.GlobalAlias + TypeNames.System_Runtime_InteropServices_NativeMemory);
-
- private static TypeSyntax? _StrategyBasedComWrappers;
- public static TypeSyntax StrategyBasedComWrappers => _StrategyBasedComWrappers ??= ParseTypeName(TypeNames.GlobalAlias + TypeNames.StrategyBasedComWrappers);
-
private static TypeSyntax? _IUnmanagedVirtualMethodTableProvider;
public static TypeSyntax IUnmanagedVirtualMethodTableProvider => _IUnmanagedVirtualMethodTableProvider ??= ParseTypeName(TypeNames.GlobalAlias + TypeNames.IUnmanagedVirtualMethodTableProvider);
- private static TypeSyntax? _IIUnknownInterfaceType;
- public static TypeSyntax IIUnknownInterfaceType => _IIUnknownInterfaceType ??= ParseTypeName(TypeNames.GlobalAlias + TypeNames.IIUnknownInterfaceType);
-
private static TypeSyntax? _UnmanagedObjectUnwrapper;
public static TypeSyntax UnmanagedObjectUnwrapper => _UnmanagedObjectUnwrapper ??= ParseTypeName(TypeNames.GlobalAlias + TypeNames.UnmanagedObjectUnwrapper);
private static TypeSyntax? _UnreachableException;
public static TypeSyntax UnreachableException => _UnreachableException ??= ParseTypeName(TypeNames.GlobalAlias + TypeNames.UnreachableException);
- private static TypeSyntax? _System_Runtime_InteropServices_ComWrappers;
- public static TypeSyntax System_Runtime_InteropServices_ComWrappers => _System_Runtime_InteropServices_ComWrappers ??= ParseTypeName(TypeNames.GlobalAlias + TypeNames.System_Runtime_InteropServices_ComWrappers);
-
private static TypeSyntax? _System_IntPtr;
public static TypeSyntax System_IntPtr => _System_IntPtr ??= ParseTypeName(TypeNames.GlobalAlias + TypeNames.System_IntPtr);
- private static TypeSyntax? _System_Guid;
- public static TypeSyntax System_Guid => _System_Guid ??= ParseTypeName(TypeNames.GlobalAlias + TypeNames.System_Guid);
-
private static TypeSyntax? _DllImportSearchPath;
public static TypeSyntax DllImportSearchPath => _DllImportSearchPath ??= ParseTypeName(TypeNames.GlobalAlias + TypeNames.DllImportSearchPath);
@@ -106,9 +84,6 @@ public static class TypeSyntaxes
private static TypeSyntax? _System_Runtime_CompilerServices_Unsafe;
public static TypeSyntax System_Runtime_CompilerServices_Unsafe => _System_Runtime_CompilerServices_Unsafe ??= ParseTypeName(TypeNames.GlobalAlias + TypeNames.System_Runtime_CompilerServices_Unsafe);
- private static TypeSyntax? _System_Runtime_InteropServices_LayoutKind;
- public static TypeSyntax System_Runtime_InteropServices_LayoutKind => _System_Runtime_InteropServices_LayoutKind ??= ParseTypeName(TypeNames.GlobalAlias + TypeNames.System_Runtime_InteropServices_LayoutKind);
-
private static TypeSyntax? _CallConvCdecl;
private static TypeSyntax? _CallConvFastcall;
private static TypeSyntax? _CallConvMemberFunction;