From 40c3516caa53708d465f969c1571ac123adf3e1b Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Wed, 23 Oct 2024 21:43:07 +0100 Subject: [PATCH] Ensure we can handle enums with the same name in different namespaces (#114) --- .../EnumGenerator.cs | 9 +- .../SourceGenerationHelper.cs | 30 +- .../InterceptorTests.cs | 58 + ...SameNameInDifferentNamespaces.verified.txt | 1270 +++++++++++++++++ .../SourceGenerationHelperSnapshotTests.cs | 6 +- 5 files changed, 1360 insertions(+), 13 deletions(-) create mode 100644 tests/NetEscapades.EnumGenerators.Tests/Snapshots/InterceptorTests.CanHandleEnumsWithSameNameInDifferentNamespaces.verified.txt diff --git a/src/NetEscapades.EnumGenerators/EnumGenerator.cs b/src/NetEscapades.EnumGenerators/EnumGenerator.cs index aed154e..d28c689 100644 --- a/src/NetEscapades.EnumGenerators/EnumGenerator.cs +++ b/src/NetEscapades.EnumGenerators/EnumGenerator.cs @@ -149,9 +149,8 @@ public void Initialize(IncrementalGeneratorInitializationContext context) static void Execute(in EnumToGenerate enumToGenerate, SourceProductionContext context) { - StringBuilder sb = new StringBuilder(); - var result = SourceGenerationHelper.GenerateExtensionClass(sb, in enumToGenerate); - context.AddSource(enumToGenerate.Name + "_EnumExtensions.g.cs", SourceText.From(result, Encoding.UTF8)); + var (result, filename) = SourceGenerationHelper.GenerateExtensionClass(in enumToGenerate); + context.AddSource(filename, SourceText.From(result, Encoding.UTF8)); } static EquatableArray? GetEnumToGenerateFromGenericAssemblyAttribute( @@ -414,8 +413,8 @@ private static bool InterceptorPredicate(SyntaxNode node, CancellationToken ct) private static void ExecuteInterceptors(MethodToIntercept? toIntercept, SourceProductionContext spc) { - var result = SourceGenerationHelper.GenerateInterceptorsClass(toIntercept!); - spc.AddSource(toIntercept!.ExtensionTypeName + "_Interceptors.g.cs", SourceText.From(result, Encoding.UTF8)); + var (result, filename) = SourceGenerationHelper.GenerateInterceptorsClass(toIntercept!); + spc.AddSource(filename, SourceText.From(result, Encoding.UTF8)); } #endif } diff --git a/src/NetEscapades.EnumGenerators/SourceGenerationHelper.cs b/src/NetEscapades.EnumGenerators/SourceGenerationHelper.cs index cbd1b69..f0e993f 100644 --- a/src/NetEscapades.EnumGenerators/SourceGenerationHelper.cs +++ b/src/NetEscapades.EnumGenerators/SourceGenerationHelper.cs @@ -129,8 +129,9 @@ public class InterceptableAttribute : global::System.Attribute #endif "; - public static string GenerateExtensionClass(StringBuilder sb, in EnumToGenerate enumToGenerate) + public static (string Content, string HintName) GenerateExtensionClass(in EnumToGenerate enumToGenerate) { + var sb = new StringBuilder(); sb .Append(Header) .Append(@" @@ -898,11 +899,21 @@ public static string[] GetNames() }"); } - return sb.ToString(); + var content = sb.ToString(); + sb.Clear(); + var filename = sb + .Append(enumToGenerate.FullyQualifiedName) + .Append("_EnumExtensions.g.cs") + .Replace('<', '_') + .Replace('>', '_') + .Replace(',', '.') + .Replace(' ', '_') + .ToString(); + return (content, filename); } #if INTERCEPTORS - public static string GenerateInterceptorsClass(MethodToIntercept toIntercept) + public static (string Content, string Filename) GenerateInterceptorsClass(MethodToIntercept toIntercept) { var sb = new StringBuilder( $$""" @@ -980,7 +991,18 @@ static file class EnumInterceptors #pragma warning restore CS0612 // Ignore usages of obsolete members or enums #pragma warning restore CS0618 // Ignore usages of obsolete members or enums """); - return sb.ToString(); + var content = sb.ToString(); + sb.Clear(); + + var filename = sb + .Append(toIntercept!.FullyQualifiedName) + .Append("_Interceptors.g.cs") + .Replace('<', '_') + .Replace('>', '_') + .Replace(',', '.') + .Replace(' ', '_') + .ToString(); + return (content, filename); static string GetInterceptorAttr(CandidateInvocation location) { diff --git a/tests/NetEscapades.EnumGenerators.Tests/InterceptorTests.cs b/tests/NetEscapades.EnumGenerators.Tests/InterceptorTests.cs index 9117ac4..9388724 100644 --- a/tests/NetEscapades.EnumGenerators.Tests/InterceptorTests.cs +++ b/tests/NetEscapades.EnumGenerators.Tests/InterceptorTests.cs @@ -190,6 +190,64 @@ public void MyTest() return Verifier.Verify(output).ScrubExpectedChanges().UseDirectory("Snapshots"); } + [Fact] + public Task CanHandleEnumsWithSameNameInDifferentNamespaces() + { + const string input = + """ + using NetEscapades.EnumGenerators; + using System; + + namespace Foo + { + [EnumExtensions] + [Flags] + internal enum MyEnum + { + First = 1, + Second = 2, + Third = 4, + } + } + + namespace Bar + { + [EnumExtensions] + [Flags] + internal enum MyEnum + { + First = 1, + Second = 2, + Third = 4, + } + } + + namespace Baz + { + internal class InnerClass + { + public Foo.MyEnum _field = default; + public Bar.MyEnum Property {get;set;} = default; + public void MyTest() + { + var myValue = Foo.MyEnum.Second; + var var1 = myValue.HasFlag(Foo.MyEnum.First); + var var2 = Foo.MyEnum.Second.HasFlag(myValue); + var var3 = Property.HasFlag(Bar.MyEnum.First); + var var4 = _field.HasFlag(Foo.MyEnum.First); + var var5 = myValue.ToString(); + var var6 = Bar.MyEnum.First.ToString(); + } + } + } + """; + var (diagnostics, output) = + TestHelpers.GetGeneratedTrees(new(_analyzerOpts, _features, input)); + + Assert.Empty(diagnostics); + return Verifier.Verify(output).ScrubExpectedChanges().UseDirectory("Snapshots"); + } + [Fact] public Task CanInterceptMultipleEnumsToString() { diff --git a/tests/NetEscapades.EnumGenerators.Tests/Snapshots/InterceptorTests.CanHandleEnumsWithSameNameInDifferentNamespaces.verified.txt b/tests/NetEscapades.EnumGenerators.Tests/Snapshots/InterceptorTests.CanHandleEnumsWithSameNameInDifferentNamespaces.verified.txt new file mode 100644 index 0000000..1405b12 --- /dev/null +++ b/tests/NetEscapades.EnumGenerators.Tests/Snapshots/InterceptorTests.CanHandleEnumsWithSameNameInDifferentNamespaces.verified.txt @@ -0,0 +1,1270 @@ +[ +//------------------------------------------------------------------------------ +// +// This code was generated by the NetEscapades.EnumGenerators source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#nullable enable + +#if NETESCAPADES_ENUMGENERATORS_EMBED_ATTRIBUTES +namespace NetEscapades.EnumGenerators +{ + /// + /// Add to enums to indicate that extension methods should be generated for the type + /// + [global::System.AttributeUsage(global::System.AttributeTargets.Enum)] + [global::System.Diagnostics.Conditional("NETESCAPADES_ENUMGENERATORS_USAGES")] +#if NET5_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage(Justification = "Generated by the NetEscapades.EnumGenerators source generator.")] +#else + [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] +#endif + public class EnumExtensionsAttribute : global::System.Attribute + { + /// + /// The namespace to generate the extension class. + /// If not provided, the namespace of the enum will be used + /// + public string? ExtensionClassNamespace { get; set; } + + /// + /// The name to use for the extension class. + /// If not provided, the enum name with "Extensions" will be used. + /// For example for an Enum called StatusCodes, the default name + /// will be StatusCodesExtensions + /// + public string? ExtensionClassName { get; set; } + + /// + /// By default, when interceptors are enabled for a project, any + /// interceptable usages of the enum will be replaced by usages of + /// the extension method in this project. To disable interception of + /// the enum in this project, set to false. + /// + public bool IsInterceptable { get; set; } = true; + } + + + /// + /// Add to enums to indicate that extension methods should be generated for the type + /// + [System.AttributeUsage(System.AttributeTargets.Assembly, AllowMultiple = true)] + [System.Diagnostics.Conditional("NETESCAPADES_ENUMGENERATORS_USAGES")] +#if NET5_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage(Justification = "Generated by the NetEscapades.EnumGenerators source generator.")] +#else + [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] +#endif + public class EnumExtensionsAttribute : System.Attribute + where T: System.Enum + { + /// + /// The namespace to generate the extension class. + /// If not provided, the namespace of the enum will be used + /// + public string? ExtensionClassNamespace { get; set; } + + /// + /// The name to use for the extension class. + /// If not provided, the enum name with ""Extensions"" will be used. + /// For example for an Enum called StatusCodes, the default name + /// will be StatusCodesExtensions + /// + public string? ExtensionClassName { get; set; } + + /// + /// By default, when interceptors are enabled for a project, any + /// interceptable usages of the enum will be replaced by usages of + /// the extension method in this project. To disable interception of + /// the enum in this project, set to false. + /// + public bool IsInterceptable { get; set; } = true; + } + + /// + /// Add to an assembly to indicate that usages of the enum should + /// be automatically intercepted to use the extension methods + /// generated by in this project. + /// Note that the extension methods must be accessible from this project, + /// otherwise you will receive compilation errors + /// + [global::System.AttributeUsage(global::System.AttributeTargets.Assembly, AllowMultiple = true)] + [global::System.Diagnostics.Conditional("NETESCAPADES_ENUMGENERATORS_USAGES")] +#if NET5_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage(Justification = "Generated by the NetEscapades.EnumGenerators source generator.")] +#else + [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] +#endif + public class InterceptableAttribute : global::System.Attribute + where T: global::System.Enum + { + /// + /// The namespace generated for the extension class. + /// If not provided, the namespace of the enum will be assumed. + /// + public string? ExtensionClassNamespace { get; set; } + + /// + /// The name used for the extension class. + /// If not provided, the enum name with ""Extensions"" will be assumed. + /// For example for an Enum called StatusCodes, the assumed name + /// will be StatusCodesExtensions. + /// + public string? ExtensionClassName { get; set; } + } +} +#endif + + +//------------------------------------------------------------------------------ +// +// This code was generated by the NetEscapades.EnumGenerators source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#nullable enable +#if NETCOREAPP && !NETCOREAPP2_0 && !NETCOREAPP1_1 && !NETCOREAPP1_0 +using System; +#endif + +namespace Foo +{ +#pragma warning disable CS0612 // Ignore usages of obsolete members or enums +#pragma warning disable CS0618 // Ignore usages of obsolete members or enums + /// + /// Extension methods for + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("NetEscapades.EnumGenerators", "FIXED_VERSION")] + internal static partial class MyEnumExtensions + { + /// + /// The number of members in the enum. + /// This is a non-distinct count of defined names. + /// + public const int Length = 3; + + /// + /// Returns the string representation of the value. + /// If the attribute is decorated with a [Display] attribute, then + /// uses the provided value. Otherwise uses the name of the member, equivalent to + /// calling ToString() on . + /// + /// The value to retrieve the string value for + /// The string representation of the value + public static string ToStringFast(this global::Foo.MyEnum value) + => value switch + { + global::Foo.MyEnum.First => nameof(global::Foo.MyEnum.First), + global::Foo.MyEnum.Second => nameof(global::Foo.MyEnum.Second), + global::Foo.MyEnum.Third => nameof(global::Foo.MyEnum.Third), + _ => value.ToString(), + }; + + /// + /// Determines whether one or more bit fields are set in the current instance. + /// Equivalent to calling on . + /// + /// The value of the instance to investigate + /// The flag to check for + /// true if the fields set in the flag are also set in the current instance; otherwise false. + /// If the underlying value of is zero, the method returns true. + /// This is consistent with the behaviour of + public static bool HasFlagFast(this global::Foo.MyEnum value, global::Foo.MyEnum flag) + => flag == 0 ? true : (value & flag) == flag; + + /// + /// Returns a boolean telling whether the given enum value exists in the enumeration. + /// + /// The value to check if it's defined + /// true if the value exists in the enumeration, false otherwise + public static bool IsDefined(global::Foo.MyEnum value) + => value switch + { + global::Foo.MyEnum.First => true, + global::Foo.MyEnum.Second => true, + global::Foo.MyEnum.Third => true, + _ => false, + }; + + /// + /// Returns a boolean telling whether an enum with the given name exists in the enumeration. + /// + /// The name to check if it's defined + /// true if a member with the name exists in the enumeration, false otherwise + public static bool IsDefined(string name) => IsDefined(name, allowMatchingMetadataAttribute: false); + + /// + /// Returns a boolean telling whether an enum with the given name exists in the enumeration, + /// or if a member decorated with a [Display] attribute + /// with the required name exists. + /// + /// The name to check if it's defined + /// If true, considers the value of metadata attributes,otherwise ignores them + /// true if a member with the name exists in the enumeration, or a member is decorated + /// with a [Display] attribute with the name, false otherwise + public static bool IsDefined(string name, bool allowMatchingMetadataAttribute) + { + return name switch + { + nameof(global::Foo.MyEnum.First) => true, + nameof(global::Foo.MyEnum.Second) => true, + nameof(global::Foo.MyEnum.Third) => true, + _ => false, + }; + } + +#if NETCOREAPP && !NETCOREAPP2_0 && !NETCOREAPP1_1 && !NETCOREAPP1_0 + /// + /// Returns a boolean telling whether an enum with the given name exists in the enumeration + /// + /// The name to check if it's defined + /// true if a member with the name exists in the enumeration, false otherwise + public static bool IsDefined(in ReadOnlySpan name) => IsDefined(name, allowMatchingMetadataAttribute: false); + + /// + /// Returns a boolean telling whether an enum with the given name exists in the enumeration, + /// or optionally if a member decorated with a [Display] attribute + /// with the required name exists. + /// Slower then the overload, but doesn't allocate memory./> + /// + /// The name to check if it's defined + /// If true, considers the value of metadata attributes,otherwise ignores them + /// true if a member with the name exists in the enumeration, or a member is decorated + /// with a [Display] attribute with the name, false otherwise + public static bool IsDefined(in ReadOnlySpan name, bool allowMatchingMetadataAttribute) + { + return name switch + { + ReadOnlySpan current when current.Equals(nameof(global::Foo.MyEnum.First).AsSpan(), global::System.StringComparison.Ordinal) => true, + ReadOnlySpan current when current.Equals(nameof(global::Foo.MyEnum.Second).AsSpan(), global::System.StringComparison.Ordinal) => true, + ReadOnlySpan current when current.Equals(nameof(global::Foo.MyEnum.Third).AsSpan(), global::System.StringComparison.Ordinal) => true, + _ => false, + }; + } +#endif + + /// + /// Converts the string representation of the name or numeric value of + /// an to the equivalent instance. + /// + /// The case-sensitive string representation of the enumeration name or underlying value to convert + /// An object of type whose + /// value is represented by + public static global::Foo.MyEnum Parse( +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] +#endif + string? name) + => TryParse(name, out var value, false, false) ? value : ThrowValueNotFound(name); + + /// + /// Converts the string representation of the name or numeric value of + /// an to the equivalent instance. + /// + /// The case-sensitive string representation of the enumeration name or underlying value to convert + /// true to read value in case insensitive mode; false to read value in case sensitive mode. + /// An object of type whose + /// value is represented by + public static global::Foo.MyEnum Parse( +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] +#endif + string? name, + bool ignoreCase) + => TryParse(name, out var value, ignoreCase, false) ? value : ThrowValueNotFound(name); + + /// + /// Converts the string representation of the name or numeric value of + /// an to the equivalent instance. + /// + /// The case-sensitive string representation of the enumeration name or underlying value to convert + /// true to read value in case insensitive mode; false to read value in case sensitive mode. + /// If true, considers the value included in metadata attributes such as + /// [Display] attribute when parsing, otherwise only considers the member names. + /// An object of type whose + /// value is represented by + public static global::Foo.MyEnum Parse( +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] +#endif + string? name, + bool ignoreCase, + bool allowMatchingMetadataAttribute) + => TryParse(name, out var value, ignoreCase, allowMatchingMetadataAttribute) ? value : ThrowValueNotFound(name); + +#if NETCOREAPP3_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.DoesNotReturn] +#endif + private static global::Foo.MyEnum ThrowValueNotFound(string? name) + => throw new System.ArgumentException($"Requested value '{name}' was not found."); + + /// + /// Converts the string representation of the name or numeric value of + /// an to the equivalent instance. + /// The return value indicates whether the conversion succeeded. + /// + /// The case-sensitive string representation of the enumeration name or underlying value to convert + /// When this method returns, contains an object of type + /// whose + /// value is represented by if the parse operation succeeds. + /// If the parse operation fails, contains the default value of the underlying type + /// of . This parameter is passed uninitialized. + /// true if the value parameter was converted successfully; otherwise, false. + public static bool TryParse( +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] +#endif + string? name, + out global::Foo.MyEnum value) + => TryParse(name, out value, false, false); + + /// + /// Converts the string representation of the name or numeric value of + /// an to the equivalent instance. + /// The return value indicates whether the conversion succeeded. + /// + /// The string representation of the enumeration name or underlying value to convert + /// When this method returns, contains an object of type + /// whose + /// value is represented by if the parse operation succeeds. + /// If the parse operation fails, contains the default value of the underlying type + /// of . This parameter is passed uninitialized. + /// true to read value in case insensitive mode; false to read value in case sensitive mode. + /// true if the value parameter was converted successfully; otherwise, false. + public static bool TryParse( +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] +#endif + string? name, + out global::Foo.MyEnum value, + bool ignoreCase) + => TryParse(name, out value, ignoreCase, false); + + /// + /// Converts the string representation of the name or numeric value of + /// an to the equivalent instance. + /// The return value indicates whether the conversion succeeded. + /// + /// The string representation of the enumeration name or underlying value to convert + /// When this method returns, contains an object of type + /// whose + /// value is represented by if the parse operation succeeds. + /// If the parse operation fails, contains the default value of the underlying type + /// of . This parameter is passed uninitialized. + /// true to read value in case insensitive mode; false to read value in case sensitive mode. + /// If true, considers the value included in metadata attributes such as + /// [Display] attribute when parsing, otherwise only considers the member names. + /// true if the value parameter was converted successfully; otherwise, false. + public static bool TryParse( +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] +#endif + string? name, + out global::Foo.MyEnum value, + bool ignoreCase, + bool allowMatchingMetadataAttribute) + => ignoreCase + ? TryParseIgnoreCase(name, out value, allowMatchingMetadataAttribute) + : TryParseWithCase(name, out value, allowMatchingMetadataAttribute); + + private static bool TryParseIgnoreCase( +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] +#endif + string? name, + out global::Foo.MyEnum value, + bool allowMatchingMetadataAttribute) + { + + switch (name) + { + case string s when s.Equals(nameof(global::Foo.MyEnum.First), global::System.StringComparison.OrdinalIgnoreCase): + value = global::Foo.MyEnum.First; + return true; + case string s when s.Equals(nameof(global::Foo.MyEnum.Second), global::System.StringComparison.OrdinalIgnoreCase): + value = global::Foo.MyEnum.Second; + return true; + case string s when s.Equals(nameof(global::Foo.MyEnum.Third), global::System.StringComparison.OrdinalIgnoreCase): + value = global::Foo.MyEnum.Third; + return true; + case string s when int.TryParse(name, out var val): + value = (global::Foo.MyEnum)val; + return true; + default: + value = default; + return false; + } + } + + private static bool TryParseWithCase( +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] +#endif + string? name, + out global::Foo.MyEnum value, + bool allowMatchingMetadataAttribute) + { + + switch (name) + { + case nameof(global::Foo.MyEnum.First): + value = global::Foo.MyEnum.First; + return true; + case nameof(global::Foo.MyEnum.Second): + value = global::Foo.MyEnum.Second; + return true; + case nameof(global::Foo.MyEnum.Third): + value = global::Foo.MyEnum.Third; + return true; + case string s when int.TryParse(name, out var val): + value = (global::Foo.MyEnum)val; + return true; + default: + value = default; + return false; + } + } + +#if NETCOREAPP && !NETCOREAPP2_0 && !NETCOREAPP1_1 && !NETCOREAPP1_0 + /// + /// Converts the string representation of the name or numeric value of + /// an to the equivalent instance. + /// + /// The case-sensitive string representation of the enumeration name or underlying value to convert + /// An object of type whose + /// value is represented by + public static global::Foo.MyEnum Parse( +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] +#endif + in ReadOnlySpan name) + => TryParse(name, out var value, false, false) ? value : ThrowValueNotFound(name.ToString()); + + /// + /// Converts the string representation of the name or numeric value of + /// an to the equivalent instance. + /// + /// The case-sensitive string representation of the enumeration name or underlying value to convert + /// true to read value in case insensitive mode; false to read value in case sensitive mode. + /// An object of type whose + /// value is represented by + public static global::Foo.MyEnum Parse( +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] +#endif + in ReadOnlySpan name, + bool ignoreCase) + => TryParse(name, out var value, ignoreCase, false) ? value : ThrowValueNotFound(name.ToString()); + + /// + /// Converts the string representation of the name or numeric value of + /// an to the equivalent instance. + /// + /// The case-sensitive string representation of the enumeration name or underlying value to convert + /// true to read value in case insensitive mode; false to read value in case sensitive mode. + /// If true, considers the value included in metadata attributes such as + /// [Display] attribute when parsing, otherwise only considers the member names. + /// An object of type whose + /// value is represented by + public static global::Foo.MyEnum Parse( +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] +#endif + in ReadOnlySpan name, + bool ignoreCase, + bool allowMatchingMetadataAttribute) + => TryParse(name, out var value, ignoreCase, allowMatchingMetadataAttribute) ? value : ThrowValueNotFound(name.ToString()); + + /// + /// Converts the span representation of the name or numeric value of + /// an to the equivalent instance. + /// The return value indicates whether the conversion succeeded. + /// + /// The span representation of the enumeration name or underlying value to convert + /// When this method returns, contains an object of type + /// whose + /// value is represented by if the parse operation succeeds. + /// If the parse operation fails, contains the default value of the underlying type + /// of . This parameter is passed uninitialized. + /// true if the value parameter was converted successfully; otherwise, false. + public static bool TryParse( +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] +#endif + in ReadOnlySpan name, + out global::Foo.MyEnum value) + => TryParse(name, out value, false, false); + + /// + /// Converts the span representation of the name or numeric value of + /// an to the equivalent instance. + /// The return value indicates whether the conversion succeeded. + /// + /// The span representation of the enumeration name or underlying value to convert + /// When this method returns, contains an object of type + /// whose + /// value is represented by if the parse operation succeeds. + /// If the parse operation fails, contains the default value of the underlying type + /// of . This parameter is passed uninitialized. + /// true to read value in case insensitive mode; false to read value in case sensitive mode. + /// true if the value parameter was converted successfully; otherwise, false. + public static bool TryParse( +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] +#endif + in ReadOnlySpan name, + out global::Foo.MyEnum value, + bool ignoreCase) + => TryParse(name, out value, ignoreCase, false); + + /// + /// Converts the span representation of the name or numeric value of + /// an to the equivalent instance. + /// The return value indicates whether the conversion succeeded. + /// + /// The span representation of the enumeration name or underlying value to convert + /// When this method returns, contains an object of type + /// whose + /// value is represented by if the parse operation succeeds. + /// If the parse operation fails, contains the default value of the underlying type + /// of . This parameter is passed uninitialized. + /// true to read value in case insensitive mode; false to read value in case sensitive mode. + /// If true, considers the value included in metadata attributes such as + /// [Display] attribute when parsing, otherwise only considers the member names. + /// true if the value parameter was converted successfully; otherwise, false. + public static bool TryParse( +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] +#endif + in ReadOnlySpan name, + out global::Foo.MyEnum result, + bool ignoreCase, + bool allowMatchingMetadataAttribute) + => ignoreCase + ? TryParseIgnoreCase(in name, out result, allowMatchingMetadataAttribute) + : TryParseWithCase(in name, out result, allowMatchingMetadataAttribute); + + private static bool TryParseIgnoreCase( +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] +#endif + in ReadOnlySpan name, + out global::Foo.MyEnum result, + bool allowMatchingMetadataAttribute) + { + switch (name) + { + case ReadOnlySpan current when current.Equals(nameof(global::Foo.MyEnum.First).AsSpan(), global::System.StringComparison.OrdinalIgnoreCase): + result = global::Foo.MyEnum.First; + return true; + case ReadOnlySpan current when current.Equals(nameof(global::Foo.MyEnum.Second).AsSpan(), global::System.StringComparison.OrdinalIgnoreCase): + result = global::Foo.MyEnum.Second; + return true; + case ReadOnlySpan current when current.Equals(nameof(global::Foo.MyEnum.Third).AsSpan(), global::System.StringComparison.OrdinalIgnoreCase): + result = global::Foo.MyEnum.Third; + return true; + case ReadOnlySpan current when int.TryParse(name, out var numericResult): + result = (global::Foo.MyEnum)numericResult; + return true; + default: + result = default; + return false; + } + } + + private static bool TryParseWithCase( +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] +#endif + in ReadOnlySpan name, + out global::Foo.MyEnum result, + bool allowMatchingMetadataAttribute) + { + switch (name) + { + case ReadOnlySpan current when current.Equals(nameof(global::Foo.MyEnum.First).AsSpan(), global::System.StringComparison.Ordinal): + result = global::Foo.MyEnum.First; + return true; + case ReadOnlySpan current when current.Equals(nameof(global::Foo.MyEnum.Second).AsSpan(), global::System.StringComparison.Ordinal): + result = global::Foo.MyEnum.Second; + return true; + case ReadOnlySpan current when current.Equals(nameof(global::Foo.MyEnum.Third).AsSpan(), global::System.StringComparison.Ordinal): + result = global::Foo.MyEnum.Third; + return true; + case ReadOnlySpan current when int.TryParse(name, out var numericResult): + result = (global::Foo.MyEnum)numericResult; + return true; + default: + result = default; + return false; + } + } +#endif + + /// + /// Retrieves an array of the values of the members defined in + /// . + /// Note that this returns a new array with every invocation, so + /// should be cached if appropriate. + /// + /// An array of the values defined in + public static global::Foo.MyEnum[] GetValues() + { + return new[] + { + global::Foo.MyEnum.First, + global::Foo.MyEnum.Second, + global::Foo.MyEnum.Third, + }; + } + + /// + /// Retrieves an array of the names of the members defined in + /// . + /// Note that this returns a new array with every invocation, so + /// should be cached if appropriate. + /// + /// An array of the names of the members defined in + public static string[] GetNames() + { + return new[] + { + nameof(global::Foo.MyEnum.First), + nameof(global::Foo.MyEnum.Second), + nameof(global::Foo.MyEnum.Third), + }; + } + } +#pragma warning restore CS0612 // Ignore usages of obsolete members or enums +#pragma warning restore CS0618 // Ignore usages of obsolete members or enums +} + +//------------------------------------------------------------------------------ +// +// This code was generated by the NetEscapades.EnumGenerators source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#nullable enable +#if NETCOREAPP && !NETCOREAPP2_0 && !NETCOREAPP1_1 && !NETCOREAPP1_0 +using System; +#endif + +namespace Bar +{ +#pragma warning disable CS0612 // Ignore usages of obsolete members or enums +#pragma warning disable CS0618 // Ignore usages of obsolete members or enums + /// + /// Extension methods for + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("NetEscapades.EnumGenerators", "FIXED_VERSION")] + internal static partial class MyEnumExtensions + { + /// + /// The number of members in the enum. + /// This is a non-distinct count of defined names. + /// + public const int Length = 3; + + /// + /// Returns the string representation of the value. + /// If the attribute is decorated with a [Display] attribute, then + /// uses the provided value. Otherwise uses the name of the member, equivalent to + /// calling ToString() on . + /// + /// The value to retrieve the string value for + /// The string representation of the value + public static string ToStringFast(this global::Bar.MyEnum value) + => value switch + { + global::Bar.MyEnum.First => nameof(global::Bar.MyEnum.First), + global::Bar.MyEnum.Second => nameof(global::Bar.MyEnum.Second), + global::Bar.MyEnum.Third => nameof(global::Bar.MyEnum.Third), + _ => value.ToString(), + }; + + /// + /// Determines whether one or more bit fields are set in the current instance. + /// Equivalent to calling on . + /// + /// The value of the instance to investigate + /// The flag to check for + /// true if the fields set in the flag are also set in the current instance; otherwise false. + /// If the underlying value of is zero, the method returns true. + /// This is consistent with the behaviour of + public static bool HasFlagFast(this global::Bar.MyEnum value, global::Bar.MyEnum flag) + => flag == 0 ? true : (value & flag) == flag; + + /// + /// Returns a boolean telling whether the given enum value exists in the enumeration. + /// + /// The value to check if it's defined + /// true if the value exists in the enumeration, false otherwise + public static bool IsDefined(global::Bar.MyEnum value) + => value switch + { + global::Bar.MyEnum.First => true, + global::Bar.MyEnum.Second => true, + global::Bar.MyEnum.Third => true, + _ => false, + }; + + /// + /// Returns a boolean telling whether an enum with the given name exists in the enumeration. + /// + /// The name to check if it's defined + /// true if a member with the name exists in the enumeration, false otherwise + public static bool IsDefined(string name) => IsDefined(name, allowMatchingMetadataAttribute: false); + + /// + /// Returns a boolean telling whether an enum with the given name exists in the enumeration, + /// or if a member decorated with a [Display] attribute + /// with the required name exists. + /// + /// The name to check if it's defined + /// If true, considers the value of metadata attributes,otherwise ignores them + /// true if a member with the name exists in the enumeration, or a member is decorated + /// with a [Display] attribute with the name, false otherwise + public static bool IsDefined(string name, bool allowMatchingMetadataAttribute) + { + return name switch + { + nameof(global::Bar.MyEnum.First) => true, + nameof(global::Bar.MyEnum.Second) => true, + nameof(global::Bar.MyEnum.Third) => true, + _ => false, + }; + } + +#if NETCOREAPP && !NETCOREAPP2_0 && !NETCOREAPP1_1 && !NETCOREAPP1_0 + /// + /// Returns a boolean telling whether an enum with the given name exists in the enumeration + /// + /// The name to check if it's defined + /// true if a member with the name exists in the enumeration, false otherwise + public static bool IsDefined(in ReadOnlySpan name) => IsDefined(name, allowMatchingMetadataAttribute: false); + + /// + /// Returns a boolean telling whether an enum with the given name exists in the enumeration, + /// or optionally if a member decorated with a [Display] attribute + /// with the required name exists. + /// Slower then the overload, but doesn't allocate memory./> + /// + /// The name to check if it's defined + /// If true, considers the value of metadata attributes,otherwise ignores them + /// true if a member with the name exists in the enumeration, or a member is decorated + /// with a [Display] attribute with the name, false otherwise + public static bool IsDefined(in ReadOnlySpan name, bool allowMatchingMetadataAttribute) + { + return name switch + { + ReadOnlySpan current when current.Equals(nameof(global::Bar.MyEnum.First).AsSpan(), global::System.StringComparison.Ordinal) => true, + ReadOnlySpan current when current.Equals(nameof(global::Bar.MyEnum.Second).AsSpan(), global::System.StringComparison.Ordinal) => true, + ReadOnlySpan current when current.Equals(nameof(global::Bar.MyEnum.Third).AsSpan(), global::System.StringComparison.Ordinal) => true, + _ => false, + }; + } +#endif + + /// + /// Converts the string representation of the name or numeric value of + /// an to the equivalent instance. + /// + /// The case-sensitive string representation of the enumeration name or underlying value to convert + /// An object of type whose + /// value is represented by + public static global::Bar.MyEnum Parse( +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] +#endif + string? name) + => TryParse(name, out var value, false, false) ? value : ThrowValueNotFound(name); + + /// + /// Converts the string representation of the name or numeric value of + /// an to the equivalent instance. + /// + /// The case-sensitive string representation of the enumeration name or underlying value to convert + /// true to read value in case insensitive mode; false to read value in case sensitive mode. + /// An object of type whose + /// value is represented by + public static global::Bar.MyEnum Parse( +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] +#endif + string? name, + bool ignoreCase) + => TryParse(name, out var value, ignoreCase, false) ? value : ThrowValueNotFound(name); + + /// + /// Converts the string representation of the name or numeric value of + /// an to the equivalent instance. + /// + /// The case-sensitive string representation of the enumeration name or underlying value to convert + /// true to read value in case insensitive mode; false to read value in case sensitive mode. + /// If true, considers the value included in metadata attributes such as + /// [Display] attribute when parsing, otherwise only considers the member names. + /// An object of type whose + /// value is represented by + public static global::Bar.MyEnum Parse( +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] +#endif + string? name, + bool ignoreCase, + bool allowMatchingMetadataAttribute) + => TryParse(name, out var value, ignoreCase, allowMatchingMetadataAttribute) ? value : ThrowValueNotFound(name); + +#if NETCOREAPP3_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.DoesNotReturn] +#endif + private static global::Bar.MyEnum ThrowValueNotFound(string? name) + => throw new System.ArgumentException($"Requested value '{name}' was not found."); + + /// + /// Converts the string representation of the name or numeric value of + /// an to the equivalent instance. + /// The return value indicates whether the conversion succeeded. + /// + /// The case-sensitive string representation of the enumeration name or underlying value to convert + /// When this method returns, contains an object of type + /// whose + /// value is represented by if the parse operation succeeds. + /// If the parse operation fails, contains the default value of the underlying type + /// of . This parameter is passed uninitialized. + /// true if the value parameter was converted successfully; otherwise, false. + public static bool TryParse( +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] +#endif + string? name, + out global::Bar.MyEnum value) + => TryParse(name, out value, false, false); + + /// + /// Converts the string representation of the name or numeric value of + /// an to the equivalent instance. + /// The return value indicates whether the conversion succeeded. + /// + /// The string representation of the enumeration name or underlying value to convert + /// When this method returns, contains an object of type + /// whose + /// value is represented by if the parse operation succeeds. + /// If the parse operation fails, contains the default value of the underlying type + /// of . This parameter is passed uninitialized. + /// true to read value in case insensitive mode; false to read value in case sensitive mode. + /// true if the value parameter was converted successfully; otherwise, false. + public static bool TryParse( +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] +#endif + string? name, + out global::Bar.MyEnum value, + bool ignoreCase) + => TryParse(name, out value, ignoreCase, false); + + /// + /// Converts the string representation of the name or numeric value of + /// an to the equivalent instance. + /// The return value indicates whether the conversion succeeded. + /// + /// The string representation of the enumeration name or underlying value to convert + /// When this method returns, contains an object of type + /// whose + /// value is represented by if the parse operation succeeds. + /// If the parse operation fails, contains the default value of the underlying type + /// of . This parameter is passed uninitialized. + /// true to read value in case insensitive mode; false to read value in case sensitive mode. + /// If true, considers the value included in metadata attributes such as + /// [Display] attribute when parsing, otherwise only considers the member names. + /// true if the value parameter was converted successfully; otherwise, false. + public static bool TryParse( +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] +#endif + string? name, + out global::Bar.MyEnum value, + bool ignoreCase, + bool allowMatchingMetadataAttribute) + => ignoreCase + ? TryParseIgnoreCase(name, out value, allowMatchingMetadataAttribute) + : TryParseWithCase(name, out value, allowMatchingMetadataAttribute); + + private static bool TryParseIgnoreCase( +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] +#endif + string? name, + out global::Bar.MyEnum value, + bool allowMatchingMetadataAttribute) + { + + switch (name) + { + case string s when s.Equals(nameof(global::Bar.MyEnum.First), global::System.StringComparison.OrdinalIgnoreCase): + value = global::Bar.MyEnum.First; + return true; + case string s when s.Equals(nameof(global::Bar.MyEnum.Second), global::System.StringComparison.OrdinalIgnoreCase): + value = global::Bar.MyEnum.Second; + return true; + case string s when s.Equals(nameof(global::Bar.MyEnum.Third), global::System.StringComparison.OrdinalIgnoreCase): + value = global::Bar.MyEnum.Third; + return true; + case string s when int.TryParse(name, out var val): + value = (global::Bar.MyEnum)val; + return true; + default: + value = default; + return false; + } + } + + private static bool TryParseWithCase( +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] +#endif + string? name, + out global::Bar.MyEnum value, + bool allowMatchingMetadataAttribute) + { + + switch (name) + { + case nameof(global::Bar.MyEnum.First): + value = global::Bar.MyEnum.First; + return true; + case nameof(global::Bar.MyEnum.Second): + value = global::Bar.MyEnum.Second; + return true; + case nameof(global::Bar.MyEnum.Third): + value = global::Bar.MyEnum.Third; + return true; + case string s when int.TryParse(name, out var val): + value = (global::Bar.MyEnum)val; + return true; + default: + value = default; + return false; + } + } + +#if NETCOREAPP && !NETCOREAPP2_0 && !NETCOREAPP1_1 && !NETCOREAPP1_0 + /// + /// Converts the string representation of the name or numeric value of + /// an to the equivalent instance. + /// + /// The case-sensitive string representation of the enumeration name or underlying value to convert + /// An object of type whose + /// value is represented by + public static global::Bar.MyEnum Parse( +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] +#endif + in ReadOnlySpan name) + => TryParse(name, out var value, false, false) ? value : ThrowValueNotFound(name.ToString()); + + /// + /// Converts the string representation of the name or numeric value of + /// an to the equivalent instance. + /// + /// The case-sensitive string representation of the enumeration name or underlying value to convert + /// true to read value in case insensitive mode; false to read value in case sensitive mode. + /// An object of type whose + /// value is represented by + public static global::Bar.MyEnum Parse( +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] +#endif + in ReadOnlySpan name, + bool ignoreCase) + => TryParse(name, out var value, ignoreCase, false) ? value : ThrowValueNotFound(name.ToString()); + + /// + /// Converts the string representation of the name or numeric value of + /// an to the equivalent instance. + /// + /// The case-sensitive string representation of the enumeration name or underlying value to convert + /// true to read value in case insensitive mode; false to read value in case sensitive mode. + /// If true, considers the value included in metadata attributes such as + /// [Display] attribute when parsing, otherwise only considers the member names. + /// An object of type whose + /// value is represented by + public static global::Bar.MyEnum Parse( +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] +#endif + in ReadOnlySpan name, + bool ignoreCase, + bool allowMatchingMetadataAttribute) + => TryParse(name, out var value, ignoreCase, allowMatchingMetadataAttribute) ? value : ThrowValueNotFound(name.ToString()); + + /// + /// Converts the span representation of the name or numeric value of + /// an to the equivalent instance. + /// The return value indicates whether the conversion succeeded. + /// + /// The span representation of the enumeration name or underlying value to convert + /// When this method returns, contains an object of type + /// whose + /// value is represented by if the parse operation succeeds. + /// If the parse operation fails, contains the default value of the underlying type + /// of . This parameter is passed uninitialized. + /// true if the value parameter was converted successfully; otherwise, false. + public static bool TryParse( +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] +#endif + in ReadOnlySpan name, + out global::Bar.MyEnum value) + => TryParse(name, out value, false, false); + + /// + /// Converts the span representation of the name or numeric value of + /// an to the equivalent instance. + /// The return value indicates whether the conversion succeeded. + /// + /// The span representation of the enumeration name or underlying value to convert + /// When this method returns, contains an object of type + /// whose + /// value is represented by if the parse operation succeeds. + /// If the parse operation fails, contains the default value of the underlying type + /// of . This parameter is passed uninitialized. + /// true to read value in case insensitive mode; false to read value in case sensitive mode. + /// true if the value parameter was converted successfully; otherwise, false. + public static bool TryParse( +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] +#endif + in ReadOnlySpan name, + out global::Bar.MyEnum value, + bool ignoreCase) + => TryParse(name, out value, ignoreCase, false); + + /// + /// Converts the span representation of the name or numeric value of + /// an to the equivalent instance. + /// The return value indicates whether the conversion succeeded. + /// + /// The span representation of the enumeration name or underlying value to convert + /// When this method returns, contains an object of type + /// whose + /// value is represented by if the parse operation succeeds. + /// If the parse operation fails, contains the default value of the underlying type + /// of . This parameter is passed uninitialized. + /// true to read value in case insensitive mode; false to read value in case sensitive mode. + /// If true, considers the value included in metadata attributes such as + /// [Display] attribute when parsing, otherwise only considers the member names. + /// true if the value parameter was converted successfully; otherwise, false. + public static bool TryParse( +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] +#endif + in ReadOnlySpan name, + out global::Bar.MyEnum result, + bool ignoreCase, + bool allowMatchingMetadataAttribute) + => ignoreCase + ? TryParseIgnoreCase(in name, out result, allowMatchingMetadataAttribute) + : TryParseWithCase(in name, out result, allowMatchingMetadataAttribute); + + private static bool TryParseIgnoreCase( +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] +#endif + in ReadOnlySpan name, + out global::Bar.MyEnum result, + bool allowMatchingMetadataAttribute) + { + switch (name) + { + case ReadOnlySpan current when current.Equals(nameof(global::Bar.MyEnum.First).AsSpan(), global::System.StringComparison.OrdinalIgnoreCase): + result = global::Bar.MyEnum.First; + return true; + case ReadOnlySpan current when current.Equals(nameof(global::Bar.MyEnum.Second).AsSpan(), global::System.StringComparison.OrdinalIgnoreCase): + result = global::Bar.MyEnum.Second; + return true; + case ReadOnlySpan current when current.Equals(nameof(global::Bar.MyEnum.Third).AsSpan(), global::System.StringComparison.OrdinalIgnoreCase): + result = global::Bar.MyEnum.Third; + return true; + case ReadOnlySpan current when int.TryParse(name, out var numericResult): + result = (global::Bar.MyEnum)numericResult; + return true; + default: + result = default; + return false; + } + } + + private static bool TryParseWithCase( +#if NETCOREAPP3_0_OR_GREATER + [global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] +#endif + in ReadOnlySpan name, + out global::Bar.MyEnum result, + bool allowMatchingMetadataAttribute) + { + switch (name) + { + case ReadOnlySpan current when current.Equals(nameof(global::Bar.MyEnum.First).AsSpan(), global::System.StringComparison.Ordinal): + result = global::Bar.MyEnum.First; + return true; + case ReadOnlySpan current when current.Equals(nameof(global::Bar.MyEnum.Second).AsSpan(), global::System.StringComparison.Ordinal): + result = global::Bar.MyEnum.Second; + return true; + case ReadOnlySpan current when current.Equals(nameof(global::Bar.MyEnum.Third).AsSpan(), global::System.StringComparison.Ordinal): + result = global::Bar.MyEnum.Third; + return true; + case ReadOnlySpan current when int.TryParse(name, out var numericResult): + result = (global::Bar.MyEnum)numericResult; + return true; + default: + result = default; + return false; + } + } +#endif + + /// + /// Retrieves an array of the values of the members defined in + /// . + /// Note that this returns a new array with every invocation, so + /// should be cached if appropriate. + /// + /// An array of the values defined in + public static global::Bar.MyEnum[] GetValues() + { + return new[] + { + global::Bar.MyEnum.First, + global::Bar.MyEnum.Second, + global::Bar.MyEnum.Third, + }; + } + + /// + /// Retrieves an array of the names of the members defined in + /// . + /// Note that this returns a new array with every invocation, so + /// should be cached if appropriate. + /// + /// An array of the names of the members defined in + public static string[] GetNames() + { + return new[] + { + nameof(global::Bar.MyEnum.First), + nameof(global::Bar.MyEnum.Second), + nameof(global::Bar.MyEnum.Third), + }; + } + } +#pragma warning restore CS0612 // Ignore usages of obsolete members or enums +#pragma warning restore CS0618 // Ignore usages of obsolete members or enums +} + +//------------------------------------------------------------------------------ +// +// This code was generated by the NetEscapades.EnumGenerators source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#nullable enable +namespace System.Runtime.CompilerServices +{ + // this type is needed by the compiler to implement interceptors - it doesn't need to + // come from the runtime itself, though + + [global::System.Diagnostics.Conditional("DEBUG")] // not needed post-build, so: evaporate + [global::System.AttributeUsage(global::System.AttributeTargets.Method, AllowMultiple = true)] + sealed file class InterceptsLocationAttribute : global::System.Attribute + { + public InterceptsLocationAttribute(int version, string data) + { + _ = version; + _ = data; + } + } +} + +#pragma warning disable CS0612 // Ignore usages of obsolete members or enums +#pragma warning disable CS0618 // Ignore usages of obsolete members or enums +namespace NetEscapades.EnumGenerators +{ + static file class EnumInterceptors + { + [global::System.Runtime.CompilerServices.InterceptsLocation(123, "REDACTED")] // Program.cs(41,32) + public static string MyEnumExtensionsToString(this global::System.Enum value) + => global::Foo.MyEnumExtensions.ToStringFast((global::Foo.MyEnum)value); + + [global::System.Runtime.CompilerServices.InterceptsLocation(123, "REDACTED")] // Program.cs(37,32) + [global::System.Runtime.CompilerServices.InterceptsLocation(123, "REDACTED")] // Program.cs(38,42) + [global::System.Runtime.CompilerServices.InterceptsLocation(123, "REDACTED")] // Program.cs(40,31) + public static bool MyEnumExtensionsHasFlag(this global::System.Enum value, global::System.Enum flag) + => global::Foo.MyEnumExtensions.HasFlagFast((global::Foo.MyEnum)value, (global::Foo.MyEnum)flag); + + } +} +#pragma warning restore CS0612 // Ignore usages of obsolete members or enums +#pragma warning restore CS0618 // Ignore usages of obsolete members or enums + + +//------------------------------------------------------------------------------ +// +// This code was generated by the NetEscapades.EnumGenerators source generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#nullable enable +namespace System.Runtime.CompilerServices +{ + // this type is needed by the compiler to implement interceptors - it doesn't need to + // come from the runtime itself, though + + [global::System.Diagnostics.Conditional("DEBUG")] // not needed post-build, so: evaporate + [global::System.AttributeUsage(global::System.AttributeTargets.Method, AllowMultiple = true)] + sealed file class InterceptsLocationAttribute : global::System.Attribute + { + public InterceptsLocationAttribute(int version, string data) + { + _ = version; + _ = data; + } + } +} + +#pragma warning disable CS0612 // Ignore usages of obsolete members or enums +#pragma warning disable CS0618 // Ignore usages of obsolete members or enums +namespace NetEscapades.EnumGenerators +{ + static file class EnumInterceptors + { + [global::System.Runtime.CompilerServices.InterceptsLocation(123, "REDACTED")] // Program.cs(42,41) + public static string MyEnumExtensionsToString(this global::System.Enum value) + => global::Bar.MyEnumExtensions.ToStringFast((global::Bar.MyEnum)value); + + [global::System.Runtime.CompilerServices.InterceptsLocation(123, "REDACTED")] // Program.cs(39,33) + public static bool MyEnumExtensionsHasFlag(this global::System.Enum value, global::System.Enum flag) + => global::Bar.MyEnumExtensions.HasFlagFast((global::Bar.MyEnum)value, (global::Bar.MyEnum)flag); + + } +} +#pragma warning restore CS0612 // Ignore usages of obsolete members or enums +#pragma warning restore CS0618 // Ignore usages of obsolete members or enums + +] \ No newline at end of file diff --git a/tests/NetEscapades.EnumGenerators.Tests/SourceGenerationHelperSnapshotTests.cs b/tests/NetEscapades.EnumGenerators.Tests/SourceGenerationHelperSnapshotTests.cs index 90d7272..d6dba01 100644 --- a/tests/NetEscapades.EnumGenerators.Tests/SourceGenerationHelperSnapshotTests.cs +++ b/tests/NetEscapades.EnumGenerators.Tests/SourceGenerationHelperSnapshotTests.cs @@ -31,8 +31,7 @@ public Task GeneratesEnumCorrectly() isDisplayAttributeUsed: false, isInterceptable: true); - var sb = new StringBuilder(); - var result = SourceGenerationHelper.GenerateExtensionClass(sb, value); + var result = SourceGenerationHelper.GenerateExtensionClass(value).Content; return Verifier.Verify(result) .ScrubExpectedChanges() @@ -57,8 +56,7 @@ public Task GeneratesFlagsEnumCorrectly() isDisplayAttributeUsed: false, isInterceptable: true); - var sb = new StringBuilder(); - var result = SourceGenerationHelper.GenerateExtensionClass(sb, value); + var result = SourceGenerationHelper.GenerateExtensionClass(value).Content; return Verifier.Verify(result) .ScrubExpectedChanges()