| __`SYSLIB1088`__ | _`SYSLIB1070`-`SYSLIB1089` reserved for System.Runtime.InteropServices.JavaScript.JSImportGenerator._ |
| __`SYSLIB1089`__ | _`SYSLIB1070`-`SYSLIB1089` reserved for System.Runtime.InteropServices.JavaScript.JSImportGenerator._ |
| __`SYSLIB1090`__ | Invalid 'GeneratedComInterfaceAttribute' usage |
+| __`SYSLIB1091`__ | Method is declared in different partial declaration than the 'GeneratedComInterface' attribute. |
+| __`SYSLIB1092`__ | _`SYSLIB1092`-`SYSLIB1099` reserved for Microsoft.Interop.ComInteropGenerator._ |
+| __`SYSLIB1093`__ | _`SYSLIB1092`-`SYSLIB1099` reserved for Microsoft.Interop.ComInteropGenerator._ |
+| __`SYSLIB1094`__ | _`SYSLIB1092`-`SYSLIB1099` reserved for Microsoft.Interop.ComInteropGenerator._ |
+| __`SYSLIB1095`__ | _`SYSLIB1092`-`SYSLIB1099` reserved for Microsoft.Interop.ComInteropGenerator._ |
+| __`SYSLIB1096`__ | _`SYSLIB1092`-`SYSLIB1099` reserved for Microsoft.Interop.ComInteropGenerator._ |
+| __`SYSLIB1097`__ | _`SYSLIB1092`-`SYSLIB1099` reserved for Microsoft.Interop.ComInteropGenerator._ |
+| __`SYSLIB1098`__ | _`SYSLIB1092`-`SYSLIB1099` reserved for Microsoft.Interop.ComInteropGenerator._ |
+| __`SYSLIB1099`__ | _`SYSLIB1092`-`SYSLIB1099` reserved for Microsoft.Interop.ComInteropGenerator._ |
### Diagnostic Suppressions (`SYSLIBSUPPRESS****`)
--- /dev/null
+// 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.Diagnostics;
+using System.Linq;
+using System.Threading;
+using System.Xml.Linq;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
+
+namespace Microsoft.Interop
+{
+ [Generator]
+ public sealed class ComInterfaceGenerator : IIncrementalGenerator
+ {
+ private sealed record ComInterfaceContext(int MethodStartIndex, Guid InterfaceId);
+
+ public static class StepNames
+ {
+ public const string CalculateStubInformation = nameof(CalculateStubInformation);
+ public const string GenerateManagedToNativeStub = nameof(GenerateManagedToNativeStub);
+ public const string GenerateNativeToManagedStub = nameof(GenerateNativeToManagedStub);
+ }
+
+ private static readonly ContainingSyntax NativeTypeContainingSyntax = new(
+ TokenList(Token(SyntaxKind.InternalKeyword), Token(SyntaxKind.PartialKeyword)),
+ SyntaxKind.InterfaceDeclaration,
+ Identifier("Native"),
+ null);
+
+ public void Initialize(IncrementalGeneratorInitializationContext context)
+ {
+ // Get all methods with the [GeneratedComInterface] attribute.
+ var attributedInterfaces = context.SyntaxProvider
+ .ForAttributeWithMetadataName(
+ TypeNames.GeneratedComInterfaceAttribute,
+ static (node, ct) => node is InterfaceDeclarationSyntax,
+ static (context, ct) => context.TargetSymbol is INamedTypeSymbol interfaceSymbol
+ ? new { Syntax = (InterfaceDeclarationSyntax)context.TargetNode, Symbol = interfaceSymbol }
+ : null)
+ .Where(
+ static modelData => modelData is not null);
+
+ var interfacesWithDiagnostics = attributedInterfaces.Select(static (data, ct) =>
+ {
+ Diagnostic? diagnostic = GetDiagnosticIfInvalidTypeForGeneration(data.Syntax, data.Symbol);
+ return new { data.Syntax, data.Symbol, Diagnostic = diagnostic };
+ });
+
+ // Split the methods we want to generate and the ones we don't into two separate groups.
+ var interfacesToGenerate = interfacesWithDiagnostics.Where(static data => data.Diagnostic is null);
+ var invalidTypeDiagnostics = interfacesWithDiagnostics.Where(static data => data.Diagnostic is not null);
+
+ var interfaceContexts = interfacesToGenerate.Select((data, ct) =>
+ {
+ // Start at offset 3 as 0-2 are IUnknown.
+ // TODO: Calculate starting offset based on base types.
+ // TODO: Extract IID from source.
+ return new ComInterfaceContext(3, Guid.Empty);
+ });
+
+ context.RegisterSourceOutput(invalidTypeDiagnostics, static (context, invalidType) =>
+ {
+ context.ReportDiagnostic(invalidType.Diagnostic);
+ });
+
+ // Zip the incremental interface context back with the symbols and syntax for the interface
+ // to calculate the methods to generate.
+ // The generator infrastructure preserves ordering of the tables once Select statements are in use,
+ // so we can rely on the order matching here.
+ var methodsWithDiagnostics = interfacesToGenerate
+ .Zip(interfaceContexts)
+ .SelectMany(static (data, ct) =>
+ {
+ var (interfaceData, interfaceContext) = data;
+ ContainingSyntaxContext containingSyntax = new(interfaceData.Syntax);
+ Location interfaceLocation = interfaceData.Syntax.GetLocation();
+ var methods = ImmutableArray.CreateBuilder<(MethodDeclarationSyntax Syntax, IMethodSymbol Symbol, int Index, Diagnostic? Diagnostic)>();
+ int methodVtableOffset = interfaceContext.MethodStartIndex;
+ foreach (var member in interfaceData.Symbol.GetMembers())
+ {
+ if (member.Kind == SymbolKind.Method && !member.IsStatic)
+ {
+ // We only support methods that are defined in the same partial interface definition as the
+ // [GeneratedComInterface] attribute.
+ // This restriction not only makes finding the syntax for a given method cheaper,
+ // but it also enables us to ensure that we can determine vtable method order easily.
+ Location? locationInAttributeSyntax = null;
+ foreach (var location in member.Locations)
+ {
+ if (location.SourceTree == interfaceLocation.SourceTree
+ && interfaceLocation.SourceSpan.Contains(location.SourceSpan))
+ {
+ locationInAttributeSyntax = location;
+ }
+ }
+
+ if (locationInAttributeSyntax is null)
+ {
+ methods.Add((
+ null!,
+ (IMethodSymbol)member,
+ 0,
+ member.CreateDiagnostic(
+ GeneratorDiagnostics.MethodNotDeclaredInAttributedInterface,
+ member.ToDisplayString(),
+ interfaceData.Symbol.ToDisplayString())));
+ }
+ else
+ {
+ var syntax = (MethodDeclarationSyntax)interfaceData.Syntax.FindNode(locationInAttributeSyntax.SourceSpan);
+ var method = (IMethodSymbol)member;
+ Diagnostic? diagnostic = GetDiagnosticIfInvalidMethodForGeneration(syntax, method);
+ methods.Add((syntax, method, diagnostic is not null ? methodVtableOffset++ : 0, diagnostic));
+ }
+ }
+ }
+ return methods.ToImmutable();
+ });
+
+ // Split the methods we want to generate and the ones we don't into two separate groups.
+ var methodsToGenerate = methodsWithDiagnostics.Where(static data => data.Diagnostic is null);
+ var invalidMethodDiagnostics = methodsWithDiagnostics.Where(static data => data.Diagnostic is not null);
+
+ context.RegisterSourceOutput(invalidMethodDiagnostics, static (context, invalidMethod) =>
+ {
+ context.ReportDiagnostic(invalidMethod.Diagnostic);
+ });
+
+ // Calculate all of information to generate both managed-to-unmanaged and unmanaged-to-managed stubs
+ // for each method.
+ IncrementalValuesProvider<IncrementalMethodStubGenerationContext> generateStubInformation = methodsToGenerate
+ .Combine(context.CreateStubEnvironmentProvider())
+ .Select(static (data, ct) => new
+ {
+ data.Left.Syntax,
+ data.Left.Symbol,
+ data.Left.Index,
+ Environment = data.Right
+ })
+ .Select(
+ static (data, ct) => CalculateStubInformation(data.Syntax, data.Symbol, data.Index, data.Environment, ct)
+ )
+ .WithTrackingName(StepNames.CalculateStubInformation);
+
+ // Generate the code for the managed-to-unmanaged stubs and the diagnostics from code-generation.
+ IncrementalValuesProvider<(MemberDeclarationSyntax, ImmutableArray<Diagnostic>)> generateManagedToNativeStub = generateStubInformation
+ .Where(data => data.VtableIndexData.Direction is MarshalDirection.ManagedToUnmanaged or MarshalDirection.Bidirectional)
+ .Select(
+ static (data, ct) => VtableIndexStubGenerator.GenerateManagedToNativeStub(data)
+ )
+ .WithComparer(Comparers.GeneratedSyntax)
+ .WithTrackingName(StepNames.GenerateManagedToNativeStub);
+
+ context.RegisterDiagnostics(generateManagedToNativeStub.SelectMany((stubInfo, ct) => stubInfo.Item2));
+
+ context.RegisterConcatenatedSyntaxOutputs(generateManagedToNativeStub.Select((data, ct) => data.Item1), "ManagedToNativeStubs.g.cs");
+
+ // Filter the list of all stubs to only the stubs that requested unmanaged-to-managed stub generation.
+ IncrementalValuesProvider<IncrementalMethodStubGenerationContext> nativeToManagedStubContexts =
+ generateStubInformation
+ .Where(data => data.VtableIndexData.Direction is MarshalDirection.UnmanagedToManaged or MarshalDirection.Bidirectional);
+
+ // Generate the code for the unmanaged-to-managed stubs and the diagnostics from code-generation.
+ IncrementalValuesProvider<(MemberDeclarationSyntax, ImmutableArray<Diagnostic>)> generateNativeToManagedStub = nativeToManagedStubContexts
+ .Select(
+ static (data, ct) => VtableIndexStubGenerator.GenerateNativeToManagedStub(data)
+ )
+ .WithComparer(Comparers.GeneratedSyntax)
+ .WithTrackingName(StepNames.GenerateNativeToManagedStub);
+
+ context.RegisterDiagnostics(generateNativeToManagedStub.SelectMany((stubInfo, ct) => stubInfo.Item2));
+
+ context.RegisterConcatenatedSyntaxOutputs(generateNativeToManagedStub.Select((data, ct) => data.Item1), "NativeToManagedStubs.g.cs");
+
+ // Generate the native interface metadata for each interface that contains a method with the [VirtualMethodIndex] attribute.
+ IncrementalValuesProvider<MemberDeclarationSyntax> generateNativeInterface = generateStubInformation
+ .Select(static (context, ct) => context.ContainingSyntaxContext)
+ .Collect()
+ .SelectMany(static (syntaxContexts, ct) => syntaxContexts.Distinct())
+ .Select(static (context, ct) => GenerateNativeInterfaceMetadata(context));
+
+ context.RegisterConcatenatedSyntaxOutputs(generateNativeInterface, "NativeInterfaces.g.cs");
+
+ // Generate a method named PopulateUnmanagedVirtualMethodTable on the native interface implementation
+ // that fills in a span with the addresses of the unmanaged-to-managed stub functions at their correct
+ // indices.
+ IncrementalValuesProvider<MemberDeclarationSyntax> populateVTable =
+ nativeToManagedStubContexts
+ .Collect()
+ .SelectMany(static (data, ct) => data.GroupBy(stub => stub.ContainingSyntaxContext))
+ .Select(static (vtable, ct) => GeneratePopulateVTableMethod(vtable));
+
+ context.RegisterConcatenatedSyntaxOutputs(populateVTable, "PopulateVTable.g.cs");
+ }
+
+ private static IncrementalMethodStubGenerationContext CalculateStubInformation(MethodDeclarationSyntax syntax, IMethodSymbol symbol, int index, StubEnvironment environment, CancellationToken ct)
+ {
+ ct.ThrowIfCancellationRequested();
+ INamedTypeSymbol? lcidConversionAttrType = environment.Compilation.GetTypeByMetadataName(TypeNames.LCIDConversionAttribute);
+ INamedTypeSymbol? suppressGCTransitionAttrType = environment.Compilation.GetTypeByMetadataName(TypeNames.SuppressGCTransitionAttribute);
+ INamedTypeSymbol? unmanagedCallConvAttrType = environment.Compilation.GetTypeByMetadataName(TypeNames.UnmanagedCallConvAttribute);
+ // Get any attributes of interest on the method
+ AttributeData? lcidConversionAttr = null;
+ AttributeData? suppressGCTransitionAttribute = null;
+ AttributeData? unmanagedCallConvAttribute = null;
+ foreach (AttributeData attr in symbol.GetAttributes())
+ {
+ if (lcidConversionAttrType is not null && SymbolEqualityComparer.Default.Equals(attr.AttributeClass, lcidConversionAttrType))
+ {
+ lcidConversionAttr = attr;
+ }
+ else if (suppressGCTransitionAttrType is not null && SymbolEqualityComparer.Default.Equals(attr.AttributeClass, suppressGCTransitionAttrType))
+ {
+ suppressGCTransitionAttribute = attr;
+ }
+ else if (unmanagedCallConvAttrType is not null && SymbolEqualityComparer.Default.Equals(attr.AttributeClass, unmanagedCallConvAttrType))
+ {
+ unmanagedCallConvAttribute = attr;
+ }
+ }
+
+ AttributeData? generatedComAttribute = null;
+ foreach (var attr in symbol.ContainingType.GetAttributes())
+ {
+ if (generatedComAttribute is not null && attr.AttributeClass?.ToDisplayString() == TypeNames.GeneratedComInterfaceAttribute)
+ {
+ generatedComAttribute = attr;
+ }
+ }
+
+ var generatorDiagnostics = new GeneratorDiagnostics();
+
+ if (lcidConversionAttr is not null)
+ {
+ // Using LCIDConversion with source-generated interop is not supported
+ generatorDiagnostics.ReportConfigurationNotSupported(lcidConversionAttr, nameof(TypeNames.LCIDConversionAttribute));
+ }
+
+ // Create the stub.
+ var signatureContext = SignatureContext.Create(symbol, DefaultMarshallingInfoParser.Create(environment, generatorDiagnostics, symbol, new InteropAttributeCompilationData(), generatedComAttribute), environment, typeof(VtableIndexStubGenerator).Assembly);
+
+ var containingSyntaxContext = new ContainingSyntaxContext(syntax);
+
+ var methodSyntaxTemplate = new ContainingSyntax(syntax.Modifiers.StripTriviaFromTokens(), SyntaxKind.MethodDeclaration, syntax.Identifier, syntax.TypeParameterList);
+
+ ImmutableArray<FunctionPointerUnmanagedCallingConventionSyntax> callConv = VtableIndexStubGenerator.GenerateCallConvSyntaxFromAttributes(suppressGCTransitionAttribute, unmanagedCallConvAttribute);
+
+ var typeKeyOwner = ManagedTypeInfo.CreateTypeInfoForTypeSymbol(symbol.ContainingType);
+
+ var virtualMethodIndexData = new VirtualMethodIndexData(index, ImplicitThisParameter: true, MarshalDirection.Bidirectional, true, ExceptionMarshalling.Com);
+
+ return new IncrementalMethodStubGenerationContext(
+ signatureContext,
+ containingSyntaxContext,
+ methodSyntaxTemplate,
+ new MethodSignatureDiagnosticLocations(syntax),
+ new SequenceEqualImmutableArray<FunctionPointerUnmanagedCallingConventionSyntax>(callConv, SyntaxEquivalentComparer.Instance),
+ virtualMethodIndexData,
+ new ComExceptionMarshalling(),
+ ComInterfaceGeneratorHelpers.CreateGeneratorFactory(environment, MarshalDirection.ManagedToUnmanaged),
+ ComInterfaceGeneratorHelpers.CreateGeneratorFactory(environment, MarshalDirection.UnmanagedToManaged),
+ typeKeyOwner,
+ new SequenceEqualImmutableArray<Diagnostic>(generatorDiagnostics.Diagnostics.ToImmutableArray()));
+ }
+
+ private static Diagnostic? GetDiagnosticIfInvalidTypeForGeneration(InterfaceDeclarationSyntax syntax, INamedTypeSymbol type)
+ {
+ // Verify the method has no generic types or defined implementation
+ // and is not marked static or sealed
+ if (syntax.TypeParameterList is not null)
+ {
+ return Diagnostic.Create(GeneratorDiagnostics.InvalidAttributedMethodSignature, syntax.Identifier.GetLocation(), type.Name);
+ }
+
+ // Verify that the types the method is declared in are marked partial.
+ for (SyntaxNode? parentNode = syntax.Parent; parentNode is TypeDeclarationSyntax typeDecl; parentNode = parentNode.Parent)
+ {
+ if (!typeDecl.Modifiers.Any(SyntaxKind.PartialKeyword))
+ {
+ return Diagnostic.Create(GeneratorDiagnostics.InvalidAttributedMethodContainingTypeMissingModifiers, syntax.Identifier.GetLocation(), type.Name, typeDecl.Identifier);
+ }
+ }
+
+ return null;
+ }
+
+ private static Diagnostic? GetDiagnosticIfInvalidMethodForGeneration(MethodDeclarationSyntax syntax, IMethodSymbol method)
+ {
+ // Verify the method has no generic types or defined implementation
+ // and is not marked static or sealed
+ if (syntax.TypeParameterList is not null
+ || syntax.Body is not null
+ || syntax.Modifiers.Any(SyntaxKind.SealedKeyword))
+ {
+ return Diagnostic.Create(GeneratorDiagnostics.InvalidAttributedMethodSignature, syntax.Identifier.GetLocation(), method.Name);
+ }
+
+ // Verify the method does not have a ref return
+ if (method.ReturnsByRef || method.ReturnsByRefReadonly)
+ {
+ return Diagnostic.Create(GeneratorDiagnostics.ReturnConfigurationNotSupported, syntax.Identifier.GetLocation(), "ref return", method.ToDisplayString());
+ }
+
+ return null;
+ }
+
+ private static MemberDeclarationSyntax GenerateNativeInterfaceMetadata(ContainingSyntaxContext context)
+ {
+ return context.WrapMemberInContainingSyntaxWithUnsafeModifier(
+ InterfaceDeclaration("Native")
+ .WithModifiers(TokenList(Token(SyntaxKind.InternalKeyword), Token(SyntaxKind.PartialKeyword)))
+ .WithBaseList(BaseList(SingletonSeparatedList((BaseTypeSyntax)SimpleBaseType(IdentifierName(context.ContainingSyntax[0].Identifier)))))
+ .AddAttributeLists(AttributeList(SingletonSeparatedList(Attribute(ParseName(TypeNames.System_Runtime_InteropServices_DynamicInterfaceCastableImplementationAttribute))))));
+ }
+
+ private const string VTableParameterName = "vtable";
+ private static readonly MethodDeclarationSyntax ManagedVirtualMethodTableImplementationSyntaxTemplate =
+ MethodDeclaration(PredefinedType(Token(SyntaxKind.VoidKeyword)),
+ "PopulateUnmanagedVirtualMethodTable")
+ .WithModifiers(TokenList(Token(SyntaxKind.InternalKeyword), Token(SyntaxKind.StaticKeyword)))
+ .AddParameterListParameters(
+ Parameter(Identifier(VTableParameterName))
+ .WithType(GenericName(TypeNames.System_Span).AddTypeArgumentListArguments(IdentifierName("nint"))));
+
+ private static MemberDeclarationSyntax GeneratePopulateVTableMethod(IGrouping<ContainingSyntaxContext, IncrementalMethodStubGenerationContext> vtableMethods)
+ {
+ ContainingSyntaxContext containingSyntax = vtableMethods.Key.AddContainingSyntax(NativeTypeContainingSyntax);
+ MethodDeclarationSyntax populateVtableMethod = ManagedVirtualMethodTableImplementationSyntaxTemplate;
+
+ foreach (var method in vtableMethods)
+ {
+ FunctionPointerTypeSyntax functionPointerType = VtableIndexStubGenerator.GenerateUnmanagedFunctionPointerTypeForMethod(method);
+
+ // <vtableParameter>[<index>] = (nint)(<functionPointerType>)&ABI_<methodIdentifier>;
+ populateVtableMethod = populateVtableMethod.AddBodyStatements(
+ ExpressionStatement(
+ AssignmentExpression(SyntaxKind.SimpleAssignmentExpression,
+ ElementAccessExpression(
+ IdentifierName(VTableParameterName))
+ .AddArgumentListArguments(Argument(LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(method.VtableIndexData.Index)))),
+ CastExpression(IdentifierName("nint"),
+ CastExpression(functionPointerType,
+ PrefixUnaryExpression(SyntaxKind.AddressOfExpression,
+ IdentifierName($"ABI_{method.StubMethodSyntaxTemplate.Identifier}")))))));
+ }
+
+ return containingSyntax.WrapMemberInContainingSyntaxWithUnsafeModifier(populateVtableMethod);
+ }
+ }
+}
public const string InvalidLibraryImportAttributeUsage = Prefix + "1050";
public const string TypeNotSupported = Prefix + "1051";
public const string ConfigurationNotSupported = Prefix + "1052";
+ public const string MethodNotDeclaredInAttributedInterface = Prefix + "1091";
}
private const string Category = "ComInterfaceGenerator";
isEnabledByDefault: true,
description: GetResourceString(nameof(SR.ConfigurationNotSupportedDescription)));
+ public static readonly DiagnosticDescriptor MethodNotDeclaredInAttributedInterface =
+ new DiagnosticDescriptor(
+ Ids.MethodNotDeclaredInAttributedInterface,
+ GetResourceString(nameof(SR.MethodNotDeclaredInAttributedInterfaceTitle)),
+ GetResourceString(nameof(SR.MethodNotDeclaredInAttributedInterfaceMessage)),
+ Category,
+ DiagnosticSeverity.Error,
+ isEnabledByDefault: true,
+ description: GetResourceString(nameof(SR.MethodNotDeclaredInAttributedInterfaceDescription)));
+
private readonly List<Diagnostic> _diagnostics = new List<Diagnostic>();
--- /dev/null
+// 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;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using System;
+
+namespace Microsoft.Interop
+{
+ internal sealed record IncrementalMethodStubGenerationContext(
+ SignatureContext SignatureContext,
+ ContainingSyntaxContext ContainingSyntaxContext,
+ ContainingSyntax StubMethodSyntaxTemplate,
+ MethodSignatureDiagnosticLocations DiagnosticLocation,
+ SequenceEqualImmutableArray<FunctionPointerUnmanagedCallingConventionSyntax> CallingConvention,
+ VirtualMethodIndexData VtableIndexData,
+ MarshallingInfo ExceptionMarshallingInfo,
+ MarshallingGeneratorFactoryKey<(TargetFramework TargetFramework, Version TargetFrameworkVersion)> ManagedToUnmanagedGeneratorFactory,
+ MarshallingGeneratorFactoryKey<(TargetFramework TargetFramework, Version TargetFrameworkVersion)> UnmanagedToManagedGeneratorFactory,
+ ManagedTypeInfo TypeKeyOwner,
+ SequenceEqualImmutableArray<Diagnostic> Diagnostics);
+}
--- /dev/null
+// 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 static class IncrementalValuesProviderExtensions
+ {
+ public static IncrementalValuesProvider<(T Left, U Right)> Zip<T, U>(this IncrementalValuesProvider<T> left, IncrementalValuesProvider<U> right)
+ {
+ return left
+ .Collect()
+ .Combine(right.Collect())
+ .SelectMany((data, ct) =>
+ {
+ if (data.Left.Length != data.Right.Length)
+ {
+ throw new InvalidOperationException("The two value providers must provide the same number of values.");
+ }
+ ImmutableArray<(T, U)>.Builder builder = ImmutableArray.CreateBuilder<(T, U)>(data.Left.Length);
+ for (int i = 0; i < data.Left.Length; i++)
+ {
+ builder.Add((data.Left[i], data.Right[i]));
+ }
+ return builder.MoveToImmutable();
+ });
+ }
+ }
+}
<data name="InterfaceTypeNotSupportedMessage" xml:space="preserve">
<value>Using 'GeneratedComInterfaceAttribute' and 'InterfaceTypeAttribute' is not supported with 'ComInterfaceType' value '{0}'.</value>
</data>
+ <data name="MethodNotDeclaredInAttributedInterfaceDescription" xml:space="preserve">
+ <value>All methods must be declared in the same partial definition of a 'GeneratedComInterface'-attributed interface type to ensure reliable calculation for virtual method table offsets.</value>
+ </data>
+ <data name="MethodNotDeclaredInAttributedInterfaceMessage" xml:space="preserve">
+ <value>The method '{0}' is declared on a different partial definition of the interface '{1}' than the definition that has the 'GeneratedComInterface' attribute</value>
+ </data>
+ <data name="MethodNotDeclaredInAttributedInterfaceTitle" xml:space="preserve">
+ <value>Method is declared in different partial declaration than the 'GeneratedComInterface' attribute.</value>
+ </data>
</root>
\ No newline at end of file
<target state="translated">Neplatné použití VirtualMethodIndexAttribute</target>
<note />
</trans-unit>
+ <trans-unit id="MethodNotDeclaredInAttributedInterfaceDescription">
+ <source>All methods must be declared in the same partial definition of a 'GeneratedComInterface'-attributed interface type to ensure reliable calculation for virtual method table offsets.</source>
+ <target state="new">All methods must be declared in the same partial definition of a 'GeneratedComInterface'-attributed interface type to ensure reliable calculation for virtual method table offsets.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MethodNotDeclaredInAttributedInterfaceMessage">
+ <source>The method '{0}' is declared on a different partial definition of the interface '{1}' than the definition that has the 'GeneratedComInterface' attribute</source>
+ <target state="new">The method '{0}' is declared on a different partial definition of the interface '{1}' than the definition that has the 'GeneratedComInterface' attribute</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MethodNotDeclaredInAttributedInterfaceTitle">
+ <source>Method is declared in different partial declaration than the 'GeneratedComInterface' attribute.</source>
+ <target state="new">Method is declared in different partial declaration than the 'GeneratedComInterface' attribute.</target>
+ <note />
+ </trans-unit>
<trans-unit id="TypeNotSupportedDescription">
<source>For types that are not supported by source-generated P/Invokes, the resulting P/Invoke will rely on the underlying runtime to marshal the specified type.</source>
<target state="translated">U typů, které nejsou podporovány zdrojem generovanými voláními P/Invoke, bude výsledné volání P/Invoke záviset na podkladovém modulu runtime, aby určený typ zařadil.</target>
<target state="translated">Ungültige Verwendung von „VirtualMethodIndexAttribute“</target>
<note />
</trans-unit>
+ <trans-unit id="MethodNotDeclaredInAttributedInterfaceDescription">
+ <source>All methods must be declared in the same partial definition of a 'GeneratedComInterface'-attributed interface type to ensure reliable calculation for virtual method table offsets.</source>
+ <target state="new">All methods must be declared in the same partial definition of a 'GeneratedComInterface'-attributed interface type to ensure reliable calculation for virtual method table offsets.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MethodNotDeclaredInAttributedInterfaceMessage">
+ <source>The method '{0}' is declared on a different partial definition of the interface '{1}' than the definition that has the 'GeneratedComInterface' attribute</source>
+ <target state="new">The method '{0}' is declared on a different partial definition of the interface '{1}' than the definition that has the 'GeneratedComInterface' attribute</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MethodNotDeclaredInAttributedInterfaceTitle">
+ <source>Method is declared in different partial declaration than the 'GeneratedComInterface' attribute.</source>
+ <target state="new">Method is declared in different partial declaration than the 'GeneratedComInterface' attribute.</target>
+ <note />
+ </trans-unit>
<trans-unit id="TypeNotSupportedDescription">
<source>For types that are not supported by source-generated P/Invokes, the resulting P/Invoke will rely on the underlying runtime to marshal the specified type.</source>
<target state="translated">Bei Typen, die von dquellgenerierten P/Invokes nicht unterstützt werden, basiert der resultierende P/Invoke auf der zugrunde liegenden Laufzeit, um den angegebenen Typ zu marshallen.</target>
<target state="translated">Uso de ”VirtualMethodIndexAttribute” no válido</target>
<note />
</trans-unit>
+ <trans-unit id="MethodNotDeclaredInAttributedInterfaceDescription">
+ <source>All methods must be declared in the same partial definition of a 'GeneratedComInterface'-attributed interface type to ensure reliable calculation for virtual method table offsets.</source>
+ <target state="new">All methods must be declared in the same partial definition of a 'GeneratedComInterface'-attributed interface type to ensure reliable calculation for virtual method table offsets.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MethodNotDeclaredInAttributedInterfaceMessage">
+ <source>The method '{0}' is declared on a different partial definition of the interface '{1}' than the definition that has the 'GeneratedComInterface' attribute</source>
+ <target state="new">The method '{0}' is declared on a different partial definition of the interface '{1}' than the definition that has the 'GeneratedComInterface' attribute</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MethodNotDeclaredInAttributedInterfaceTitle">
+ <source>Method is declared in different partial declaration than the 'GeneratedComInterface' attribute.</source>
+ <target state="new">Method is declared in different partial declaration than the 'GeneratedComInterface' attribute.</target>
+ <note />
+ </trans-unit>
<trans-unit id="TypeNotSupportedDescription">
<source>For types that are not supported by source-generated P/Invokes, the resulting P/Invoke will rely on the underlying runtime to marshal the specified type.</source>
<target state="translated">Para los tipos que no son compatibles con P/Invokes de un generador de código fuente, el P/Invoke resultante se basará en el entorno de ejecución subyacente para serializar las referencias del tipo especificado.</target>
<target state="translated">Utilisation de « VirtualMethodIndexAttribute » non valide</target>
<note />
</trans-unit>
+ <trans-unit id="MethodNotDeclaredInAttributedInterfaceDescription">
+ <source>All methods must be declared in the same partial definition of a 'GeneratedComInterface'-attributed interface type to ensure reliable calculation for virtual method table offsets.</source>
+ <target state="new">All methods must be declared in the same partial definition of a 'GeneratedComInterface'-attributed interface type to ensure reliable calculation for virtual method table offsets.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MethodNotDeclaredInAttributedInterfaceMessage">
+ <source>The method '{0}' is declared on a different partial definition of the interface '{1}' than the definition that has the 'GeneratedComInterface' attribute</source>
+ <target state="new">The method '{0}' is declared on a different partial definition of the interface '{1}' than the definition that has the 'GeneratedComInterface' attribute</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MethodNotDeclaredInAttributedInterfaceTitle">
+ <source>Method is declared in different partial declaration than the 'GeneratedComInterface' attribute.</source>
+ <target state="new">Method is declared in different partial declaration than the 'GeneratedComInterface' attribute.</target>
+ <note />
+ </trans-unit>
<trans-unit id="TypeNotSupportedDescription">
<source>For types that are not supported by source-generated P/Invokes, the resulting P/Invoke will rely on the underlying runtime to marshal the specified type.</source>
<target state="translated">Pour les types qui ne sont pas pris en charge par les P/Invok générés par la source, le P/Invoke résultant se base sur le runtime sous-jacent pour marshaler le type spécifié.</target>
<target state="translated">Utilizzo di 'VirtualMethodIndexAttribute' non valido</target>
<note />
</trans-unit>
+ <trans-unit id="MethodNotDeclaredInAttributedInterfaceDescription">
+ <source>All methods must be declared in the same partial definition of a 'GeneratedComInterface'-attributed interface type to ensure reliable calculation for virtual method table offsets.</source>
+ <target state="new">All methods must be declared in the same partial definition of a 'GeneratedComInterface'-attributed interface type to ensure reliable calculation for virtual method table offsets.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MethodNotDeclaredInAttributedInterfaceMessage">
+ <source>The method '{0}' is declared on a different partial definition of the interface '{1}' than the definition that has the 'GeneratedComInterface' attribute</source>
+ <target state="new">The method '{0}' is declared on a different partial definition of the interface '{1}' than the definition that has the 'GeneratedComInterface' attribute</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MethodNotDeclaredInAttributedInterfaceTitle">
+ <source>Method is declared in different partial declaration than the 'GeneratedComInterface' attribute.</source>
+ <target state="new">Method is declared in different partial declaration than the 'GeneratedComInterface' attribute.</target>
+ <note />
+ </trans-unit>
<trans-unit id="TypeNotSupportedDescription">
<source>For types that are not supported by source-generated P/Invokes, the resulting P/Invoke will rely on the underlying runtime to marshal the specified type.</source>
<target state="translated">Per i tipi non supportati da P/Invoke generati dall'origine, il P/Invoke risultante si baserà sul runtime sottostante per effettuare il marshalling del tipo specificato.</target>
<target state="translated">'VirtualMethodIndexAttribute' の使用法が無効です</target>
<note />
</trans-unit>
+ <trans-unit id="MethodNotDeclaredInAttributedInterfaceDescription">
+ <source>All methods must be declared in the same partial definition of a 'GeneratedComInterface'-attributed interface type to ensure reliable calculation for virtual method table offsets.</source>
+ <target state="new">All methods must be declared in the same partial definition of a 'GeneratedComInterface'-attributed interface type to ensure reliable calculation for virtual method table offsets.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MethodNotDeclaredInAttributedInterfaceMessage">
+ <source>The method '{0}' is declared on a different partial definition of the interface '{1}' than the definition that has the 'GeneratedComInterface' attribute</source>
+ <target state="new">The method '{0}' is declared on a different partial definition of the interface '{1}' than the definition that has the 'GeneratedComInterface' attribute</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MethodNotDeclaredInAttributedInterfaceTitle">
+ <source>Method is declared in different partial declaration than the 'GeneratedComInterface' attribute.</source>
+ <target state="new">Method is declared in different partial declaration than the 'GeneratedComInterface' attribute.</target>
+ <note />
+ </trans-unit>
<trans-unit id="TypeNotSupportedDescription">
<source>For types that are not supported by source-generated P/Invokes, the resulting P/Invoke will rely on the underlying runtime to marshal the specified type.</source>
<target state="translated">ソース生成済みの P/Invoke でサポートされていない型である場合、生成された P/Invoke は、基礎となるなるランタイムに依存して、指定された型をマーシャリングします。</target>
<target state="translated">잘못된 'VirtualMethodIndexAttribute' 사용</target>
<note />
</trans-unit>
+ <trans-unit id="MethodNotDeclaredInAttributedInterfaceDescription">
+ <source>All methods must be declared in the same partial definition of a 'GeneratedComInterface'-attributed interface type to ensure reliable calculation for virtual method table offsets.</source>
+ <target state="new">All methods must be declared in the same partial definition of a 'GeneratedComInterface'-attributed interface type to ensure reliable calculation for virtual method table offsets.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MethodNotDeclaredInAttributedInterfaceMessage">
+ <source>The method '{0}' is declared on a different partial definition of the interface '{1}' than the definition that has the 'GeneratedComInterface' attribute</source>
+ <target state="new">The method '{0}' is declared on a different partial definition of the interface '{1}' than the definition that has the 'GeneratedComInterface' attribute</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MethodNotDeclaredInAttributedInterfaceTitle">
+ <source>Method is declared in different partial declaration than the 'GeneratedComInterface' attribute.</source>
+ <target state="new">Method is declared in different partial declaration than the 'GeneratedComInterface' attribute.</target>
+ <note />
+ </trans-unit>
<trans-unit id="TypeNotSupportedDescription">
<source>For types that are not supported by source-generated P/Invokes, the resulting P/Invoke will rely on the underlying runtime to marshal the specified type.</source>
<target state="translated">소스 생성 P/Invoke에서 지원하지 않는 형식의 경우 결과 P/Invoke는 기본 런타임에 의존하여 지정된 형식을 마샬링합니다.</target>
<target state="translated">Nieprawidłowe użycie elementu "VirtualMethodIndexAttribute"</target>
<note />
</trans-unit>
+ <trans-unit id="MethodNotDeclaredInAttributedInterfaceDescription">
+ <source>All methods must be declared in the same partial definition of a 'GeneratedComInterface'-attributed interface type to ensure reliable calculation for virtual method table offsets.</source>
+ <target state="new">All methods must be declared in the same partial definition of a 'GeneratedComInterface'-attributed interface type to ensure reliable calculation for virtual method table offsets.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MethodNotDeclaredInAttributedInterfaceMessage">
+ <source>The method '{0}' is declared on a different partial definition of the interface '{1}' than the definition that has the 'GeneratedComInterface' attribute</source>
+ <target state="new">The method '{0}' is declared on a different partial definition of the interface '{1}' than the definition that has the 'GeneratedComInterface' attribute</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MethodNotDeclaredInAttributedInterfaceTitle">
+ <source>Method is declared in different partial declaration than the 'GeneratedComInterface' attribute.</source>
+ <target state="new">Method is declared in different partial declaration than the 'GeneratedComInterface' attribute.</target>
+ <note />
+ </trans-unit>
<trans-unit id="TypeNotSupportedDescription">
<source>For types that are not supported by source-generated P/Invokes, the resulting P/Invoke will rely on the underlying runtime to marshal the specified type.</source>
<target state="translated">W przypadku typów, które nie są obsługiwane przez funkcję P/Invokes generowaną przez źródło, wynikowa funkcja P/Invoke będzie polegać na bazowym środowisku uruchomieniowym, aby skierować określony typ.</target>
<target state="translated">Uso inválido de 'VirtualMethodIndexAttribute'</target>
<note />
</trans-unit>
+ <trans-unit id="MethodNotDeclaredInAttributedInterfaceDescription">
+ <source>All methods must be declared in the same partial definition of a 'GeneratedComInterface'-attributed interface type to ensure reliable calculation for virtual method table offsets.</source>
+ <target state="new">All methods must be declared in the same partial definition of a 'GeneratedComInterface'-attributed interface type to ensure reliable calculation for virtual method table offsets.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MethodNotDeclaredInAttributedInterfaceMessage">
+ <source>The method '{0}' is declared on a different partial definition of the interface '{1}' than the definition that has the 'GeneratedComInterface' attribute</source>
+ <target state="new">The method '{0}' is declared on a different partial definition of the interface '{1}' than the definition that has the 'GeneratedComInterface' attribute</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MethodNotDeclaredInAttributedInterfaceTitle">
+ <source>Method is declared in different partial declaration than the 'GeneratedComInterface' attribute.</source>
+ <target state="new">Method is declared in different partial declaration than the 'GeneratedComInterface' attribute.</target>
+ <note />
+ </trans-unit>
<trans-unit id="TypeNotSupportedDescription">
<source>For types that are not supported by source-generated P/Invokes, the resulting P/Invoke will rely on the underlying runtime to marshal the specified type.</source>
<target state="translated">Para tipos sem suporte por P/Invokes gerados pela origem, o P/Invoke resultante dependerá do tempo de execução subjacente para realizar marshaling no tipo especificado.</target>
<target state="translated">Недопустимое использование VirtualMethodIndexAttribute</target>
<note />
</trans-unit>
+ <trans-unit id="MethodNotDeclaredInAttributedInterfaceDescription">
+ <source>All methods must be declared in the same partial definition of a 'GeneratedComInterface'-attributed interface type to ensure reliable calculation for virtual method table offsets.</source>
+ <target state="new">All methods must be declared in the same partial definition of a 'GeneratedComInterface'-attributed interface type to ensure reliable calculation for virtual method table offsets.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MethodNotDeclaredInAttributedInterfaceMessage">
+ <source>The method '{0}' is declared on a different partial definition of the interface '{1}' than the definition that has the 'GeneratedComInterface' attribute</source>
+ <target state="new">The method '{0}' is declared on a different partial definition of the interface '{1}' than the definition that has the 'GeneratedComInterface' attribute</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MethodNotDeclaredInAttributedInterfaceTitle">
+ <source>Method is declared in different partial declaration than the 'GeneratedComInterface' attribute.</source>
+ <target state="new">Method is declared in different partial declaration than the 'GeneratedComInterface' attribute.</target>
+ <note />
+ </trans-unit>
<trans-unit id="TypeNotSupportedDescription">
<source>For types that are not supported by source-generated P/Invokes, the resulting P/Invoke will rely on the underlying runtime to marshal the specified type.</source>
<target state="translated">Для типов, которые не поддерживаются в P/Invoke с созданием источника, в полученном P/Invoke для маршализации указанного типа будет использоваться среда выполнения.</target>
<target state="translated">Geçersiz 'VirtualMethodIndexAttribute' kullanımı</target>
<note />
</trans-unit>
+ <trans-unit id="MethodNotDeclaredInAttributedInterfaceDescription">
+ <source>All methods must be declared in the same partial definition of a 'GeneratedComInterface'-attributed interface type to ensure reliable calculation for virtual method table offsets.</source>
+ <target state="new">All methods must be declared in the same partial definition of a 'GeneratedComInterface'-attributed interface type to ensure reliable calculation for virtual method table offsets.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MethodNotDeclaredInAttributedInterfaceMessage">
+ <source>The method '{0}' is declared on a different partial definition of the interface '{1}' than the definition that has the 'GeneratedComInterface' attribute</source>
+ <target state="new">The method '{0}' is declared on a different partial definition of the interface '{1}' than the definition that has the 'GeneratedComInterface' attribute</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MethodNotDeclaredInAttributedInterfaceTitle">
+ <source>Method is declared in different partial declaration than the 'GeneratedComInterface' attribute.</source>
+ <target state="new">Method is declared in different partial declaration than the 'GeneratedComInterface' attribute.</target>
+ <note />
+ </trans-unit>
<trans-unit id="TypeNotSupportedDescription">
<source>For types that are not supported by source-generated P/Invokes, the resulting P/Invoke will rely on the underlying runtime to marshal the specified type.</source>
<target state="translated">Kaynak tarafından oluşturulan P/Invokes tarafından desteklenmeyen türler için, elde edilen P/Invoke, belirtilen türü sıralamak için temel alınan çalışma zamanını kullanır.</target>
<target state="translated">“VirtualMethodIndexAttribute” 使用情况无效</target>
<note />
</trans-unit>
+ <trans-unit id="MethodNotDeclaredInAttributedInterfaceDescription">
+ <source>All methods must be declared in the same partial definition of a 'GeneratedComInterface'-attributed interface type to ensure reliable calculation for virtual method table offsets.</source>
+ <target state="new">All methods must be declared in the same partial definition of a 'GeneratedComInterface'-attributed interface type to ensure reliable calculation for virtual method table offsets.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MethodNotDeclaredInAttributedInterfaceMessage">
+ <source>The method '{0}' is declared on a different partial definition of the interface '{1}' than the definition that has the 'GeneratedComInterface' attribute</source>
+ <target state="new">The method '{0}' is declared on a different partial definition of the interface '{1}' than the definition that has the 'GeneratedComInterface' attribute</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MethodNotDeclaredInAttributedInterfaceTitle">
+ <source>Method is declared in different partial declaration than the 'GeneratedComInterface' attribute.</source>
+ <target state="new">Method is declared in different partial declaration than the 'GeneratedComInterface' attribute.</target>
+ <note />
+ </trans-unit>
<trans-unit id="TypeNotSupportedDescription">
<source>For types that are not supported by source-generated P/Invokes, the resulting P/Invoke will rely on the underlying runtime to marshal the specified type.</source>
<target state="translated">对于源生成的 P/Invoke 不支持的类型,生成的 P/Invoke 将依赖基础运行时来封送指定的类型。</target>
<target state="translated">'VirtualMethodIndexAttribute' 使用方式無效</target>
<note />
</trans-unit>
+ <trans-unit id="MethodNotDeclaredInAttributedInterfaceDescription">
+ <source>All methods must be declared in the same partial definition of a 'GeneratedComInterface'-attributed interface type to ensure reliable calculation for virtual method table offsets.</source>
+ <target state="new">All methods must be declared in the same partial definition of a 'GeneratedComInterface'-attributed interface type to ensure reliable calculation for virtual method table offsets.</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MethodNotDeclaredInAttributedInterfaceMessage">
+ <source>The method '{0}' is declared on a different partial definition of the interface '{1}' than the definition that has the 'GeneratedComInterface' attribute</source>
+ <target state="new">The method '{0}' is declared on a different partial definition of the interface '{1}' than the definition that has the 'GeneratedComInterface' attribute</target>
+ <note />
+ </trans-unit>
+ <trans-unit id="MethodNotDeclaredInAttributedInterfaceTitle">
+ <source>Method is declared in different partial declaration than the 'GeneratedComInterface' attribute.</source>
+ <target state="new">Method is declared in different partial declaration than the 'GeneratedComInterface' attribute.</target>
+ <note />
+ </trans-unit>
<trans-unit id="TypeNotSupportedDescription">
<source>For types that are not supported by source-generated P/Invokes, the resulting P/Invoke will rely on the underlying runtime to marshal the specified type.</source>
<target state="translated">對於來源產生的 P/Invokes 不支援的類型,產生的 P/Invoke 將依賴基礎運行時間來封送指定的類型。</target>
[Generator]
public sealed class VtableIndexStubGenerator : IIncrementalGenerator
{
- internal sealed record IncrementalStubGenerationContext(
- SignatureContext SignatureContext,
- ContainingSyntaxContext ContainingSyntaxContext,
- ContainingSyntax StubMethodSyntaxTemplate,
- MethodSignatureDiagnosticLocations DiagnosticLocation,
- SequenceEqualImmutableArray<FunctionPointerUnmanagedCallingConventionSyntax> CallingConvention,
- VirtualMethodIndexData VtableIndexData,
- MarshallingInfo ExceptionMarshallingInfo,
- MarshallingGeneratorFactoryKey<(TargetFramework TargetFramework, Version TargetFrameworkVersion)> ManagedToUnmanagedGeneratorFactory,
- MarshallingGeneratorFactoryKey<(TargetFramework TargetFramework, Version TargetFrameworkVersion)> UnmanagedToManagedGeneratorFactory,
- ManagedTypeInfo TypeKeyOwner,
- SequenceEqualImmutableArray<Diagnostic> Diagnostics);
-
public static class StepNames
{
public const string CalculateStubInformation = nameof(CalculateStubInformation);
// Calculate all of information to generate both managed-to-unmanaged and unmanaged-to-managed stubs
// for each method.
- IncrementalValuesProvider<IncrementalStubGenerationContext> generateStubInformation = methodsToGenerate
+ IncrementalValuesProvider<IncrementalMethodStubGenerationContext> generateStubInformation = methodsToGenerate
.Combine(context.CreateStubEnvironmentProvider())
.Select(static (data, ct) => new
{
context.RegisterConcatenatedSyntaxOutputs(generateManagedToNativeStub.Select((data, ct) => data.Item1), "ManagedToNativeStubs.g.cs");
// Filter the list of all stubs to only the stubs that requested unmanaged-to-managed stub generation.
- IncrementalValuesProvider<IncrementalStubGenerationContext> nativeToManagedStubContexts =
+ IncrementalValuesProvider<IncrementalMethodStubGenerationContext> nativeToManagedStubContexts =
generateStubInformation
.Where(data => data.VtableIndexData.Direction is MarshalDirection.UnmanagedToManaged or MarshalDirection.Bidirectional);
context.RegisterConcatenatedSyntaxOutputs(populateVTable, "PopulateVTable.g.cs");
}
- private static ImmutableArray<FunctionPointerUnmanagedCallingConventionSyntax> GenerateCallConvSyntaxFromAttributes(AttributeData? suppressGCTransitionAttribute, AttributeData? unmanagedCallConvAttribute)
+ internal static ImmutableArray<FunctionPointerUnmanagedCallingConventionSyntax> GenerateCallConvSyntaxFromAttributes(AttributeData? suppressGCTransitionAttribute, AttributeData? unmanagedCallConvAttribute)
{
const string CallConvsField = "CallConvs";
ImmutableArray<FunctionPointerUnmanagedCallingConventionSyntax>.Builder callingConventions = ImmutableArray.CreateBuilder<FunctionPointerUnmanagedCallingConventionSyntax>();
};
}
- private static IncrementalStubGenerationContext CalculateStubInformation(MethodDeclarationSyntax syntax, IMethodSymbol symbol, StubEnvironment environment, CancellationToken ct)
+ private static IncrementalMethodStubGenerationContext CalculateStubInformation(MethodDeclarationSyntax syntax, IMethodSymbol symbol, StubEnvironment environment, CancellationToken ct)
{
ct.ThrowIfCancellationRequested();
INamedTypeSymbol? lcidConversionAttrType = environment.Compilation.GetTypeByMetadataName(TypeNames.LCIDConversionAttribute);
MarshallingInfo exceptionMarshallingInfo = CreateExceptionMarshallingInfo(virtualMethodIndexAttr, symbol, environment.Compilation, generatorDiagnostics, virtualMethodIndexData);
- return new IncrementalStubGenerationContext(
+ return new IncrementalMethodStubGenerationContext(
signatureContext,
containingSyntaxContext,
methodSyntaxTemplate,
return NoMarshallingInfo.Instance;
}
- private static (MemberDeclarationSyntax, ImmutableArray<Diagnostic>) GenerateManagedToNativeStub(
- IncrementalStubGenerationContext methodStub)
+ internal static (MemberDeclarationSyntax, ImmutableArray<Diagnostic>) GenerateManagedToNativeStub(
+ IncrementalMethodStubGenerationContext methodStub)
{
var diagnostics = new GeneratorDiagnostics();
private const string ThisParameterIdentifier = "@this";
- private static (MemberDeclarationSyntax, ImmutableArray<Diagnostic>) GenerateNativeToManagedStub(
- IncrementalStubGenerationContext methodStub)
+ internal static (MemberDeclarationSyntax, ImmutableArray<Diagnostic>) GenerateNativeToManagedStub(
+ IncrementalMethodStubGenerationContext methodStub)
{
var diagnostics = new GeneratorDiagnostics();
ImmutableArray<TypePositionInfo> elements = AddImplicitElementInfos(methodStub);
methodStub.Diagnostics.Array.AddRange(diagnostics.Diagnostics));
}
- private static ImmutableArray<TypePositionInfo> AddImplicitElementInfos(IncrementalStubGenerationContext methodStub)
+ private static ImmutableArray<TypePositionInfo> AddImplicitElementInfos(IncrementalMethodStubGenerationContext methodStub)
{
ImmutableArray<TypePositionInfo> originalElements = methodStub.SignatureContext.ElementTypeInformation;
.AddAttributeLists(AttributeList(SingletonSeparatedList(Attribute(ParseName(TypeNames.System_Runtime_InteropServices_DynamicInterfaceCastableImplementationAttribute))))));
}
- private static MemberDeclarationSyntax GeneratePopulateVTableMethod(IGrouping<ContainingSyntaxContext, IncrementalStubGenerationContext> vtableMethods)
+ private static MemberDeclarationSyntax GeneratePopulateVTableMethod(IGrouping<ContainingSyntaxContext, IncrementalMethodStubGenerationContext> vtableMethods)
{
const string vtableParameter = "vtable";
ContainingSyntaxContext containingSyntax = vtableMethods.Key.AddContainingSyntax(NativeTypeContainingSyntax);
foreach (var method in vtableMethods)
{
- var stubGenerator = new UnmanagedToManagedStubGenerator(
- method.UnmanagedToManagedGeneratorFactory.Key.TargetFramework,
- method.UnmanagedToManagedGeneratorFactory.Key.TargetFrameworkVersion,
- AddImplicitElementInfos(method),
- // Swallow diagnostics here since the diagnostics will be reported by the unmanaged->managed stub generation
- (elementInfo, ex) => { },
- method.UnmanagedToManagedGeneratorFactory.GeneratorFactory);
-
- List<FunctionPointerParameterSyntax> functionPointerParameters = new();
- var (paramList, retType, _) = stubGenerator.GenerateAbiMethodSignatureData();
- functionPointerParameters.AddRange(paramList.Parameters.Select(p => FunctionPointerParameter(p.Type)));
- functionPointerParameters.Add(FunctionPointerParameter(retType));
-
- // delegate* unmanaged<...>
- ImmutableArray<FunctionPointerUnmanagedCallingConventionSyntax> callConv = method.CallingConvention.Array;
- FunctionPointerTypeSyntax functionPointerType = FunctionPointerType(
- FunctionPointerCallingConvention(Token(SyntaxKind.UnmanagedKeyword), callConv.IsEmpty ? null : FunctionPointerUnmanagedCallingConventionList(SeparatedList(callConv))),
- FunctionPointerParameterList(SeparatedList(functionPointerParameters)));
+ FunctionPointerTypeSyntax functionPointerType = GenerateUnmanagedFunctionPointerTypeForMethod(method);
// <vtableParameter>[<index>] = (nint)(<functionPointerType>)&ABI_<methodIdentifier>;
populateVtableMethod = populateVtableMethod.AddBodyStatements(
return containingSyntax.WrapMemberInContainingSyntaxWithUnsafeModifier(populateVtableMethod);
}
+
+ internal static FunctionPointerTypeSyntax GenerateUnmanagedFunctionPointerTypeForMethod(IncrementalMethodStubGenerationContext method)
+ {
+ var stubGenerator = new UnmanagedToManagedStubGenerator(
+ method.UnmanagedToManagedGeneratorFactory.Key.TargetFramework,
+ method.UnmanagedToManagedGeneratorFactory.Key.TargetFrameworkVersion,
+ AddImplicitElementInfos(method),
+ // Swallow diagnostics here since the diagnostics will be reported by the unmanaged->managed stub generation
+ (elementInfo, ex) => { },
+ method.UnmanagedToManagedGeneratorFactory.GeneratorFactory);
+
+ List<FunctionPointerParameterSyntax> functionPointerParameters = new();
+ var (paramList, retType, _) = stubGenerator.GenerateAbiMethodSignatureData();
+ functionPointerParameters.AddRange(paramList.Parameters.Select(p => FunctionPointerParameter(p.Type)));
+ // We add the return type as the last "parameter" here as that's what the function pointer syntax requires.
+ functionPointerParameters.Add(FunctionPointerParameter(retType));
+
+ // delegate* unmanaged<...>
+ ImmutableArray<FunctionPointerUnmanagedCallingConventionSyntax> callConv = method.CallingConvention.Array;
+ FunctionPointerTypeSyntax functionPointerType = FunctionPointerType(
+ FunctionPointerCallingConvention(Token(SyntaxKind.UnmanagedKeyword), callConv.IsEmpty ? null : FunctionPointerUnmanagedCallingConventionList(SeparatedList(callConv))),
+ FunctionPointerParameterList(SeparatedList(functionPointerParameters)));
+ return functionPointerType;
+ }
}
}