Skip to content

Commit

Permalink
refactor: enum source generator
Browse files Browse the repository at this point in the history
  • Loading branch information
MarsonShine committed Jan 25, 2024
1 parent 1325a8c commit 24aab6d
Show file tree
Hide file tree
Showing 19 changed files with 236 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ internal class EnumToGenerator : IIncrementalGenerator
{
public void Initialize(IncrementalGeneratorInitializationContext context)
{
//Debugger.Launch();
// 添加标记特性给编译器
context.RegisterPostInitializationOutput(ctx => ctx.AddSource(
"EnumExtensionsAttribute.g.cs",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,9 @@ namespace MySourceGenerator.Enums2;
[Generator]
internal class EnumToGenerator : IIncrementalGenerator
{
private const string EnumExtensionsAttribute = "MySourceGenerator.Enums.EnumExtensionsAttribute";
private const string EnumExtensionsAttribute = "MySourceGenerator.Enums2.EnumExtensionsAttribute";
public void Initialize(IncrementalGeneratorInitializationContext context)
{
//Debugger.Launch();
// 添加标记特性给编译器
context.RegisterPostInitializationOutput(ctx => ctx.AddSource(
"EnumExtensionsAttribute.g.cs",
Expand All @@ -33,7 +32,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
transform: static (ctx, _) => GetSemanticTargetForGeneration(ctx)) // 使用 [EnumExtensions] 属性选择枚举并提取详细信息
.Where(static m => m is not null); // 不需要关心过滤器输出的错误

IncrementalValueProvider<(Compilation Compilation, ImmutableArray<EnumDeclarationSyntax> EnumDeclarationSyntaxes)> compilationAndEnums = context.CompilationProvider.Combine(enumDeclarations.Collect());
IncrementalValueProvider<(Compilation Compilation, ImmutableArray<EnumDeclarationSyntax?> EnumDeclarationSyntaxes)> compilationAndEnums = context.CompilationProvider.Combine(enumDeclarations.Collect());

// 上面的两部可以用 ForAttributeWithMetadataName 一步完成
//IncrementalValuesProvider<EnumToGenerate?> enumsToGenerate = context.SyntaxProvider
Expand Down Expand Up @@ -111,7 +110,7 @@ static void Execute(Compilation compilation, ImmutableArray<EnumDeclarationSynta
{
// generate the source code and add it to the output
string result = SourceGenerationHelper.GenerateExtensionClass(enumsToGenerate);
context.AddSource("EnumExtensions.g.cs", SourceText.From(result, Encoding.UTF8));
context.AddSource("EnumExtensions2.g.cs", SourceText.From(result, Encoding.UTF8));
}

}
Expand Down Expand Up @@ -140,7 +139,7 @@ static List<EnumToGenerate> GetTypesToGenerate(Compilation compilation, IEnumera
}

string enumName = enumSymbol.ToString();
string extensionName = enumName + "EnumExtensions";
string extensionName = "EnumExtensions";

foreach (AttributeData attributeData in enumSymbol.GetAttributes())
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;

namespace MySourceGenerator.Enums2;
public static class SourceGenerationHelper
{
public const string Attribute = @"
namespace MySourceGenerator.Enums
namespace MySourceGenerator.Enums2
{
[System.AttributeUsage(System.AttributeTargets.Enum)]
public class EnumExtensionsAttribute : System.Attribute
{
public string ExtensionClassName { get; set; }
}
}
";
Expand All @@ -19,7 +20,7 @@ public static string GenerateExtensionClass(List<EnumToGenerate> enumToGenerates
{
var sb = new StringBuilder();
sb.Append(@"
namespace MySourceGenerator.Enums
namespace MySourceGenerator.Enums2
{");
foreach (var enumToGenerate in enumToGenerates)
{
Expand All @@ -38,7 +39,7 @@ public static string ToStringFast(this ").Append(enumToGenerate.Name).Append(@"
}
sb.Append(@"
_ => value.ToString(),
};
};
}
");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

namespace MySourceGenerator
{

public partial class UserClass
{
private void GeneratedMethod()
{
// generated code
Console.WriteLine("Hello from generated code!");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace MySourceGenerator
{
public class GeneratedClass
{
public static void GeneratedMethod()
{
Console.WriteLine("GeneratedMethod...");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

namespace MySourceGenerator.Enums
{
[System.AttributeUsage(System.AttributeTargets.Enum)]
public class EnumExtensionsAttribute : System.Attribute
{

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@

namespace MySourceGenerator.Enums2
{
public static partial class DirectionExtensions
{
public static string ToStringFast(this MySourceGenerator.Program.Direction value)
=> value switch
{
MySourceGenerator.Program.Direction.Left => nameof(MySourceGenerator.Program.Direction.Left),
MySourceGenerator.Program.Direction.Right => nameof(MySourceGenerator.Program.Direction.Right),
MySourceGenerator.Program.Direction.Up => nameof(MySourceGenerator.Program.Direction.Up),
MySourceGenerator.Program.Direction.Down => nameof(MySourceGenerator.Program.Direction.Down),
_ => value.ToString(),
};
}

public static partial class EnumExtensions
{
public static string ToStringFast(this MySourceGenerator.Program.Color value)
=> value switch
{
MySourceGenerator.Program.Color.Red => nameof(MySourceGenerator.Program.Color.Red),
MySourceGenerator.Program.Color.Green => nameof(MySourceGenerator.Program.Color.Green),
MySourceGenerator.Program.Color.Yellow => nameof(MySourceGenerator.Program.Color.Yellow),
MySourceGenerator.Program.Color.Pink => nameof(MySourceGenerator.Program.Color.Pink),
MySourceGenerator.Program.Color.Black => nameof(MySourceGenerator.Program.Color.Black),
_ => value.ToString(),
};
}

public static partial class EnumExtensions
{
public static string ToStringFast(this MySourceGenerator.NestedEnum.RoleEnum value)
=> value switch
{
MySourceGenerator.NestedEnum.RoleEnum.None => nameof(MySourceGenerator.NestedEnum.RoleEnum.None),
MySourceGenerator.NestedEnum.RoleEnum.Admin => nameof(MySourceGenerator.NestedEnum.RoleEnum.Admin),
_ => value.ToString(),
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

namespace MySourceGenerator.Enums2
{
[System.AttributeUsage(System.AttributeTargets.Enum)]
public class EnumExtensionsAttribute : System.Attribute
{
public string ExtensionClassName { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
 // Auto-generated code
using System;

namespace MySourceGenerator
{
public static partial class Program
{
static partial void HelloFrom(string name) =>
Console.WriteLine($"Generator says: Hi from '{name}'");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

namespace MySourceGenerator
{

public partial class UserClass
{
private void GeneratedMethod()
{
// generated code
Console.WriteLine("Hello from generated code!");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace MySourceGenerator
{
public class GeneratedClass
{
public static void GeneratedMethod()
{
Console.WriteLine("GeneratedMethod...");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

namespace MySourceGenerator.Enums
{
[System.AttributeUsage(System.AttributeTargets.Enum)]
public class EnumExtensionsAttribute : System.Attribute
{

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@

namespace MySourceGenerator.Enums2
{
public static partial class DirectionExtensions
{
public static string ToStringFast(this MySourceGenerator.Program.Direction value)
=> value switch
{
MySourceGenerator.Program.Direction.Left => nameof(MySourceGenerator.Program.Direction.Left),
MySourceGenerator.Program.Direction.Right => nameof(MySourceGenerator.Program.Direction.Right),
MySourceGenerator.Program.Direction.Up => nameof(MySourceGenerator.Program.Direction.Up),
MySourceGenerator.Program.Direction.Down => nameof(MySourceGenerator.Program.Direction.Down),
_ => value.ToString(),
};
}

public static partial class EnumExtensions
{
public static string ToStringFast(this MySourceGenerator.Program.Color value)
=> value switch
{
MySourceGenerator.Program.Color.Red => nameof(MySourceGenerator.Program.Color.Red),
MySourceGenerator.Program.Color.Green => nameof(MySourceGenerator.Program.Color.Green),
MySourceGenerator.Program.Color.Yellow => nameof(MySourceGenerator.Program.Color.Yellow),
MySourceGenerator.Program.Color.Pink => nameof(MySourceGenerator.Program.Color.Pink),
MySourceGenerator.Program.Color.Black => nameof(MySourceGenerator.Program.Color.Black),
_ => value.ToString(),
};
}

public static partial class EnumExtensions
{
public static string ToStringFast(this MySourceGenerator.NestedEnum.RoleEnum value)
=> value switch
{
MySourceGenerator.NestedEnum.RoleEnum.None => nameof(MySourceGenerator.NestedEnum.RoleEnum.None),
MySourceGenerator.NestedEnum.RoleEnum.Admin => nameof(MySourceGenerator.NestedEnum.RoleEnum.Admin),
_ => value.ToString(),
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

namespace MySourceGenerator.Enums2
{
[System.AttributeUsage(System.AttributeTargets.Enum)]
public class EnumExtensionsAttribute : System.Attribute
{
public string ExtensionClassName { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
 // Auto-generated code
using System;

namespace MySourceGenerator
{
public static partial class Program
{
static partial void HelloFrom(string name) =>
Console.WriteLine($"Generator says: Hi from '{name}'");
}
}
38 changes: 20 additions & 18 deletions CSharpGuide/SourceGeneratorDemo/SourceGeneratorGuide/Program.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// See https://aka.ms/new-console-template for more information
using MySourceGenerator.Enums;
using MySourceGenerator.Enums2;
using MySourceGenerator.NestedEnum;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

Expand All @@ -12,35 +13,37 @@ static void Main(string[] args)
HelloFrom("Generated Code");
// Console.ReadLine();

//Direction c = Direction.Down;
//Console.WriteLine(c.ToStringFast());
Direction c = Direction.Down;
Console.WriteLine(c.ToStringFast());
//Console.WriteLine(c.ToDescription());

Color.Red.ToStringFast();
//_ = Color.Red.ToStringFast();

//Color c2 = Color.Red;
//Console.WriteLine(c2.ToStringFast());
//Console.WriteLine(c2.ToDescription());
// Console.WriteLine()
GeneratedClass.GeneratedMethod();
new UserClass().UserMethod();

RoleEnum.Admin.ToStringFast();
}

static partial void HelloFrom(string name);

//[EnumExtensions(ExtensionClassName = "DirectionExtensions")]
//public enum Direction
//{
// [Description("左")]
// Left,
// [Description("右")]
// Right,
// [Description("上")]
// Up,
// [Description("下")]
// Down,
//}
[EnumExtensions]
[EnumExtensions(ExtensionClassName = "DirectionExtensions")]
public enum Direction
{
[Description("左")]
Left,
[Description("右")]
Right,
[Description("上")]
Up,
[Description("下")]
Down,
}
[Enums2.EnumExtensions]
public enum Color
{
[Display(Name = "红")]
Expand All @@ -60,5 +63,4 @@ partial class MyRecord
public string ITem1 { get; }
public int ITem2 { get; }
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,21 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net8.0</TargetFrameworks>
<TargetFrameworks>net8.0;net7.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>preview</LangVersion>
<!-- https://andrewlock.net/creating-a-source-generator-part-6-saving-source-generator-output-in-source-control/ -->
<!--以下设置在调试模式(开发阶段)设置比较方便,发布成nuget包建议取消-->
<!-- 设置编译器生成文件,生成在 obj 文件夹中,如何想要将文件添加到项目中来(obj 文件夹一般会被 git ignore 排除),可以设置<CompilerGeneratedFilesOutputPath>属性 -->
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<!-- <CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath> -->
<GeneratedFolder>Generated</GeneratedFolder>
<CompilerGeneratedFilesOutputPath>$(GeneratedFolder)\$(TargetFramework)</CompilerGeneratedFilesOutputPath>
</PropertyGroup>


<!--CompilerGeneratedFilesOutputPath 生成到项目,可以下面设置将源生成器的输出排除在编译之外-->
<ItemGroup>
<Compile Remove="$(GeneratedFolder)/**/*.cs"></Compile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MySourceGenerator\MySourceGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
using System.ComponentModel;
using MySourceGenerator.Enums2;
using System.ComponentModel;

namespace MySourceGenerator
{
namespace NestedEnum
{
[EnumExtensions]
public enum RoleEnum
{
None = 0,
Admin = 1
}
}
public partial class UserClass
{
[AutoNotify]
Expand Down
Loading

0 comments on commit 24aab6d

Please sign in to comment.