| File: InteropAttributeData.cs | Web Access |
| Project: src\runtime\src\libraries\System.Runtime.InteropServices\gen\Microsoft.Interop.SourceGeneration\Microsoft.Interop.SourceGeneration.csproj (Microsoft.Interop.SourceGeneration) |
// 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.Immutable; using Microsoft.CodeAnalysis; namespace Microsoft.Interop { /// <summary> /// Flags used to indicate members on source-generated interop attributes. /// </summary> [Flags] public enum InteropAttributeMember { None = 0, SetLastError = 1 << 0, StringMarshalling = 1 << 1, StringMarshallingCustomType = 1 << 2, All = ~None } /// <summary> /// Common data for all source-generated-interop trigger attributes. /// This type and derived types should not have any reference that would keep a compilation alive. /// </summary> public record InteropAttributeData { /// <summary> /// Value set by the user on the original declaration. /// </summary> public InteropAttributeMember IsUserDefined { get; init; } public bool SetLastError { get; init; } public StringMarshalling StringMarshalling { get; init; } public ManagedTypeInfo? StringMarshallingCustomType { get; init; } } /// <summary> /// Common data for all source-generated-interop trigger attributes that also includes a reference to the Roslyn symbol for StringMarshallingCustomType. /// See <seealso cref="InteropAttributeData"/> for a type that doesn't keep a compilation alive. /// </summary> public record InteropAttributeCompilationData { /// <summary> /// Value set by the user on the original declaration. /// </summary> public InteropAttributeMember IsUserDefined { get; init; } public bool SetLastError { get; init; } public StringMarshalling StringMarshalling { get; init; } public INamedTypeSymbol? StringMarshallingCustomType { get; init; } } public static class InteropAttributeDataExtensions { public static T WithValuesFromNamedArguments<T>(this T t, ImmutableDictionary<string, TypedConstant> namedArguments) where T : InteropAttributeCompilationData { InteropAttributeMember userDefinedValues = InteropAttributeMember.None; bool setLastError = false; StringMarshalling stringMarshalling = StringMarshalling.Custom; INamedTypeSymbol? stringMarshallingCustomType = null; if (namedArguments.TryGetValue(nameof(InteropAttributeCompilationData.SetLastError), out TypedConstant setLastErrorValue)) { userDefinedValues |= InteropAttributeMember.SetLastError; if (setLastErrorValue.Value is not bool) { return null; } setLastError = (bool)setLastErrorValue.Value!; } if (namedArguments.TryGetValue(nameof(InteropAttributeCompilationData.StringMarshalling), out TypedConstant stringMarshallingValue)) { userDefinedValues |= InteropAttributeMember.StringMarshalling; // TypedConstant's Value property only contains primitive values. if (stringMarshallingValue.Value is not int) { return null; } // A boxed primitive can be unboxed to an enum with the same underlying type. stringMarshalling = (StringMarshalling)stringMarshallingValue.Value!; } if (namedArguments.TryGetValue(nameof(InteropAttributeCompilationData.StringMarshallingCustomType), out TypedConstant stringMarshallingCustomTypeValue)) { userDefinedValues |= InteropAttributeMember.StringMarshallingCustomType; if (stringMarshallingCustomTypeValue.Value is not INamedTypeSymbol) { return null; } stringMarshallingCustomType = (INamedTypeSymbol)stringMarshallingCustomTypeValue.Value; } return t with { IsUserDefined = userDefinedValues, SetLastError = setLastError, StringMarshalling = stringMarshalling, StringMarshallingCustomType = stringMarshallingCustomType }; } } }