diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceAndMethodsContext.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceAndMethodsContext.cs index e1ee7e6d535c98..107ee390e89330 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceAndMethodsContext.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceAndMethodsContext.cs @@ -20,11 +20,23 @@ internal sealed record ComInterfaceAndMethodsContext(ComInterfaceContext Interfa /// /// COM methods that require shadowing declarations on the derived interface. /// - public IEnumerable ShadowingMethods => Methods.Where(m => m.IsInheritedMethod && !m.IsHiddenOnDerivedInterface); + public IEnumerable ShadowingMethods => Methods.Where(m => m.IsInheritedMethod && !m.IsHiddenOnDerivedInterface && !m.IsExternallyDefined); /// /// COM methods that are declared on an interface the interface inherits from. /// public IEnumerable InheritedMethods => Methods.Where(m => m.IsInheritedMethod); + + /// + /// The size of the vtable for this interface, including the base interface methods and IUnknown methods. + /// + public int VTableSize => Methods.Length == 0 + ? IUnknownConstants.VTableSize + : 1 + Methods.Max(m => m.GenerationContext.VtableIndexData.Index); + + /// + /// The size of the vtable for the base interface, including it's base interface methods and IUnknown methods. + /// + public int BaseVTableSize => VTableSize - DeclaredMethods.Count(); } } diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.cs index 2d94a3bd4a1bdd..c85104517d6c08 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceGenerator.cs @@ -54,7 +54,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) var externalInterfaceSymbols = attributedInterfaces.SelectMany(static (data, ct) => { return ComInterfaceInfo.CreateInterfaceInfoForBaseInterfacesInOtherCompilations(data.Symbol); - }); + }).Collect().SelectMany(static (data, ct) => data.Distinct(ComInterfaceInfo.EqualityComparerForExternalIfaces.Instance)); var interfaceSymbolsWithoutDiagnostics = interfaceSymbolsToGenerateWithoutDiagnostics.Concat(externalInterfaceSymbols); @@ -84,11 +84,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) .SelectMany(static (data, ct) => { return ComMethodContext.CalculateAllMethods(data, ct); - }) - // Now that we've determined method offsets, we can remove all externally defined methods. - // We'll also filter out methods originally declared on externally defined base interfaces - // as we may not be able to emit them into our assembly. - .Where(context => !context.Method.OriginalDeclaringInterface.IsExternallyDefined); + }); // Now that we've determined method offsets, we can remove all externally defined interfaces. var interfaceContextsToGenerate = interfaceContexts.Where(context => !context.IsExternallyDefined); @@ -107,13 +103,20 @@ public void Initialize(IncrementalGeneratorInitializationContext context) return new ComMethodContext( data.Method, data.OwningInterface, - CalculateStubInformation(data.Method.MethodInfo.Syntax, symbolMap[data.Method.MethodInfo], data.Method.Index, env, data.OwningInterface.Info, ct)); + CalculateStubInformation( + data.Method.MethodInfo.Syntax, + symbolMap[data.Method.MethodInfo], + data.Method.Index, + env, + data.OwningInterface.Info, + ct)); }).WithTrackingName(StepNames.CalculateStubInformation); var interfaceAndMethodsContexts = comMethodContexts .Collect() .Combine(interfaceContextsToGenerate.Collect()) - .SelectMany((data, ct) => GroupComContextsForInterfaceGeneration(data.Left, data.Right, ct)); + .SelectMany((data, ct) => + GroupComContextsForInterfaceGeneration(data.Left, data.Right, ct)); // Generate the code for the managed-to-unmanaged stubs. var managedToNativeInterfaceImplementations = interfaceAndMethodsContexts @@ -256,12 +259,22 @@ private static bool IsHResultLikeType(ManagedTypeInfo type) || typeName.Equals("hresult", StringComparison.OrdinalIgnoreCase); } - private static IncrementalMethodStubGenerationContext CalculateStubInformation(MethodDeclarationSyntax syntax, IMethodSymbol symbol, int index, StubEnvironment environment, ComInterfaceInfo owningInterfaceInfo, CancellationToken ct) + /// + /// Calculates the shared information needed for both source-available and sourceless stub generation. + /// + private static IncrementalMethodStubGenerationContext CalculateSharedStubInformation( + IMethodSymbol symbol, + int index, + StubEnvironment environment, + ISignatureDiagnosticLocations diagnosticLocations, + ComInterfaceInfo owningInterfaceInfo, + CancellationToken ct) { ct.ThrowIfCancellationRequested(); INamedTypeSymbol? lcidConversionAttrType = environment.LcidConversionAttrType; INamedTypeSymbol? suppressGCTransitionAttrType = environment.SuppressGCTransitionAttrType; INamedTypeSymbol? unmanagedCallConvAttrType = environment.UnmanagedCallConvAttrType; + // Get any attributes of interest on the method AttributeData? lcidConversionAttr = null; AttributeData? suppressGCTransitionAttribute = null; @@ -282,8 +295,7 @@ private static IncrementalMethodStubGenerationContext CalculateStubInformation(M } } - var locations = new MethodSignatureDiagnosticLocations(syntax); - var generatorDiagnostics = new GeneratorDiagnosticsBag(new DiagnosticDescriptorProvider(), locations, SR.ResourceManager, typeof(FxResources.Microsoft.Interop.ComInterfaceGenerator.SR)); + var generatorDiagnostics = new GeneratorDiagnosticsBag(new DiagnosticDescriptorProvider(), diagnosticLocations, SR.ResourceManager, typeof(FxResources.Microsoft.Interop.ComInterfaceGenerator.SR)); if (lcidConversionAttr is not null) { @@ -293,8 +305,8 @@ private static IncrementalMethodStubGenerationContext CalculateStubInformation(M GeneratedComInterfaceCompilationData.TryGetGeneratedComInterfaceAttributeFromInterface(symbol.ContainingType, out var generatedComAttribute); var generatedComInterfaceAttributeData = GeneratedComInterfaceCompilationData.GetDataFromAttribute(generatedComAttribute); - // Create the stub. + // Create the stub. var signatureContext = SignatureContext.Create( symbol, DefaultMarshallingInfoParser.Create( @@ -387,10 +399,6 @@ private static IncrementalMethodStubGenerationContext CalculateStubInformation(M GeneratorDiagnostics.SizeOfInCollectionMustBeDefinedAtCallReturnValue); } - var containingSyntaxContext = new ContainingSyntaxContext(syntax); - - var methodSyntaxTemplate = new ContainingSyntax(new SyntaxTokenList(syntax.Modifiers.Where(static m => !m.IsKind(SyntaxKind.NewKeyword))).StripAccessibilityModifiers(), SyntaxKind.MethodDeclaration, syntax.Identifier, syntax.TypeParameterList); - ImmutableArray callConv = VirtualMethodPointerStubGenerator.GenerateCallConvSyntaxFromAttributes( suppressGCTransitionAttribute, unmanagedCallConvAttribute, @@ -398,10 +406,7 @@ private static IncrementalMethodStubGenerationContext CalculateStubInformation(M var declaringType = ManagedTypeInfo.CreateTypeInfoForTypeSymbol(symbol.ContainingType); - var virtualMethodIndexData = new VirtualMethodIndexData(index, ImplicitThisParameter: true, direction, true, ExceptionMarshalling.Com); - MarshallingInfo exceptionMarshallingInfo; - if (generatedComInterfaceAttributeData.ExceptionToUnmanagedMarshaller is null) { exceptionMarshallingInfo = new ComExceptionMarshalling(); @@ -418,11 +423,9 @@ private static IncrementalMethodStubGenerationContext CalculateStubInformation(M return new IncrementalMethodStubGenerationContext( signatureContext, - containingSyntaxContext, - methodSyntaxTemplate, - locations, + diagnosticLocations, callConv.ToSequenceEqualImmutableArray(SyntaxEquivalentComparer.Instance), - virtualMethodIndexData, + new VirtualMethodIndexData(index, ImplicitThisParameter: true, direction, true, ExceptionMarshalling.Com), exceptionMarshallingInfo, environment.EnvironmentFlags, owningInterfaceInfo.Type, @@ -431,6 +434,45 @@ private static IncrementalMethodStubGenerationContext CalculateStubInformation(M ComInterfaceDispatchMarshallingInfo.Instance); } + private static IncrementalMethodStubGenerationContext CalculateStubInformation(MethodDeclarationSyntax? syntax, IMethodSymbol symbol, int index, StubEnvironment environment, ComInterfaceInfo owningInterface, CancellationToken ct) + { + ISignatureDiagnosticLocations locations = syntax is null + ? NoneSignatureDiagnosticLocations.Instance + : new MethodSignatureDiagnosticLocations(syntax); + + var sourcelessStubInformation = CalculateSharedStubInformation( + symbol, + index, + environment, + locations, + owningInterface, + ct); + + if (syntax is null) + return sourcelessStubInformation; + + var containingSyntaxContext = new ContainingSyntaxContext(syntax); + var methodSyntaxTemplate = new ContainingSyntax( + new SyntaxTokenList(syntax.Modifiers.Where(static m => !m.IsKind(SyntaxKind.NewKeyword))).StripAccessibilityModifiers(), + SyntaxKind.MethodDeclaration, + syntax.Identifier, + syntax.TypeParameterList); + + return new SourceAvailableIncrementalMethodStubGenerationContext( + sourcelessStubInformation.SignatureContext, + containingSyntaxContext, + methodSyntaxTemplate, + locations, + sourcelessStubInformation.CallingConvention, + sourcelessStubInformation.VtableIndexData, + sourcelessStubInformation.ExceptionMarshallingInfo, + sourcelessStubInformation.EnvironmentFlags, + sourcelessStubInformation.TypeKeyOwner, + sourcelessStubInformation.DeclaringType, + sourcelessStubInformation.Diagnostics, + ComInterfaceDispatchMarshallingInfo.Instance); + } + private static MarshalDirection GetDirectionFromOptions(ComInterfaceOptions options) { if (options.HasFlag(ComInterfaceOptions.ManagedObjectWrapper | ComInterfaceOptions.ComObjectWrapper)) @@ -520,12 +562,12 @@ static bool MethodEquals(ComMethodContext a, ComMethodContext b) private static InterfaceDeclarationSyntax GenerateImplementationInterface(ComInterfaceAndMethodsContext interfaceGroup, CancellationToken _) { var definingType = interfaceGroup.Interface.Info.Type; - var shadowImplementations = interfaceGroup.InheritedMethods.Select(m => (Method: m, ManagedToUnmanagedStub: m.ManagedToUnmanagedStub)) + 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.Select(m => m.UnreachableExceptionStub); + var inheritedStubs = interfaceGroup.InheritedMethods.Where(m => !m.IsExternallyDefined).Select(m => m.UnreachableExceptionStub); return ImplementationInterfaceTemplate .AddBaseListTypes(SimpleBaseType(definingType.Syntax)) .WithMembers( @@ -661,7 +703,6 @@ private static InterfaceDeclarationSyntax GenerateImplementationVTable(ComInterf BlockSyntax fillBaseInterfaceSlots; - if (interfaceMethods.Interface.Base is null) { // If we don't have a base interface, we need to manually fill in the base iUnknown slots. @@ -740,7 +781,7 @@ private static InterfaceDeclarationSyntax GenerateImplementationVTable(ComInterf } else { - // NativeMemory.Copy(StrategyBasedComWrappers.DefaultIUnknownInteraceDetailsStrategy.GetIUnknownDerivedDetails(typeof().TypeHandle).ManagedVirtualMethodTable, vtable, (nuint)(sizeof(void*) * )); + // NativeMemory.Copy(StrategyBasedComWrappers.DefaultIUnknownInterfaceDetailsStrategy.GetIUnknownDerivedDetails(typeof().TypeHandle).ManagedVirtualMethodTable, vtable, (nuint)(sizeof(void*) * )); fillBaseInterfaceSlots = Block( MethodInvocationStatement( TypeSyntaxes.System_Runtime_InteropServices_NativeMemory, @@ -750,7 +791,7 @@ private static InterfaceDeclarationSyntax GenerateImplementationVTable(ComInterf TypeSyntaxes.StrategyBasedComWrappers .Dot(IdentifierName("DefaultIUnknownInterfaceDetailsStrategy")), IdentifierName("GetIUnknownDerivedDetails"), - Argument( //baseInterfaceTypeInfo.BaseInterface.FullTypeName)), + Argument( TypeOfExpression(ParseTypeName(interfaceMethods.Interface.Base.Info.Type.FullTypeName)) .Dot(IdentifierName("TypeHandle")))) .Dot(IdentifierName("ManagedVirtualMethodTable"))), @@ -767,7 +808,7 @@ private static InterfaceDeclarationSyntax GenerateImplementationVTable(ComInterf ParenthesizedExpression( BinaryExpression(SyntaxKind.MultiplyExpression, SizeOfExpression(PointerType(PredefinedType(Token(SyntaxKind.VoidKeyword)))), - LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(interfaceMethods.InheritedMethods.Count() + 3)))))))); + LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(interfaceMethods.BaseVTableSize)))))))); } var validDeclaredMethods = interfaceMethods.DeclaredMethods @@ -787,7 +828,7 @@ private static InterfaceDeclarationSyntax GenerateImplementationVTable(ComInterf IdentifierName($"{declaredMethodContext.MethodInfo.MethodName}_{declaredMethodContext.GenerationContext.VtableIndexData.Index}")), PrefixUnaryExpression( SyntaxKind.AddressOfExpression, - IdentifierName($"ABI_{declaredMethodContext.GenerationContext.StubMethodSyntaxTemplate.Identifier}"))))); + IdentifierName($"ABI_{((SourceAvailableIncrementalMethodStubGenerationContext)declaredMethodContext.GenerationContext).StubMethodSyntaxTemplate.Identifier}"))))); } return ImplementationInterfaceTemplate diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceInfo.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceInfo.cs index 0e5219065c8ab5..cbdffa67d62357 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceInfo.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceInfo.cs @@ -2,7 +2,9 @@ // 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.Diagnostics.CodeAnalysis; using System.Threading; using Microsoft.CodeAnalysis; @@ -10,7 +12,6 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using InterfaceInfo = (Microsoft.Interop.ComInterfaceInfo InterfaceInfo, Microsoft.CodeAnalysis.INamedTypeSymbol Symbol); using DiagnosticOrInterfaceInfo = Microsoft.Interop.DiagnosticOr<(Microsoft.Interop.ComInterfaceInfo InterfaceInfo, Microsoft.CodeAnalysis.INamedTypeSymbol Symbol)>; -using System.Diagnostics; namespace Microsoft.Interop { @@ -176,6 +177,13 @@ public static ImmutableArray CreateInterfaceInfoForBaseInterfaces return builder.ToImmutable(); } + internal sealed class EqualityComparerForExternalIfaces : IEqualityComparer<(ComInterfaceInfo InterfaceInfo, INamedTypeSymbol Symbol)> + { + public bool Equals((ComInterfaceInfo, INamedTypeSymbol) x, (ComInterfaceInfo, INamedTypeSymbol) y) => SymbolEqualityComparer.Default.Equals(x.Item2, y.Item2); + public int GetHashCode((ComInterfaceInfo, INamedTypeSymbol) obj) => SymbolEqualityComparer.Default.GetHashCode(obj.Item2); + public static readonly EqualityComparerForExternalIfaces Instance = new(); + } + private static bool IsInPartialContext(INamedTypeSymbol symbol, InterfaceDeclarationSyntax syntax, [NotNullWhen(false)] out DiagnosticInfo? diagnostic) { // Verify that the types the interface is declared in are marked partial. diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComMethodContext.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComMethodContext.cs index 42d0bb3691ead8..d2327e0cafdb34 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComMethodContext.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComMethodContext.cs @@ -21,8 +21,8 @@ namespace Microsoft.Interop internal sealed class ComMethodContext : IEquatable { /// - /// A partially constructed that does not have a generated for it yet. - /// can be constructed without a reference to an ISymbol, whereas the requires an ISymbol + /// A partially constructed that does not have a generated for it yet. + /// can be constructed without a reference to an ISymbol, whereas the requires an ISymbol /// /// /// The interface that originally declared the method in user code @@ -48,7 +48,7 @@ private record struct State( /// The partially constructed context /// The final owning interface of this method context /// The generation context for this method - public ComMethodContext(Builder builder, ComInterfaceContext owningInterface, IncrementalMethodStubGenerationContext generationContext) + public ComMethodContext(Builder builder, ComInterfaceContext owningInterface, IncrementalMethodStubGenerationContext? generationContext) { _state = new State(builder.OriginalDeclaringInterface, owningInterface, builder.MethodInfo, generationContext); } @@ -65,6 +65,8 @@ public ComMethodContext(Builder builder, ComInterfaceContext owningInterface, In public ComMethodInfo MethodInfo => _state.MethodInfo; + public bool IsExternallyDefined => _state.OriginalDeclaringInterface.IsExternallyDefined || _state.OwningInterface.IsExternallyDefined; + public IncrementalMethodStubGenerationContext GenerationContext => _state.GenerationContext; public bool IsInheritedMethod => OriginalDeclaringInterface != OwningInterface; @@ -77,12 +79,18 @@ public ComMethodContext(Builder builder, ComInterfaceContext owningInterface, In private GeneratedMethodContextBase CreateManagedToUnmanagedStub() { - if (GenerationContext.VtableIndexData.Direction is not (MarshalDirection.ManagedToUnmanaged or MarshalDirection.Bidirectional) || IsHiddenOnDerivedInterface) + if (GenerationContext.VtableIndexData.Direction is not (MarshalDirection.ManagedToUnmanaged or MarshalDirection.Bidirectional) + || IsHiddenOnDerivedInterface + || IsExternallyDefined) { return new SkippedStubContext(OriginalDeclaringInterface.Info.Type); } - var (methodStub, diagnostics) = VirtualMethodPointerStubGenerator.GenerateManagedToNativeStub(GenerationContext, ComInterfaceGeneratorHelpers.GetGeneratorResolver); - return new GeneratedStubCodeContext(GenerationContext.TypeKeyOwner, GenerationContext.ContainingSyntaxContext, new(methodStub), new(diagnostics)); + if (GenerationContext is not SourceAvailableIncrementalMethodStubGenerationContext sourceAvailableContext) + { + throw new InvalidOperationException("Cannot generate stubs for non-source available methods."); + } + var (methodStub, diagnostics) = VirtualMethodPointerStubGenerator.GenerateManagedToNativeStub(sourceAvailableContext, ComInterfaceGeneratorHelpers.GetGeneratorResolver); + return new GeneratedStubCodeContext(sourceAvailableContext.TypeKeyOwner, sourceAvailableContext.ContainingSyntaxContext, new(methodStub), new(diagnostics)); } private GeneratedMethodContextBase? _unmanagedToManagedStub; @@ -91,12 +99,18 @@ private GeneratedMethodContextBase CreateManagedToUnmanagedStub() private GeneratedMethodContextBase CreateUnmanagedToManagedStub() { - if (GenerationContext.VtableIndexData.Direction is not (MarshalDirection.UnmanagedToManaged or MarshalDirection.Bidirectional) || IsHiddenOnDerivedInterface) + if (GenerationContext.VtableIndexData.Direction is not (MarshalDirection.UnmanagedToManaged or MarshalDirection.Bidirectional) + || IsHiddenOnDerivedInterface + || IsExternallyDefined) { return new SkippedStubContext(GenerationContext.OriginalDefiningType); } - var (methodStub, diagnostics) = VirtualMethodPointerStubGenerator.GenerateNativeToManagedStub(GenerationContext, ComInterfaceGeneratorHelpers.GetGeneratorResolver); - return new GeneratedStubCodeContext(GenerationContext.OriginalDefiningType, GenerationContext.ContainingSyntaxContext, new(methodStub), new(diagnostics)); + if (GenerationContext is not SourceAvailableIncrementalMethodStubGenerationContext sourceAvailableContext) + { + throw new InvalidOperationException("Cannot generate stubs for non-source available methods."); + } + var (methodStub, diagnostics) = VirtualMethodPointerStubGenerator.GenerateNativeToManagedStub(sourceAvailableContext, ComInterfaceGeneratorHelpers.GetGeneratorResolver); + return new GeneratedStubCodeContext(sourceAvailableContext.OriginalDefiningType, sourceAvailableContext.ContainingSyntaxContext, new(methodStub), new(diagnostics)); } private MethodDeclarationSyntax? _unreachableExceptionStub; @@ -183,7 +197,7 @@ ImmutableArray AddMethods(ComInterfaceContext iface, IEnumerable methods = new(); // If we have a base interface, we should add the inherited methods to our list in vtable order if (iface.Base is not null) diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComMethodInfo.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComMethodInfo.cs index 7cb12ff08c308e..f58aa48301ff0d 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComMethodInfo.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComMethodInfo.cs @@ -17,7 +17,7 @@ namespace Microsoft.Interop /// internal sealed record ComMethodInfo { - public MethodDeclarationSyntax Syntax { get; init; } + public MethodDeclarationSyntax? Syntax { get; init; } public string MethodName { get; init; } public SequenceEqualImmutableArray Attributes { get; init; } public bool IsUserDefinedShadowingMethod { get; init; } @@ -94,7 +94,7 @@ private ComMethodInfo( if (ifaceContext.IsExternallyDefined) { return DiagnosticOr<(ComMethodInfo, IMethodSymbol)>.From(( - new ComMethodInfo(null!, method.Name, method.GetAttributes().Select(AttributeInfo.From).ToImmutableArray().ToSequenceEqual(), false), + new ComMethodInfo(null, method.Name, method.GetAttributes().Select(AttributeInfo.From).ToImmutableArray().ToSequenceEqual(), false), method)); } diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/IUnknownConstants.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/IUnknownConstants.cs new file mode 100644 index 00000000000000..e03567780b38ae --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/IUnknownConstants.cs @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.Interop +{ + internal static class IUnknownConstants + { + public const int QueryInterfaceIndex = 0; + public const int AddRefIndex = 1; + public const int ReleaseIndex = 2; + public const int VTableSize = 3; + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/IncrementalMethodStubGenerationContext.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/IncrementalMethodStubGenerationContext.cs index 06ece904e3f2ef..d42b40e8d998b8 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/IncrementalMethodStubGenerationContext.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/IncrementalMethodStubGenerationContext.cs @@ -1,19 +1,29 @@ // 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 abstract record GeneratedMethodContextBase(ManagedTypeInfo OriginalDefiningType, SequenceEqualImmutableArray Diagnostics); - internal sealed record IncrementalMethodStubGenerationContext( + internal record IncrementalMethodStubGenerationContext( + SignatureContext SignatureContext, + ISignatureDiagnosticLocations DiagnosticLocation, + SequenceEqualImmutableArray CallingConvention, + VirtualMethodIndexData VtableIndexData, + MarshallingInfo ExceptionMarshallingInfo, + EnvironmentFlags EnvironmentFlags, + ManagedTypeInfo TypeKeyOwner, + ManagedTypeInfo DeclaringType, + SequenceEqualImmutableArray Diagnostics, + MarshallingInfo ManagedThisMarshallingInfo) : GeneratedMethodContextBase(DeclaringType, Diagnostics); + + internal sealed record SourceAvailableIncrementalMethodStubGenerationContext( SignatureContext SignatureContext, ContainingSyntaxContext ContainingSyntaxContext, ContainingSyntax StubMethodSyntaxTemplate, - MethodSignatureDiagnosticLocations DiagnosticLocation, + ISignatureDiagnosticLocations DiagnosticLocation, SequenceEqualImmutableArray CallingConvention, VirtualMethodIndexData VtableIndexData, MarshallingInfo ExceptionMarshallingInfo, @@ -21,5 +31,15 @@ internal sealed record IncrementalMethodStubGenerationContext( ManagedTypeInfo TypeKeyOwner, ManagedTypeInfo DeclaringType, SequenceEqualImmutableArray Diagnostics, - MarshallingInfo ManagedThisMarshallingInfo) : GeneratedMethodContextBase(DeclaringType, Diagnostics); + MarshallingInfo ManagedThisMarshallingInfo) : IncrementalMethodStubGenerationContext( + SignatureContext, + DiagnosticLocation, + CallingConvention, + VtableIndexData, + ExceptionMarshallingInfo, + EnvironmentFlags, + TypeKeyOwner, + DeclaringType, + Diagnostics, + ManagedThisMarshallingInfo); } diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VirtualMethodPointerStubGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VirtualMethodPointerStubGenerator.cs index 54ab6543c8a373..fb7df8530364f2 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VirtualMethodPointerStubGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VirtualMethodPointerStubGenerator.cs @@ -21,7 +21,7 @@ internal static class VirtualMethodPointerStubGenerator internal const string VirtualMethodTarget = "__target"; public static (MethodDeclarationSyntax, ImmutableArray) GenerateManagedToNativeStub( - IncrementalMethodStubGenerationContext methodStub, + SourceAvailableIncrementalMethodStubGenerationContext methodStub, Func generatorResolverCreator) { var diagnostics = new GeneratorDiagnosticsBag(new DiagnosticDescriptorProvider(), methodStub.DiagnosticLocation, SR.ResourceManager, typeof(FxResources.Microsoft.Interop.ComInterfaceGenerator.SR)); @@ -128,7 +128,7 @@ private static MethodDeclarationSyntax PrintGeneratedSource( private const string ManagedThisParameterIdentifier = "@this"; public static (MethodDeclarationSyntax, ImmutableArray) GenerateNativeToManagedStub( - IncrementalMethodStubGenerationContext methodStub, + SourceAvailableIncrementalMethodStubGenerationContext methodStub, Func generatorResolverCreator) { var diagnostics = new GeneratorDiagnosticsBag(new DiagnosticDescriptorProvider(), methodStub.DiagnosticLocation, SR.ResourceManager, typeof(FxResources.Microsoft.Interop.ComInterfaceGenerator.SR)); @@ -174,7 +174,7 @@ public static (MethodDeclarationSyntax, ImmutableArray) Generate methodStub.Diagnostics.Array.AddRange(diagnostics.Diagnostics)); } - private static ImmutableArray AddManagedToUnmanagedImplicitThis(IncrementalMethodStubGenerationContext methodStub) + private static ImmutableArray AddManagedToUnmanagedImplicitThis(SourceAvailableIncrementalMethodStubGenerationContext methodStub) { ImmutableArray originalElements = methodStub.SignatureContext.ElementTypeInformation; @@ -232,7 +232,7 @@ private static ImmutableArray AddUnmanagedToManagedImplicitEle } public static BlockSyntax GenerateVirtualMethodTableSlotAssignments( - IEnumerable vtableMethods, + IEnumerable vtableMethods, string vtableIdentifier, Func generatorResolverCreator) { diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs index 9328c0e7d6e56e..e46ab33137dab4 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs @@ -62,7 +62,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) // Calculate all of information to generate both managed-to-unmanaged and unmanaged-to-managed stubs // for each method. - IncrementalValuesProvider generateStubInformation = methodsToGenerate + IncrementalValuesProvider generateStubInformation = methodsToGenerate .Combine(context.CreateStubEnvironmentProvider()) .Select(static (data, ct) => new { @@ -89,7 +89,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) 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 nativeToManagedStubContexts = + IncrementalValuesProvider nativeToManagedStubContexts = generateStubInformation .Where(data => data.VtableIndexData.Direction is MarshalDirection.UnmanagedToManaged or MarshalDirection.Bidirectional); @@ -195,7 +195,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) }; } - private static IncrementalMethodStubGenerationContext CalculateStubInformation(MethodDeclarationSyntax syntax, IMethodSymbol symbol, StubEnvironment environment, CancellationToken ct) + private static SourceAvailableIncrementalMethodStubGenerationContext CalculateStubInformation(MethodDeclarationSyntax syntax, IMethodSymbol symbol, StubEnvironment environment, CancellationToken ct) { ct.ThrowIfCancellationRequested(); INamedTypeSymbol? lcidConversionAttrType = environment.Compilation.GetTypeByMetadataName(TypeNames.LCIDConversionAttribute); @@ -306,7 +306,7 @@ private static IncrementalMethodStubGenerationContext CalculateStubInformation(M MarshallingInfo exceptionMarshallingInfo = CreateExceptionMarshallingInfo(virtualMethodIndexAttr, symbol, environment.Compilation, generatorDiagnostics, virtualMethodIndexData); - return new IncrementalMethodStubGenerationContext( + return new SourceAvailableIncrementalMethodStubGenerationContext( signatureContext, containingSyntaxContext, methodSyntaxTemplate, @@ -363,7 +363,7 @@ private static MarshallingInfo CreateExceptionMarshallingInfo(AttributeData virt } private static (MemberDeclarationSyntax, ImmutableArray) GenerateManagedToNativeStub( - IncrementalMethodStubGenerationContext methodStub) + SourceAvailableIncrementalMethodStubGenerationContext methodStub) { var (stub, diagnostics) = VirtualMethodPointerStubGenerator.GenerateManagedToNativeStub(methodStub, VtableIndexStubGeneratorHelpers.GetGeneratorResolver); @@ -376,7 +376,7 @@ private static (MemberDeclarationSyntax, ImmutableArray) Generat } private static (MemberDeclarationSyntax, ImmutableArray) GenerateNativeToManagedStub( - IncrementalMethodStubGenerationContext methodStub) + SourceAvailableIncrementalMethodStubGenerationContext methodStub) { var (stub, diagnostics) = VirtualMethodPointerStubGenerator.GenerateNativeToManagedStub(methodStub, VtableIndexStubGeneratorHelpers.GetGeneratorResolver); @@ -433,7 +433,7 @@ private static MemberDeclarationSyntax GenerateNativeInterfaceMetadata(Containin .AddAttributeLists(AttributeList(SingletonSeparatedList(Attribute(NameSyntaxes.System_Runtime_InteropServices_DynamicInterfaceCastableImplementationAttribute))))); } - private static MemberDeclarationSyntax GeneratePopulateVTableMethod(IGrouping vtableMethods) + private static MemberDeclarationSyntax GeneratePopulateVTableMethod(IGrouping vtableMethods) { ContainingSyntaxContext containingSyntax = vtableMethods.Key.AddContainingSyntax(NativeTypeContainingSyntax); diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/MethodSignatureDiagnosticLocations.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/MethodSignatureDiagnosticLocations.cs index 2705493f9155aa..f874103ec9e45d 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/MethodSignatureDiagnosticLocations.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/MethodSignatureDiagnosticLocations.cs @@ -42,6 +42,15 @@ public interface ISignatureDiagnosticLocations DiagnosticInfo CreateDiagnosticInfo(DiagnosticDescriptor descriptor, GeneratorDiagnostic diagnostic); } + public class NoneSignatureDiagnosticLocations : ISignatureDiagnosticLocations + { + public static readonly NoneSignatureDiagnosticLocations Instance = new(); + public DiagnosticInfo CreateDiagnosticInfo(DiagnosticDescriptor descriptor, GeneratorDiagnostic diagnostic) + { + return diagnostic.ToDiagnosticInfo(descriptor, Location.None, string.Empty); + } + } + public sealed record MethodSignatureDiagnosticLocations(string MethodIdentifier, ImmutableArray ManagedParameterLocations, Location FallbackLocation) : ISignatureDiagnosticLocations { public MethodSignatureDiagnosticLocations(MethodDeclarationSyntax syntax) diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypePositionInfo.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypePositionInfo.cs index f3b6b790ec4d49..14fa3a62d559ab 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypePositionInfo.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypePositionInfo.cs @@ -96,7 +96,7 @@ public static TypePositionInfo CreateForParameter(IParameterSymbol paramSymbol, ByValueContentsMarshalKind = byValueContentsMarshalKind, ByValueMarshalAttributeLocations = (inLocation, outLocation), ScopedKind = paramSymbol.ScopedKind, - IsExplicitThis = ((ParameterSyntax)paramSymbol.DeclaringSyntaxReferences[0].GetSyntax()).Modifiers.Any(SyntaxKind.ThisKeyword) + IsExplicitThis = ((ParameterSyntax?)paramSymbol.DeclaringSyntaxReferences.FirstOrDefault()?.GetSyntax())?.Modifiers.Any(SyntaxKind.ThisKeyword) ?? false }; return typeInfo; diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/ComInterfaceGenerator.Tests.csproj b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/ComInterfaceGenerator.Tests.csproj index 16016d184700d7..30ca8dd99aff38 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/ComInterfaceGenerator.Tests.csproj +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/ComInterfaceGenerator.Tests.csproj @@ -17,7 +17,7 @@ - + diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/CrossAssemblyInheritanceTests.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/CrossAssemblyInheritanceTests.cs new file mode 100644 index 00000000000000..14f916718fcd9d --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/CrossAssemblyInheritanceTests.cs @@ -0,0 +1,256 @@ +// 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.Linq; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; +using SharedTypes.ComInterfaces; +using Xunit; + +namespace ComInterfaceGenerator.Tests +{ + public partial class CrossAssemblyInheritanceTests + { + [GeneratedComClass] + [Guid("e0c6b35f-1234-4567-8901-123456789abc")] + internal partial class DerivedExternalBaseImpl : IDerivedExternalBase + { + private int _value = 10; + + public int GetInt() => _value; + public void SetInt(int x) => _value = x; + public string GetName() => "DerivedExternalBase"; + } + + [GeneratedComClass] + [Guid("e0c6b35f-1234-4567-8901-123456789abd")] + internal partial class DerivedExternalBase2Impl : IDerivedExternalBase2 + { + private int _value = 20; + + public int GetInt() => _value; + public void SetInt(int x) => _value = x; + public string GetName() => "DerivedExternalBase2"; + } + + [GeneratedComClass] + [Guid("e0c6b35f-1234-4567-8901-123456789abe")] + internal partial class DerivedFromExternalDerivedImpl : IDerivedFromExternalDerived + { + private int _value = 30; + private bool _boolValue = true; + + public int GetInt() => _value; + public void SetInt(int x) => _value = x; + public bool GetBool() => _boolValue; + public void SetBool(bool x) => _boolValue = x; + public string GetName() => "DerivedFromExternalDerived"; + } + + [GeneratedComClass] + [Guid("e0c6b35f-1234-4567-8901-123456789abf")] + internal partial class DerivedFromDerivedExternalDerivedImpl : IDerivedFromDerivedExternalDerived + { + private int _value = 40; + private bool _boolValue = false; + private float _floatValue = 3.14f; + + public int GetInt() => _value; + public void SetInt(int x) => _value = x; + public bool GetBool() => _boolValue; + public void SetBool(bool x) => _boolValue = x; + public string GetName() => "DerivedFromDerivedExternalDerived"; + public float GetFloat() => _floatValue; + } + + [Fact] + public void IDerivedExternalBase_CanCallMethods() + { + var implementation = new DerivedExternalBaseImpl(); + var comWrappers = new StrategyBasedComWrappers(); + var nativeObj = comWrappers.GetOrCreateComInterfaceForObject(implementation, CreateComInterfaceFlags.None); + var managedObj = comWrappers.GetOrCreateObjectForComInstance(nativeObj, CreateObjectFlags.None); + + var externalBase = (IExternalBase)managedObj; + Assert.Equal(10, externalBase.GetInt()); + externalBase.SetInt(15); + Assert.Equal(15, externalBase.GetInt()); + + var derivedExternalBase = (IDerivedExternalBase)managedObj; + Assert.Equal(15, derivedExternalBase.GetInt()); + Assert.Equal("DerivedExternalBase", derivedExternalBase.GetName()); + } + + [Fact] + public void IDerivedExternalBase2_CanCallMethods() + { + var implementation = new DerivedExternalBase2Impl(); + var comWrappers = new StrategyBasedComWrappers(); + var nativeObj = comWrappers.GetOrCreateComInterfaceForObject(implementation, CreateComInterfaceFlags.None); + var managedObj = comWrappers.GetOrCreateObjectForComInstance(nativeObj, CreateObjectFlags.None); + + // Test as base interface + var externalBase = (IExternalBase)managedObj; + Assert.Equal(20, externalBase.GetInt()); + externalBase.SetInt(25); + Assert.Equal(25, externalBase.GetInt()); + + // Test as derived interface + var derivedExternalBase2 = (IDerivedExternalBase2)managedObj; + Assert.Equal(25, derivedExternalBase2.GetInt()); + Assert.Equal("DerivedExternalBase2", derivedExternalBase2.GetName()); + } + + [Fact] + public void IDerivedFromExternalDerived_CanCallMethods() + { + var implementation = new DerivedFromExternalDerivedImpl(); + var comWrappers = new StrategyBasedComWrappers(); + var nativeObj = comWrappers.GetOrCreateComInterfaceForObject(implementation, CreateComInterfaceFlags.None); + var managedObj = comWrappers.GetOrCreateObjectForComInstance(nativeObj, CreateObjectFlags.None); + + var externalBase = (IExternalBase)managedObj; + Assert.Equal(30, externalBase.GetInt()); + externalBase.SetInt(35); + Assert.Equal(35, externalBase.GetInt()); + + var externalDerived = (IExternalDerived)managedObj; + Assert.Equal(35, externalDerived.GetInt()); + Assert.True(externalDerived.GetBool()); + externalDerived.SetBool(false); + Assert.False(externalDerived.GetBool()); + + var derivedFromExternalDerived = (IDerivedFromExternalDerived)managedObj; + Assert.Equal(35, derivedFromExternalDerived.GetInt()); + Assert.False(derivedFromExternalDerived.GetBool()); + Assert.Equal("DerivedFromExternalDerived", derivedFromExternalDerived.GetName()); + } + + [Fact] + public void IDerivedFromDerivedExternalDerived_CanCallMethods() + { + var implementation = new DerivedFromDerivedExternalDerivedImpl(); + var comWrappers = new StrategyBasedComWrappers(); + var nativeObj = comWrappers.GetOrCreateComInterfaceForObject(implementation, CreateComInterfaceFlags.None); + var managedObj = comWrappers.GetOrCreateObjectForComInstance(nativeObj, CreateObjectFlags.None); + + var externalBase = (IExternalBase)managedObj; + Assert.Equal(40, externalBase.GetInt()); + externalBase.SetInt(45); + Assert.Equal(45, externalBase.GetInt()); + + var externalDerived = (IExternalDerived)managedObj; + Assert.Equal(45, externalDerived.GetInt()); + Assert.False(externalDerived.GetBool()); + externalDerived.SetBool(true); + Assert.True(externalDerived.GetBool()); + + var derivedFromExternalDerived = (IDerivedFromExternalDerived)managedObj; + Assert.Equal(45, derivedFromExternalDerived.GetInt()); + Assert.True(derivedFromExternalDerived.GetBool()); + Assert.Equal("DerivedFromDerivedExternalDerived", derivedFromExternalDerived.GetName()); + + var derivedFromDerivedExternalDerived = (IDerivedFromDerivedExternalDerived)managedObj; + Assert.Equal(45, derivedFromDerivedExternalDerived.GetInt()); + Assert.True(derivedFromDerivedExternalDerived.GetBool()); + Assert.Equal("DerivedFromDerivedExternalDerived", derivedFromDerivedExternalDerived.GetName()); + Assert.Equal(3.14f, derivedFromDerivedExternalDerived.GetFloat()); + } + + [Fact] + public unsafe void MultipleInterfacesDerivedFromSameBase_ShareCommonVTableLayout() + { + IIUnknownDerivedDetails baseDetails = StrategyBasedComWrappers.DefaultIUnknownInterfaceDetailsStrategy + .GetIUnknownDerivedDetails(typeof(IExternalBase).TypeHandle); + + IIUnknownDerivedDetails derived1Details = StrategyBasedComWrappers.DefaultIUnknownInterfaceDetailsStrategy + .GetIUnknownDerivedDetails(typeof(IDerivedExternalBase).TypeHandle); + + IIUnknownDerivedDetails derived2Details = StrategyBasedComWrappers.DefaultIUnknownInterfaceDetailsStrategy + .GetIUnknownDerivedDetails(typeof(IDerivedExternalBase2).TypeHandle); + + var numBaseMethods = typeof(IExternalBase).GetMethods().Length; + var numPointersToCompare = 3 + numBaseMethods; // IUnknown (3) + base methods + + // Both derived interfaces should have the same base vtable layout + var baseVTable = new ReadOnlySpan(baseDetails.ManagedVirtualMethodTable, numPointersToCompare); + var derived1BaseVTable = new ReadOnlySpan(derived1Details.ManagedVirtualMethodTable, numPointersToCompare); + var derived2BaseVTable = new ReadOnlySpan(derived2Details.ManagedVirtualMethodTable, numPointersToCompare); + + Assert.True(baseVTable.SequenceEqual(derived1BaseVTable), + "IDerivedExternalBase should have consistent base vtable layout"); + Assert.True(baseVTable.SequenceEqual(derived2BaseVTable), + "IDerivedExternalBase2 should have consistent base vtable layout"); + Assert.True(derived1BaseVTable.SequenceEqual(derived2BaseVTable), + "Both derived interfaces should have identical base vtable layouts"); + } + + [Fact] + public unsafe void CrossAssemblyInheritance_VTableLayoutIsCorrect() + { + IIUnknownDerivedDetails baseInterfaceDetails = StrategyBasedComWrappers.DefaultIUnknownInterfaceDetailsStrategy + .GetIUnknownDerivedDetails(typeof(IExternalBase).TypeHandle); + + IIUnknownDerivedDetails derivedInterfaceDetails = StrategyBasedComWrappers.DefaultIUnknownInterfaceDetailsStrategy + .GetIUnknownDerivedDetails(typeof(IDerivedExternalBase).TypeHandle); + + var numBaseMethods = typeof(IExternalBase).GetMethods().Length; + var numPointersToCompare = 3 + numBaseMethods; + + // The first part of the vtable should match between base and derived + var expectedBaseVTable = new ReadOnlySpan(baseInterfaceDetails.ManagedVirtualMethodTable, numPointersToCompare); + var actualDerivedVTable = new ReadOnlySpan(derivedInterfaceDetails.ManagedVirtualMethodTable, numPointersToCompare); + + Assert.True(expectedBaseVTable.SequenceEqual(actualDerivedVTable), + "Base interface methods should have the same vtable entries in derived interface"); + } + + [Fact] + public unsafe void IDerivedFromDerivedExternalDerived_VTableLayoutIsCorrect() + { + var baseDetails = StrategyBasedComWrappers.DefaultIUnknownInterfaceDetailsStrategy + .GetIUnknownDerivedDetails(typeof(IExternalBase).TypeHandle); + var externalDerivedDetails = StrategyBasedComWrappers.DefaultIUnknownInterfaceDetailsStrategy + .GetIUnknownDerivedDetails(typeof(IExternalDerived).TypeHandle); + var derivedFromExternalDerivedDetails = StrategyBasedComWrappers.DefaultIUnknownInterfaceDetailsStrategy + .GetIUnknownDerivedDetails(typeof(IDerivedFromExternalDerived).TypeHandle); + var deepDerivedDetails = StrategyBasedComWrappers.DefaultIUnknownInterfaceDetailsStrategy + .GetIUnknownDerivedDetails(typeof(IDerivedFromDerivedExternalDerived).TypeHandle); + + var baseMethods = typeof(IExternalBase).GetMethods().Length; + var baseVTableSize = 3 + baseMethods; + + var baseVTable = new ReadOnlySpan(baseDetails.ManagedVirtualMethodTable, baseVTableSize); + var externalDerivedBaseVTable = new ReadOnlySpan(externalDerivedDetails.ManagedVirtualMethodTable, baseVTableSize); + var derivedFromExternalDerivedBaseVTable = new ReadOnlySpan(derivedFromExternalDerivedDetails.ManagedVirtualMethodTable, baseVTableSize); + var deepDerivedBaseVTable = new ReadOnlySpan(deepDerivedDetails.ManagedVirtualMethodTable, baseVTableSize); + + Assert.True(baseVTable.SequenceEqual(externalDerivedBaseVTable), + "IExternalDerived should have consistent base vtable layout"); + Assert.True(baseVTable.SequenceEqual(derivedFromExternalDerivedBaseVTable), + "IDerivedFromExternalDerived should have consistent base vtable layout"); + Assert.True(baseVTable.SequenceEqual(deepDerivedBaseVTable), + "IDerivedFromDerivedExternalDerived should have consistent base vtable layout"); + + var externalDerivedMethods = typeof(IExternalDerived).GetMethods().Length; + var externalDerivedVTableSize = 3 + externalDerivedMethods; + + var externalDerivedVTable = new ReadOnlySpan(externalDerivedDetails.ManagedVirtualMethodTable, externalDerivedVTableSize); + var derivedFromExternalDerivedIntermediateVTable = new ReadOnlySpan(derivedFromExternalDerivedDetails.ManagedVirtualMethodTable, externalDerivedVTableSize); + var deepDerivedIntermediateVTable = new ReadOnlySpan(deepDerivedDetails.ManagedVirtualMethodTable, externalDerivedVTableSize); + + Assert.True(externalDerivedVTable.SequenceEqual(derivedFromExternalDerivedIntermediateVTable), + "IDerivedFromExternalDerived should have consistent IExternalDerived vtable layout"); + Assert.True(externalDerivedVTable.SequenceEqual(deepDerivedIntermediateVTable), + "IDerivedFromDerivedExternalDerived should have consistent IExternalDerived vtable layout"); + + var derivedFromExternalDerivedMethods = typeof(IDerivedFromExternalDerived).GetMethods().Length; + var derivedFromExternalDerivedVTableSize = 3 + derivedFromExternalDerivedMethods; + var derivedFromExternalDerivedVTable = new ReadOnlySpan(derivedFromExternalDerivedDetails.ManagedVirtualMethodTable, derivedFromExternalDerivedVTableSize); + var deepDerivedVTable = new ReadOnlySpan(deepDerivedDetails.ManagedVirtualMethodTable, derivedFromExternalDerivedVTableSize); + Assert.True(derivedFromExternalDerivedVTable.SequenceEqual(deepDerivedVTable), + "IDerivedFromDerivedExternalDerived should have consistent IDerivedFromExternalDerived vtable layout"); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/IDerivedTests.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/IDerivedTests.cs index e457a287748bc3..476db4b2cdd285 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/IDerivedTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/IDerivedTests.cs @@ -13,6 +13,56 @@ namespace ComInterfaceGenerator.Tests { public partial class IDerivedTests { + [GeneratedComInterface] + [Guid("7F0DB364-3C04-4487-9193-4BB05DC7B654")] + internal partial interface IDerivedFromSharedType2 : SharedTypes.ComInterfaces.IGetAndSetInt + { + int GetTwoTimesInt(); + } + + [GeneratedComInterface] + [Guid("7F0DB364-3C04-4487-9194-4BB05DC7B654")] +#pragma warning disable SYSLIB1230 // Specifying 'GeneratedComInterfaceAttribute' on an interface that has a base interface defined in another assembly is not supported + internal partial interface IDerivedFromSharedType : SharedTypes.ComInterfaces.IGetAndSetInt +#pragma warning restore SYSLIB1230 + { + int GetIntPlusOne(); + } + + [GeneratedComClass] + [Guid("7F0DB364-3C04-4487-9195-4BB05DC7B654")] + internal partial class DerivedFromSharedTypeImpl : IDerivedFromSharedType, IDerivedFromSharedType2 + { + int _value = 42; + + public int GetInt() => _value; + public int GetIntPlusOne() => _value + 1; + public int GetTwoTimesInt() => _value * 2; + public void SetInt(int value) { _value = value; } + } + + [Fact] + public unsafe void TypesDerivedFromSharedTypeHaveCorrectVTableSize() + { + var managedSourceObject = new DerivedFromSharedTypeImpl(); + var cw = new StrategyBasedComWrappers(); + var nativeObj = cw.GetOrCreateComInterfaceForObject(managedSourceObject, CreateComInterfaceFlags.None); + object managedObj = cw.GetOrCreateObjectForComInstance(nativeObj, CreateObjectFlags.None); + IGetAndSetInt getAndSetInt = (IGetAndSetInt)managedObj; + IDerivedFromSharedType derivedFromSharedType = (IDerivedFromSharedType)managedObj; + IDerivedFromSharedType2 derivedFromSharedType2 = (IDerivedFromSharedType2)managedObj; + + Assert.Equal(42, getAndSetInt.GetInt()); + Assert.Equal(42, derivedFromSharedType.GetInt()); + Assert.Equal(42, derivedFromSharedType2.GetInt()); + + getAndSetInt.SetInt(100); + Assert.Equal(100, getAndSetInt.GetInt()); + Assert.Equal(101, derivedFromSharedType.GetIntPlusOne()); + Assert.Equal(200, derivedFromSharedType2.GetTwoTimesInt()); + } + + [Fact] public unsafe void DerivedInterfaceTypeProvidesBaseInterfaceUnmanagedToManagedMembers() { @@ -36,16 +86,16 @@ public unsafe void DerivedInterfaceTypeProvidesBaseInterfaceUnmanagedToManagedMe public unsafe void CallBaseInterfaceMethod_EnsureQiCalledOnce() { var cw = new SingleQIComWrapper(); - var derivedImpl = new DerivedImpl(); + var derivedImpl = new Derived(); var nativeObj = cw.GetOrCreateComInterfaceForObject(derivedImpl, CreateComInterfaceFlags.None); var obj = cw.GetOrCreateObjectForComInstance(nativeObj, CreateObjectFlags.None); IDerived iface = (IDerived)obj; - Assert.Equal(3, iface.GetInt()); + Assert.Equal(0, iface.GetInt()); iface.SetInt(5); Assert.Equal(5, iface.GetInt()); - Assert.Equal("myName", iface.GetName()); + Assert.Equal("hello", iface.GetName()); iface.SetName("updated"); Assert.Equal("updated", iface.GetName()); @@ -58,22 +108,6 @@ public unsafe void CallBaseInterfaceMethod_EnsureQiCalledOnce() Assert.Equal(1, countQi.QiCallCount); } - [GeneratedComClass] - partial class DerivedImpl : IDerived - { - int data = 3; - string myName = "myName"; - public void DoThingWithString(string name) => throw new NotImplementedException(); - - public int GetInt() => data; - - public string GetName() => myName; - - public void SetInt(int n) => data = n; - - public void SetName(string name) => myName = name; - } - /// /// Used to ensure that QI is only called once when calling base methods on a derived COM interface /// diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/Interfaces/IDerivedAcrossAssembly.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/Interfaces/IDerivedAcrossAssembly.cs new file mode 100644 index 00000000000000..89db66843c4dc9 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/Interfaces/IDerivedAcrossAssembly.cs @@ -0,0 +1,24 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; +using SharedTypes.ComInterfaces; + +[GeneratedComInterface(StringMarshalling = StringMarshalling.Utf16)] +[Guid("da8eed10-f3f4-42c3-86de-04f2dc56514e")] +#pragma warning disable SYSLIB1230 // Specifying 'GeneratedComInterfaceAttribute' on an interface that has a base interface defined in another assembly is not supported +internal partial interface IDerivedExternalBase : IExternalBase +#pragma warning restore SYSLIB1230 +{ + string GetName(); +} + +[GeneratedComInterface(StringMarshalling = StringMarshalling.Utf16)] +[Guid("c3d3990e-5b05-4a9b-adc4-58c521700ece")] +#pragma warning disable SYSLIB1230 // Specifying 'GeneratedComInterfaceAttribute' on an interface that has a base interface defined in another assembly is not supported +internal partial interface IDerivedExternalBase2 : IExternalBase +#pragma warning restore SYSLIB1230 +{ + string GetName(); +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/Interfaces/IDerivedFromDerivedAcrossAssembly.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/Interfaces/IDerivedFromDerivedAcrossAssembly.cs new file mode 100644 index 00000000000000..e28b68bd4cc033 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/Interfaces/IDerivedFromDerivedAcrossAssembly.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; +using SharedTypes.ComInterfaces; + +[GeneratedComInterface(StringMarshalling = StringMarshalling.Utf16)] +[Guid("f252bddd-aac0-4004-acfd-b39f73fb9791")] +#pragma warning disable SYSLIB1230 // Specifying 'GeneratedComInterfaceAttribute' on an interface that has a base interface defined in another assembly is not supported +internal partial interface IDerivedFromExternalDerived : IExternalDerived +#pragma warning restore SYSLIB1230 +{ + string GetName(); +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/Interfaces/IDerivedFromDerivedExternalDerived.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/Interfaces/IDerivedFromDerivedExternalDerived.cs new file mode 100644 index 00000000000000..5cd88d06b2a93f --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/Interfaces/IDerivedFromDerivedExternalDerived.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; +using SharedTypes.ComInterfaces; + +[GeneratedComInterface(StringMarshalling = StringMarshalling.Utf16)] +[Guid("b158aaf2-85a3-40e7-805f-5797580a05f2")] +#pragma warning disable SYSLIB1230 // Specifying 'GeneratedComInterfaceAttribute' on an interface that has a base interface defined in another assembly is not supported +internal partial interface IDerivedFromDerivedExternalDerived : IDerivedFromExternalDerived +#pragma warning restore SYSLIB1230 +{ + float GetFloat(); +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/TargetSignatureTests.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/TargetSignatureTests.cs index 7c0ead99ba5f44..ea4c4c5904a2f2 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/TargetSignatureTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/TargetSignatureTests.cs @@ -8,8 +8,10 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Operations; using Microsoft.CodeAnalysis.Testing; +using Microsoft.CodeAnalysis.Text; using Microsoft.Interop; using Xunit; @@ -317,7 +319,7 @@ public partial interface IComInterface using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.InteropServices.Marshalling; - + [GeneratedComInterface] [Guid("0A617667-4961-4F90-B74F-6DC368E9817A")] partial interface {|#1:IComInterface2|} : IComInterface @@ -342,6 +344,74 @@ await VerifyInvocationWithMultipleProjectsAsync( VerifyCS.DiagnosticWithArguments(GeneratorDiagnostics.BaseInterfaceDefinedInOtherAssembly, "IComInterface2", "IComInterface").WithLocation(1).WithSeverity(DiagnosticSeverity.Warning)); } + [Fact] + public async Task ComInterfacesInheritingFromTheSameInterfaceAcrossCompilationsCalculatesCorrectVTableIndex() + { + string baseSource = $$""" + using System.Runtime.CompilerServices; + using System.Runtime.InteropServices; + using System.Runtime.InteropServices.Marshalling; + + [GeneratedComInterface] + [Guid("0A617667-4961-4F90-B74F-6DC368E98179")] + public partial interface IComInterface + { + void Method(); + } + """; + + string derivedSource = $$""" + using System.Runtime.CompilerServices; + using System.Runtime.InteropServices; + using System.Runtime.InteropServices.Marshalling; + + [GeneratedComInterface] + [Guid("0A617667-4961-4F90-B74F-6DC368E9817A")] + internal partial interface {|#1:IComInterface2|} : IComInterface + { + void DerivedMethod(); + } + + [GeneratedComInterface] + [Guid("0951f7b7-a700-4de4-930e-0b1fbc4684a9")] + internal partial interface {|#2:IComInterface3|} : IComInterface + { + void DerivedMethod(); + } + """; + + await VerifyInvocationWithMultipleProjectsAsync( + derivedSource, + baseSource, + "IComInterface2", + "DerivedMethod", + (newComp, _) => + { + // Validate VTable sizes for interfaces inheriting from the same base + // IUnknown has 3 methods, IComInterface adds 1 method = 4 total + // Both IComInterface2 and IComInterface3 inherit from IComInterface and add 1 method each = 5 total + ValidateInterface("IComInterface2", 5); + ValidateInterface("IComInterface3", 5); + + void ValidateInterface(string name, int expectedVTableSize) + { + INamedTypeSymbol? userDefinedInterface = newComp.Assembly.GetTypeByMetadataName(name); + Assert.NotNull(userDefinedInterface); + ITypeSymbol vtableType = new ComInterfaceImplementationLocator().FindVTableStructType(newComp, userDefinedInterface); + int actualVTableSize = vtableType.GetMembers().OfType().Count(); + + if (expectedVTableSize != actualVTableSize) + { + Assert.Fail($"VTable size mismatch for {name}. Expected: {expectedVTableSize}, Actual: {actualVTableSize}. VTable structure:\n{vtableType.DeclaringSyntaxReferences[0].GetSyntax().SyntaxTree.GetText()}"); + } + + Assert.Equal(expectedVTableSize, actualVTableSize); + } + }, + VerifyCS.DiagnosticWithArguments(GeneratorDiagnostics.BaseInterfaceDefinedInOtherAssembly, "IComInterface2", "IComInterface").WithLocation(1).WithSeverity(DiagnosticSeverity.Warning), + VerifyCS.DiagnosticWithArguments(GeneratorDiagnostics.BaseInterfaceDefinedInOtherAssembly, "IComInterface3", "IComInterface").WithLocation(2).WithSeverity(DiagnosticSeverity.Warning)); + } + [Fact] public async Task ComInterfaceInheritingAcrossCompilationsChainInBaseCalculatesCorrectVTableIndex() { @@ -369,7 +439,7 @@ public partial interface IComInterface2 : IComInterface using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.InteropServices.Marshalling; - + [GeneratedComInterface] [Guid("0A617667-4961-4F90-B74F-6DC368E9817A")] partial interface {|#1:IComInterface3|} : IComInterface2 @@ -446,6 +516,84 @@ await VerifyInvocationWithMultipleProjectsAsync( VerifyCS.DiagnosticWithArguments(GeneratorDiagnostics.BaseInterfaceDefinedInOtherAssembly, "IComInterface2", "IComInterface").WithLocation(1).WithSeverity(DiagnosticSeverity.Warning)); } + [Fact] + public async Task ComInterfaceDeepInheritanceChainCalculatesCorrectVTableSizes() + { + string baseSource = $$""" + using System.Runtime.CompilerServices; + using System.Runtime.InteropServices; + using System.Runtime.InteropServices.Marshalling; + + [GeneratedComInterface] + [Guid("0A617667-4961-4F90-B74F-6DC368E98179")] + public partial interface IComInterface + { + void BaseMethod(); + } + + [GeneratedComInterface] + [Guid("0A617667-4961-4F90-B74F-6DC368E98178")] + public partial interface IComInterface2 : IComInterface + { + void MiddleMethod(); + } + """; + + string derivedSource = $$""" + using System.Runtime.CompilerServices; + using System.Runtime.InteropServices; + using System.Runtime.InteropServices.Marshalling; + + [GeneratedComInterface] + [Guid("0A617667-4961-4F90-B74F-6DC368E9817A")] + partial interface {|#1:IComInterface3|} : IComInterface2 + { + void DerivedMethod(); + } + + [GeneratedComInterface] + [Guid("0A617667-4961-4F90-B74F-6DC368E9817B")] + partial interface IComInterface4 : IComInterface3 + { + void DeepDerivedMethod(); + } + """; + + await VerifyInvocationWithMultipleProjectsAsync( + derivedSource, + baseSource, + "IComInterface4", + "DeepDerivedMethod", + (newComp, _) => + { + // Validate VTable sizes for deep inheritance chain + // IUnknown has 3 methods (QueryInterface=0, AddRef=1, Release=2) + // IComInterface: IUnknown (3) + BaseMethod (1) = 4 total + // IComInterface2: IComInterface (4) + MiddleMethod (1) = 5 total + // IComInterface3: IComInterface2 (5) + DerivedMethod (1) = 6 total + // IComInterface4: IComInterface3 (6) + DeepDerivedMethod (1) = 7 total + + ValidateInterface("IComInterface3", 6); + ValidateInterface("IComInterface4", 7); + + void ValidateInterface(string name, int expectedVTableSize) + { + INamedTypeSymbol? userDefinedInterface = newComp.Assembly.GetTypeByMetadataName(name); + Assert.NotNull(userDefinedInterface); + ITypeSymbol vtableType = new ComInterfaceImplementationLocator().FindVTableStructType(newComp, userDefinedInterface); + int actualVTableSize = vtableType.GetMembers().OfType().Count(); + + if (expectedVTableSize != actualVTableSize) + { + Assert.Fail($"VTable size mismatch for {name}. Expected: {expectedVTableSize}, Actual: {actualVTableSize}. VTable structure:\n{vtableType.DeclaringSyntaxReferences[0].GetSyntax().SyntaxTree.GetText()}"); + } + + Assert.Equal(expectedVTableSize, actualVTableSize); + } + }, + VerifyCS.DiagnosticWithArguments(GeneratorDiagnostics.BaseInterfaceDefinedInOtherAssembly, "IComInterface3", "IComInterface2").WithLocation(1).WithSeverity(DiagnosticSeverity.Warning)); + } + private static async Task VerifyInvocationWithMultipleProjectsAsync( string thisSource, string baseSource, @@ -581,6 +729,14 @@ public INamedTypeSymbol FindImplementationInterface(Compilation compilation, INa return (INamedTypeSymbol)iUnknownDerivedAttribute.AttributeClass!.TypeArguments[1]; } + + public ITypeSymbol FindVTableStructType(Compilation compilation, INamedTypeSymbol userDefinedInterface) + { + INamedTypeSymbol? implementationInterface = FindImplementationInterface(compilation, userDefinedInterface); + var vtableField = implementationInterface.GetMembers("Vtable").OfType().SingleOrDefault(); + Assert.NotNull(vtableField); + return vtableField.Type; + } } } } diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IArrayOfStatelessElements.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IArrayOfStatelessElements.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IArrayOfStatelessElements.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IArrayOfStatelessElements.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IBool.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IBool.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IBool.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IBool.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/ICustomStringMarshallingUtf16.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/ICustomStringMarshallingUtf16.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/ICustomStringMarshallingUtf16.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/ICustomStringMarshallingUtf16.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IDerived.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IDerived.cs similarity index 73% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IDerived.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IDerived.cs index f6cd4ff8afc55b..50ee6fbe2c2add 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IDerived.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IDerived.cs @@ -18,6 +18,15 @@ internal partial interface IDerived : IGetAndSetInt internal new const string IID = "7F0DB364-3C04-4487-9193-4BB05DC7B654"; } + [GeneratedComInterface] + [Guid("D38D8B40-54A4-4685-B048-D04E215E6A93")] + internal partial interface IDerivedBool : IBool + { + void SetName([MarshalUsing(typeof(Utf16StringMarshaller))] string name); + + [return: MarshalUsing(typeof(Utf16StringMarshaller))] + string GetName(); + } [GeneratedComClass] internal partial class Derived : GetAndSetInt, IDerived diff --git a/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IDerivedDerived.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IDerivedDerived.cs new file mode 100644 index 00000000000000..d5b6d4ee4850d9 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IDerivedDerived.cs @@ -0,0 +1,28 @@ +// 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.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; + +namespace SharedTypes.ComInterfaces +{ + [GeneratedComInterface] + [Guid(IID)] + internal partial interface IDerivedDerived : IDerived + { + void SetFloat(float name); + + float GetFloat(); + + internal new const string IID = "7F0DB364-3C04-4487-9193-4BB05DC7B654"; + } + + [GeneratedComClass] + internal partial class DerivedDerived : Derived, IDerivedDerived + { + float _data = 0; + public float GetFloat() => _data; + public void SetFloat(float name) => _data = name; + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IEmpty.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IEmpty.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IEmpty.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IEmpty.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IEnumUnknown.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IEnumUnknown.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IEnumUnknown.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IEnumUnknown.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IFloat.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IFloat.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IFloat.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IFloat.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IGetAndSetInt.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IGetAndSetInt.cs similarity index 99% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IGetAndSetInt.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IGetAndSetInt.cs index 3f1b18f34e9beb..42dbca1c0adbd4 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IGetAndSetInt.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IGetAndSetInt.cs @@ -17,6 +17,7 @@ internal partial interface IGetAndSetInt public const string IID = "2c3f9903-b586-46b1-881b-adfce9af47b1"; } + [GeneratedComClass] internal partial class GetAndSetInt : IGetAndSetInt { diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IGetIntArray.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IGetIntArray.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IGetIntArray.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IGetIntArray.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IHide.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IHide.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IHide.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IHide.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IInt.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IInt.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IInt.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IInt.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IIntArray.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IIntArray.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IIntArray.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IIntArray.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IInterface.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IInterface.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IInterface.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IInterface.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IJaggedIntArray.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IJaggedIntArray.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IJaggedIntArray.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IJaggedIntArray.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IPointProvider.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IPointProvider.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IPointProvider.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IPointProvider.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IRefStrings.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IRefStrings.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IRefStrings.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IRefStrings.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/ISafeHandles.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/ISafeHandles.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/ISafeHandles.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/ISafeHandles.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulAllShapes.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStatefulAllShapes.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulAllShapes.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStatefulAllShapes.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulCallerAllocatedBuffer.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStatefulCallerAllocatedBuffer.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulCallerAllocatedBuffer.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStatefulCallerAllocatedBuffer.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulCollectionAllShapes.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStatefulCollectionAllShapes.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulCollectionAllShapes.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStatefulCollectionAllShapes.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulCollectionBlittableElement.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStatefulCollectionBlittableElement.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulCollectionBlittableElement.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStatefulCollectionBlittableElement.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulCollectionPinnableReference.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStatefulCollectionPinnableReference.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulCollectionPinnableReference.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStatefulCollectionPinnableReference.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulCollectionStatelessElement.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStatefulCollectionStatelessElement.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulCollectionStatelessElement.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStatefulCollectionStatelessElement.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulFinallyMarshalling.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStatefulFinallyMarshalling.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulFinallyMarshalling.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStatefulFinallyMarshalling.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulMarshalling.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStatefulMarshalling.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulMarshalling.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStatefulMarshalling.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulPinnedMarshalling.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStatefulPinnedMarshalling.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatefulPinnedMarshalling.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStatefulPinnedMarshalling.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessAllShapes.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStatelessAllShapes.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessAllShapes.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStatelessAllShapes.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessCallerAllocateBufferMarshalling.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStatelessCallerAllocateBufferMarshalling.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessCallerAllocateBufferMarshalling.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStatelessCallerAllocateBufferMarshalling.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessCollectionAllShapes.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStatelessCollectionAllShapes.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessCollectionAllShapes.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStatelessCollectionAllShapes.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessCollectionBlittableElement.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStatelessCollectionBlittableElement.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessCollectionBlittableElement.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStatelessCollectionBlittableElement.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessCollectionCallerAllocatedBuffer.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStatelessCollectionCallerAllocatedBuffer.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessCollectionCallerAllocatedBuffer.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStatelessCollectionCallerAllocatedBuffer.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessCollectionPinnableReference.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStatelessCollectionPinnableReference.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessCollectionPinnableReference.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStatelessCollectionPinnableReference.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessCollectionStatelessElement.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStatelessCollectionStatelessElement.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessCollectionStatelessElement.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStatelessCollectionStatelessElement.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessFinallyMarshalling.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStatelessFinallyMarshalling.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessFinallyMarshalling.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStatelessFinallyMarshalling.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessMarshalling.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStatelessMarshalling.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessMarshalling.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStatelessMarshalling.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessPinnableCollectionBlittableElements.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStatelessPinnableCollectionBlittableElements.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessPinnableCollectionBlittableElements.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStatelessPinnableCollectionBlittableElements.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessPinnedMarshalling.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStatelessPinnedMarshalling.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStatelessPinnedMarshalling.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStatelessPinnedMarshalling.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStringMarshallingOverride.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStringMarshallingOverride.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStringMarshallingOverride.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStringMarshallingOverride.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStringMarshallingOverrideDerived.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStringMarshallingOverrideDerived.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStringMarshallingOverrideDerived.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IStringMarshallingOverrideDerived.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/ISystem.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/ISystem.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/ISystem.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/ISystem.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IUTF16Marshalling.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IUTF16Marshalling.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IUTF16Marshalling.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IUTF16Marshalling.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IUTF8Marshalling.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IUTF8Marshalling.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IUTF8Marshalling.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/IUTF8Marshalling.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/ManagedComMethodFailureException.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/ManagedComMethodFailureException.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/ManagedComMethodFailureException.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/ManagedComMethodFailureException.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/MarshallingFails/ICollectionMarshallingFails.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/MarshallingFails/ICollectionMarshallingFails.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/MarshallingFails/ICollectionMarshallingFails.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/MarshallingFails/ICollectionMarshallingFails.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/MarshallingFails/IJaggedIntArrayMarshallingFails.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/MarshallingFails/IJaggedIntArrayMarshallingFails.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/MarshallingFails/IJaggedIntArrayMarshallingFails.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/MarshallingFails/IJaggedIntArrayMarshallingFails.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/MarshallingFails/IStringArrayMarshallingFails.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/MarshallingFails/IStringArrayMarshallingFails.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/MarshallingFails/IStringArrayMarshallingFails.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/MarshallingFails/IStringArrayMarshallingFails.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/MarshallingFails/ISupportErrorInfo.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/MarshallingFails/ISupportErrorInfo.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/MarshallingFails/ISupportErrorInfo.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/MarshallingFails/ISupportErrorInfo.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/MarshallingFails/MarshallingFailureException.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/MarshallingFails/MarshallingFailureException.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/MarshallingFails/MarshallingFailureException.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/MarshallingFails/MarshallingFailureException.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/MarshallingFails/ThrowOn4thElementMarshalled.cs b/src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/MarshallingFails/ThrowOn4thElementMarshalled.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/MarshallingFails/ThrowOn4thElementMarshalled.cs rename to src/libraries/System.Runtime.InteropServices/tests/Common/ComInterfaces/MarshallingFails/ThrowOn4thElementMarshalled.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/NativeExports.csproj b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/NativeExports.csproj index 5f4996e2f699af..f34b39521b7ac5 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/NativeExports.csproj +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/NativeExports.csproj @@ -20,7 +20,7 @@ - + diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/BaseInterfaces/IBaseDifferentAssembly.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/BaseInterfaces/IBaseDifferentAssembly.cs new file mode 100644 index 00000000000000..0a02d9e1c6bc1b --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/BaseInterfaces/IBaseDifferentAssembly.cs @@ -0,0 +1,18 @@ +// 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.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; + +namespace SharedTypes.ComInterfaces +{ + [GeneratedComInterface] + [Guid(IID)] + public partial interface IExternalBase + { + public int GetInt(); + public void SetInt(int x); + public const string IID = "2c3f9903-b586-46b1-881b-adfce9af47b1"; + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/BaseInterfaces/IDerivedDifferentAssembly.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/BaseInterfaces/IDerivedDifferentAssembly.cs new file mode 100644 index 00000000000000..bb3d6b431b3210 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/BaseInterfaces/IDerivedDifferentAssembly.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 System; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; + +namespace SharedTypes.ComInterfaces +{ + [GeneratedComInterface] + [Guid(IID)] + public partial interface IExternalDerived : IExternalBase + { + [return: MarshalAs(UnmanagedType.Bool)] + bool GetBool(); + public void SetBool([MarshalAs(UnmanagedType.Bool)] bool x); + new public const string IID = "594DF2B9-66CE-490D-9D05-34646675B188"; + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/SharedTypes.csproj b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/SharedTypes.csproj index 790a5e3f05a366..c68eadac7ca4b4 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/SharedTypes.csproj +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/SharedTypes.csproj @@ -11,8 +11,6 @@ - -