Skip to content

Commit

Permalink
Ensure we can handle enums with the same name in different namespaces (
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewlock authored Oct 23, 2024
1 parent e87b3d2 commit 40c3516
Show file tree
Hide file tree
Showing 5 changed files with 1,360 additions and 13 deletions.
9 changes: 4 additions & 5 deletions src/NetEscapades.EnumGenerators/EnumGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<EnumToGenerate>? GetEnumToGenerateFromGenericAssemblyAttribute(
Expand Down Expand Up @@ -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
}
30 changes: 26 additions & 4 deletions src/NetEscapades.EnumGenerators/SourceGenerationHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,9 @@ public class InterceptableAttribute<T> : 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(@"
Expand Down Expand Up @@ -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(
$$"""
Expand Down Expand Up @@ -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)
{
Expand Down
58 changes: 58 additions & 0 deletions tests/NetEscapades.EnumGenerators.Tests/InterceptorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<EnumGenerator, TrackingNames>(new(_analyzerOpts, _features, input));

Assert.Empty(diagnostics);
return Verifier.Verify(output).ScrubExpectedChanges().UseDirectory("Snapshots");
}

[Fact]
public Task CanInterceptMultipleEnumsToString()
{
Expand Down
Loading

0 comments on commit 40c3516

Please sign in to comment.