-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Split the MarshalAsParser into two classes #93038
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
119 changes: 119 additions & 0 deletions
119
...opServices/gen/Microsoft.Interop.SourceGeneration/MarshalAsWithCustomMarshallersParser.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,119 @@ | ||
| // Licensed to the .NET Foundation under one or more agreements. | ||
| // The .NET Foundation licenses this file to you under the MIT license. | ||
|
|
||
| using System; | ||
| using System.Collections.Generic; | ||
| using System.Collections.Immutable; | ||
| using System.Runtime.InteropServices; | ||
| using Microsoft.CodeAnalysis; | ||
|
|
||
| namespace Microsoft.Interop | ||
| { | ||
| /// <summary> | ||
| /// This class suppports parsing a System.Runtime.InteropServices.MarshalAsAttribute into either a <see cref="MarshalAsInfo"/> or a <see cref="NativeMarshallingAttributeInfo"/> | ||
| /// if the marshalling is implemented with a custom marshaller in the framework. | ||
| /// </summary> | ||
| public sealed class MarshalAsWithCustomMarshallersParser : IMarshallingInfoAttributeParser | ||
| { | ||
| private readonly Compilation _compilation; | ||
| private readonly GeneratorDiagnosticsBag _diagnostics; | ||
| private readonly IMarshallingInfoAttributeParser _marshalAsAttributeParser; | ||
|
|
||
| /// <summary> | ||
| /// Create a new instance of <see cref="MarshalAsWithCustomMarshallersParser"/>. | ||
| /// </summary> | ||
| /// <param name="compilation">The compilation that the attributes are defined within.</param> | ||
| /// <param name="diagnostics">The diagnostics bag to which to report diagnostics.</param> | ||
| /// <param name="marshalAsAttributeParser">The parser that will do basic parsing of a MarshalAsAttribute into a <see cref="MarshalAsInfo"/> element.</param> | ||
| public MarshalAsWithCustomMarshallersParser(Compilation compilation, GeneratorDiagnosticsBag diagnostics, IMarshallingInfoAttributeParser marshalAsAttributeParser) | ||
| { | ||
| _compilation = compilation; | ||
| _diagnostics = diagnostics; | ||
| _marshalAsAttributeParser = marshalAsAttributeParser; | ||
| } | ||
|
|
||
| public bool CanParseAttributeType(INamedTypeSymbol attributeType) => attributeType.ToDisplayString() == TypeNames.System_Runtime_InteropServices_MarshalAsAttribute; | ||
|
|
||
| MarshallingInfo? IMarshallingInfoAttributeParser.ParseAttribute(AttributeData attributeData, ITypeSymbol type, int indirectionDepth, UseSiteAttributeProvider useSiteAttributes, GetMarshallingInfoCallback marshallingInfoCallback) | ||
| { | ||
| var marshalAsInfo = (MarshalAsInfo)_marshalAsAttributeParser.ParseAttribute(attributeData, type, indirectionDepth, useSiteAttributes, marshallingInfoCallback); | ||
|
|
||
| // We'll support the UnmanagedType.Interface option, but we'll explicitly | ||
| // leave ComImport types with the MarshalAs info instead of the custom marshaller | ||
| // as they will not work as expected unless they are migrated to [GeneratedComInterface]. | ||
| if (marshalAsInfo.UnmanagedType == UnmanagedType.Interface) | ||
| { | ||
| return type is INamedTypeSymbol { IsComImport: true } | ||
| ? marshalAsInfo | ||
| : ComInterfaceMarshallingInfoProvider.CreateComInterfaceMarshallingInfo(_compilation, type); | ||
| } | ||
|
|
||
| if (marshalAsInfo is MarshalAsArrayInfo arrayInfo) | ||
| { | ||
| if (type is not IArrayTypeSymbol { ElementType: ITypeSymbol elementType }) | ||
| { | ||
| _diagnostics.ReportConfigurationNotSupported(attributeData, nameof(UnmanagedType), arrayInfo.UnmanagedType.ToString()); | ||
| return NoMarshallingInfo.Instance; | ||
| } | ||
|
|
||
| MarshallingInfo elementMarshallingInfo = NoMarshallingInfo.Instance; | ||
| if (arrayInfo.ArraySubType != (UnmanagedType)SizeAndParamIndexInfo.UnspecifiedConstSize) | ||
| { | ||
| if (elementType.SpecialType == SpecialType.System_String) | ||
| { | ||
| elementMarshallingInfo = CreateStringMarshallingInfo(elementType, new MarshalAsScalarInfo(arrayInfo.ArraySubType, arrayInfo.CharEncoding)); | ||
| } | ||
| else if (arrayInfo.ArraySubType == UnmanagedType.Interface && elementType is not INamedTypeSymbol { IsComImport: true }) | ||
| { | ||
| elementMarshallingInfo = ComInterfaceMarshallingInfoProvider.CreateComInterfaceMarshallingInfo(_compilation, elementType); | ||
| } | ||
| else | ||
| { | ||
| elementMarshallingInfo = new MarshalAsScalarInfo(arrayInfo.ArraySubType, arrayInfo.CharEncoding); | ||
| } | ||
| } | ||
| else | ||
| { | ||
| elementMarshallingInfo = marshallingInfoCallback(elementType, useSiteAttributes, indirectionDepth + 1); | ||
| } | ||
|
|
||
| CountInfo countInfo = NoCountInfo.Instance; | ||
|
|
||
| if (useSiteAttributes.TryGetUseSiteAttributeInfo(indirectionDepth, out UseSiteAttributeData useSiteAttributeData)) | ||
| { | ||
| countInfo = useSiteAttributeData.CountInfo; | ||
| } | ||
|
|
||
| return ArrayMarshallingInfoProvider.CreateArrayMarshallingInfo(_compilation, type, elementType, countInfo, elementMarshallingInfo); | ||
| } | ||
|
|
||
| if (type.SpecialType == SpecialType.System_String) | ||
| { | ||
| return CreateStringMarshallingInfo(type, marshalAsInfo); | ||
| } | ||
|
|
||
| return marshalAsInfo; | ||
| } | ||
|
|
||
| private MarshallingInfo CreateStringMarshallingInfo( | ||
| ITypeSymbol type, | ||
| MarshalAsInfo marshalAsInfo) | ||
| { | ||
| string? marshallerName = marshalAsInfo.UnmanagedType switch | ||
| { | ||
| UnmanagedType.BStr => TypeNames.BStrStringMarshaller, | ||
| UnmanagedType.LPStr => TypeNames.AnsiStringMarshaller, | ||
| UnmanagedType.LPTStr or UnmanagedType.LPWStr => TypeNames.Utf16StringMarshaller, | ||
| MarshalAsInfo.UnmanagedType_LPUTF8Str => TypeNames.Utf8StringMarshaller, | ||
| _ => null | ||
| }; | ||
|
|
||
| if (marshallerName is null) | ||
| { | ||
| return marshalAsInfo; | ||
| } | ||
|
|
||
| return StringMarshallingInfoProvider.CreateStringMarshallingInfo(_compilation, type, marshallerName); | ||
| } | ||
| } | ||
| } |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this still used as a
IMarshallingInfoAttributeParsernow?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's intended to optionally be used that way. We don't use it in the same way currently, but we delegate to this implementation from the other one through the interface.