Skip to content

Commit

Permalink
[ComInterfaceGenerator] Fix StringMarshalling error message and actua…
Browse files Browse the repository at this point in the history
…lly copy attributes from methods to shadows (#86731)


Co-authored-by: Jeremy Koritzinsky <[email protected]>
  • Loading branch information
jtschuster and jkoritzinsky authored May 26, 2023
1 parent 87d6bba commit 4177d2d
Show file tree
Hide file tree
Showing 23 changed files with 73 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ internal static class ComInterfaceGeneratorHelpers
// If we're in a "supported" scenario, then emit a diagnostic as our final fallback.
generatorFactory = new UnsupportedMarshallingFactory();

generatorFactory = new NoMarshallingInfoErrorMarshallingFactory(generatorFactory);
generatorFactory = new NoMarshallingInfoErrorMarshallingFactory(generatorFactory, TypeNames.GeneratedComInterfaceAttribute_ShortName);

// The presence of System.Runtime.CompilerServices.DisableRuntimeMarshallingAttribute is tied to TFM,
// so we use TFM in the generator factory key instead of the Compilation as the compilation changes on every keystroke.
Expand All @@ -27,15 +27,15 @@ internal static class ComInterfaceGeneratorHelpers

// Since the char type can go into the P/Invoke signature here, we can only use it when
// runtime marshalling is disabled.
generatorFactory = new CharMarshallingGeneratorFactory(generatorFactory, useBlittableMarshallerForUtf16: runtimeMarshallingDisabled);
generatorFactory = new CharMarshallingGeneratorFactory(generatorFactory, useBlittableMarshallerForUtf16: runtimeMarshallingDisabled, TypeNames.GeneratedComInterfaceAttribute_ShortName);

InteropGenerationOptions interopGenerationOptions = new(UseMarshalType: true);
generatorFactory = new MarshalAsMarshallingGeneratorFactory(interopGenerationOptions, generatorFactory);

IMarshallingGeneratorFactory elementFactory = new AttributedMarshallingModelGeneratorFactory(
// Since the char type in an array will not be part of the P/Invoke signature, we can
// use the regular blittable marshaller in all cases.
new CharMarshallingGeneratorFactory(generatorFactory, useBlittableMarshallerForUtf16: true),
new CharMarshallingGeneratorFactory(generatorFactory, useBlittableMarshallerForUtf16: true, TypeNames.GeneratedComInterfaceAttribute_ShortName),
new AttributedMarshallingModelOptions(runtimeMarshallingDisabled, MarshalMode.ElementIn, MarshalMode.ElementRef, MarshalMode.ElementOut));
// We don't need to include the later generator factories for collection elements
// as the later generator factories only apply to parameters.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ private MethodDeclarationSyntax GenerateShadow()
var forwarder = new Forwarder();
return MethodDeclaration(GenerationContext.SignatureContext.StubReturnType, MethodInfo.MethodName)
.WithModifiers(TokenList(Token(SyntaxKind.NewKeyword)))
.WithAttributeLists(List(GenerationContext.SignatureContext.AdditionalAttributes.Concat(MethodInfo.Attributes.Select(a => a.GenerateAttributeList()))))
.WithParameterList(ParameterList(SeparatedList(GenerationContext.SignatureContext.StubParameters)))
.WithExpressionBody(
ArrowExpressionClause(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
Expand All @@ -16,7 +17,8 @@ namespace Microsoft.Interop
/// </summary>
internal sealed record ComMethodInfo(
MethodDeclarationSyntax Syntax,
string MethodName)
string MethodName,
SequenceEqualImmutableArray<AttributeInfo> Attributes)
{
/// <summary>
/// Returns a list of tuples of ComMethodInfo, IMethodSymbol, and Diagnostic. If ComMethodInfo is null, Diagnostic will not be null, and vice versa.
Expand Down Expand Up @@ -108,7 +110,14 @@ private static bool IsComMethodCandidate(ISymbol member)
{
return DiagnosticOr<(ComMethodInfo, IMethodSymbol)>.From(diag);
}
var comMethodInfo = new ComMethodInfo(comMethodDeclaringSyntax, method.Name);

var attributes = method.GetAttributes();
var attributeInfos = ImmutableArray.CreateBuilder<AttributeInfo>(attributes.Length);
foreach (var attr in attributes)
{
attributeInfos.Add(AttributeInfo.From(attr));
}
var comMethodInfo = new ComMethodInfo(comMethodDeclaringSyntax, method.Name, attributeInfos.MoveToImmutable().ToSequenceEqual());
return DiagnosticOr<(ComMethodInfo, IMethodSymbol)>.From((comMethodInfo, method));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ internal static class VtableIndexStubGeneratorHelpers
// If we're in a "supported" scenario, then emit a diagnostic as our final fallback.
generatorFactory = new UnsupportedMarshallingFactory();

generatorFactory = new NoMarshallingInfoErrorMarshallingFactory(generatorFactory);
generatorFactory = new NoMarshallingInfoErrorMarshallingFactory(generatorFactory, TypeNames.VirtualMethodIndexAttribute_ShortName);

// The presence of System.Runtime.CompilerServices.DisableRuntimeMarshallingAttribute is tied to TFM,
// so we use TFM in the generator factory key instead of the Compilation as the compilation changes on every keystroke.
Expand All @@ -27,15 +27,15 @@ internal static class VtableIndexStubGeneratorHelpers

// Since the char type can go into the P/Invoke signature here, we can only use it when
// runtime marshalling is disabled.
generatorFactory = new CharMarshallingGeneratorFactory(generatorFactory, useBlittableMarshallerForUtf16: runtimeMarshallingDisabled);
generatorFactory = new CharMarshallingGeneratorFactory(generatorFactory, useBlittableMarshallerForUtf16: runtimeMarshallingDisabled, TypeNames.VirtualMethodIndexAttribute_ShortName);

InteropGenerationOptions interopGenerationOptions = new(UseMarshalType: true);
generatorFactory = new MarshalAsMarshallingGeneratorFactory(interopGenerationOptions, generatorFactory);

IMarshallingGeneratorFactory elementFactory = new AttributedMarshallingModelGeneratorFactory(
// Since the char type in an array will not be part of the P/Invoke signature, we can
// use the regular blittable marshaller in all cases.
new CharMarshallingGeneratorFactory(generatorFactory, useBlittableMarshallerForUtf16: true),
new CharMarshallingGeneratorFactory(generatorFactory, useBlittableMarshallerForUtf16: true, TypeNames.VirtualMethodIndexAttribute_ShortName),
new AttributedMarshallingModelOptions(runtimeMarshallingDisabled, MarshalMode.ElementIn, MarshalMode.ElementRef, MarshalMode.ElementOut));
// We don't need to include the later generator factories for collection elements
// as the later generator factories only apply to parameters.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ internal static class LibraryImportGeneratorHelpers
generatorFactory = new UnsupportedMarshallingFactory();
}

generatorFactory = new NoMarshallingInfoErrorMarshallingFactory(generatorFactory);
generatorFactory = new NoMarshallingInfoErrorMarshallingFactory(generatorFactory, TypeNames.LibraryImportAttribute_ShortName);

// The presence of System.Runtime.CompilerServices.DisableRuntimeMarshallingAttribute is tied to TFM,
// so we use TFM in the generator factory key instead of the Compilation as the compilation changes on every keystroke.
Expand All @@ -43,15 +43,15 @@ internal static class LibraryImportGeneratorHelpers

// Since the char type can go into the P/Invoke signature here, we can only use it when
// runtime marshalling is disabled.
generatorFactory = new CharMarshallingGeneratorFactory(generatorFactory, useBlittableMarshallerForUtf16: runtimeMarshallingDisabled);
generatorFactory = new CharMarshallingGeneratorFactory(generatorFactory, useBlittableMarshallerForUtf16: runtimeMarshallingDisabled, TypeNames.LibraryImportAttribute_ShortName);

InteropGenerationOptions interopGenerationOptions = new(options.UseMarshalType);
generatorFactory = new MarshalAsMarshallingGeneratorFactory(interopGenerationOptions, generatorFactory);

IMarshallingGeneratorFactory elementFactory = new AttributedMarshallingModelGeneratorFactory(
// Since the char type in an array will not be part of the P/Invoke signature, we can
// use the regular blittable marshaller in all cases.
new CharMarshallingGeneratorFactory(generatorFactory, useBlittableMarshallerForUtf16: true),
new CharMarshallingGeneratorFactory(generatorFactory, useBlittableMarshallerForUtf16: true, TypeNames.LibraryImportAttribute_ShortName),
new AttributedMarshallingModelOptions(runtimeMarshallingDisabled, MarshalMode.ElementIn, MarshalMode.ElementRef, MarshalMode.ElementOut));
// We don't need to include the later generator factories for collection elements
// as the later generator factories only apply to parameters.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,21 @@ public sealed class CharMarshallingGeneratorFactory : IMarshallingGeneratorFacto

private readonly IMarshallingGeneratorFactory _inner;
private readonly bool _useBlittableMarshallerForUtf16;
private readonly string _stringMarshallingAttribute;

// Needed for API compatibility with preview 4
public CharMarshallingGeneratorFactory(IMarshallingGeneratorFactory inner, bool useBlittableMarshallerForUtf16)
{
_inner = inner;
_useBlittableMarshallerForUtf16 = useBlittableMarshallerForUtf16;
_stringMarshallingAttribute = "LibraryImportGenerator";
}

public CharMarshallingGeneratorFactory(IMarshallingGeneratorFactory inner, bool useBlittableMarshallerForUtf16, string stringMarshallingAttribute)
{
_inner = inner;
_useBlittableMarshallerForUtf16 = useBlittableMarshallerForUtf16;
_stringMarshallingAttribute = stringMarshallingAttribute;
}

public IMarshallingGenerator Create(TypePositionInfo info, StubCodeContext context)
Expand All @@ -41,7 +51,7 @@ private IMarshallingGenerator CreateCharMarshaller(TypePositionInfo info, StubCo
// [Compat] Require explicit marshalling information.
throw new MarshallingNotSupportedException(info, context)
{
NotSupportedDetails = SR.MarshallingStringOrCharAsUndefinedNotSupported
NotSupportedDetails = string.Format(SR.MarshallingStringOrCharAsUndefinedNotSupported, _stringMarshallingAttribute)
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,14 @@ public IMarshallingGenerator Create(
return _inner.Create(info, context);
}

// Necessary for API compatibility with preview 4 SDK
public NoMarshallingInfoErrorMarshallingFactory(IMarshallingGeneratorFactory inner)
: this(inner, DefaultTypeToErrorMessageMap)
: this(inner, DefaultTypeToErrorMessageMap("LibraryImportAttribute"))
{
}

public NoMarshallingInfoErrorMarshallingFactory(IMarshallingGeneratorFactory inner, string stringMarshallingAttribute)
: this(inner, DefaultTypeToErrorMessageMap(stringMarshallingAttribute))
{
}

Expand All @@ -40,10 +46,10 @@ private NoMarshallingInfoErrorMarshallingFactory(IMarshallingGeneratorFactory in

public ImmutableDictionary<ManagedTypeInfo, string> CustomTypeToErrorMessageMap { get; }

private static ImmutableDictionary<ManagedTypeInfo, string> DefaultTypeToErrorMessageMap { get; } =
ImmutableDictionary.CreateRange(new Dictionary<ManagedTypeInfo, string>
private static ImmutableDictionary<ManagedTypeInfo, string> DefaultTypeToErrorMessageMap(string stringMarshallingAttribute)
=> ImmutableDictionary.CreateRange(new Dictionary<ManagedTypeInfo, string>
{
{ SpecialTypeInfo.String, SR.MarshallingStringOrCharAsUndefinedNotSupported },
{ SpecialTypeInfo.String, string.Format(SR.MarshallingStringOrCharAsUndefinedNotSupported, stringMarshallingAttribute) },
{ SpecialTypeInfo.Boolean, SR.MarshallingBoolAsUndefinedNotSupported },
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@
<value>Marshalling char with 'StringMarshalling.{0}' is not supported. Instead, manually convert the char type to the desired byte representation and pass to the source-generated P/Invoke.</value>
</data>
<data name="MarshallingStringOrCharAsUndefinedNotSupported" xml:space="preserve">
<value>Marshalling string or char without explicit marshalling information is not supported. Specify 'LibraryImportAttribute.StringMarshalling', 'LibraryImportAttribute.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'.</value>
<value>Marshalling string or char without explicit marshalling information is not supported. Specify '{0}.StringMarshalling', '{0}.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'.</value>
</data>
<data name="SafeHandleByRefMustBeConcrete" xml:space="preserve">
<value>An abstract type derived from 'SafeHandle' cannot be marshalled by reference. The provided type must be concrete.</value>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@
<note />
</trans-unit>
<trans-unit id="MarshallingStringOrCharAsUndefinedNotSupported">
<source>Marshalling string or char without explicit marshalling information is not supported. Specify 'LibraryImportAttribute.StringMarshalling', 'LibraryImportAttribute.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'.</source>
<target state="translated">Zařazování řetězce nebo znaku bez explicitních informací o zařazování se nepodporuje. Zadejte LibraryImportAttribute.StringMarshalling, LibraryImportAttribute.StringMarshallingCustomType, MarshalUsingAttribute nebo MarshalAsAttribute.</target>
<source>Marshalling string or char without explicit marshalling information is not supported. Specify '{0}.StringMarshalling', '{0}.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'.</source>
<target state="new">Marshalling string or char without explicit marshalling information is not supported. Specify '{0}.StringMarshalling', '{0}.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'.</target>
<note />
</trans-unit>
<trans-unit id="RuntimeMarshallingMustBeDisabled">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@
<note />
</trans-unit>
<trans-unit id="MarshallingStringOrCharAsUndefinedNotSupported">
<source>Marshalling string or char without explicit marshalling information is not supported. Specify 'LibraryImportAttribute.StringMarshalling', 'LibraryImportAttribute.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'.</source>
<target state="translated">Das Marshalling von Zeichenfolgen oder Zeichen ohne explizite Marshalling-Informationen wird nicht unterstützt. Geben Sie „LibraryImportAttribute.StringMarshalling“, „LibraryImportAttribute.StringMarshallingCustomType“, „MarshalUsingAttribute“ oder „MarshalAsAttribute“ an.</target>
<source>Marshalling string or char without explicit marshalling information is not supported. Specify '{0}.StringMarshalling', '{0}.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'.</source>
<target state="new">Marshalling string or char without explicit marshalling information is not supported. Specify '{0}.StringMarshalling', '{0}.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'.</target>
<note />
</trans-unit>
<trans-unit id="RuntimeMarshallingMustBeDisabled">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@
<note />
</trans-unit>
<trans-unit id="MarshallingStringOrCharAsUndefinedNotSupported">
<source>Marshalling string or char without explicit marshalling information is not supported. Specify 'LibraryImportAttribute.StringMarshalling', 'LibraryImportAttribute.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'.</source>
<target state="translated">No se admite la serialización de cadenas o caracteres sin información de serialización explícita. Especifique \"LibraryImportAttribute.StringMars slaing\", \"LibraryImportAttribute.StringMars slaingCustomType\", \"MarshalUsingAttribute\" o \"MarshalAsAttribute\".</target>
<source>Marshalling string or char without explicit marshalling information is not supported. Specify '{0}.StringMarshalling', '{0}.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'.</source>
<target state="new">Marshalling string or char without explicit marshalling information is not supported. Specify '{0}.StringMarshalling', '{0}.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'.</target>
<note />
</trans-unit>
<trans-unit id="RuntimeMarshallingMustBeDisabled">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@
<note />
</trans-unit>
<trans-unit id="MarshallingStringOrCharAsUndefinedNotSupported">
<source>Marshalling string or char without explicit marshalling information is not supported. Specify 'LibraryImportAttribute.StringMarshalling', 'LibraryImportAttribute.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'.</source>
<target state="translated">Le marshaling de chaîne ou de char sans informations de marshaling explicites n’est pas pris en charge. Spécifiez « LibraryImportAttribute.StringMars streaming », « LibraryImportAttribute.StringMars streamingCustomType », « MarshalUsingAttribute » ou « MarshalAsAttribute ».</target>
<source>Marshalling string or char without explicit marshalling information is not supported. Specify '{0}.StringMarshalling', '{0}.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'.</source>
<target state="new">Marshalling string or char without explicit marshalling information is not supported. Specify '{0}.StringMarshalling', '{0}.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'.</target>
<note />
</trans-unit>
<trans-unit id="RuntimeMarshallingMustBeDisabled">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@
<note />
</trans-unit>
<trans-unit id="MarshallingStringOrCharAsUndefinedNotSupported">
<source>Marshalling string or char without explicit marshalling information is not supported. Specify 'LibraryImportAttribute.StringMarshalling', 'LibraryImportAttribute.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'.</source>
<target state="translated">Il marshalling di stringa o carattere senza informazioni di marshalling esplicite non è supportato. Specificare 'LibraryImportAttribute.StringMarshalling', 'LibraryImportAttribute.StringMarshallingCustomType', 'MarshalUsingAttribute' o 'MarshalAsAttribute'.</target>
<source>Marshalling string or char without explicit marshalling information is not supported. Specify '{0}.StringMarshalling', '{0}.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'.</source>
<target state="new">Marshalling string or char without explicit marshalling information is not supported. Specify '{0}.StringMarshalling', '{0}.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'.</target>
<note />
</trans-unit>
<trans-unit id="RuntimeMarshallingMustBeDisabled">
Expand Down
Loading

0 comments on commit 4177d2d

Please sign in to comment.