using System.Globalization;
using Microsoft.CodeAnalysis;
namespace Dpz.Core.SourceGenerator;
/// <summary>
/// 源生成器内部统一的 Roslyn 符号显示工具。
/// </summary>
internal static class SymbolDisplay
{
private static readonly SymbolDisplayFormat TypeNameFormat =
SymbolDisplayFormat.FullyQualifiedFormat.WithMiscellaneousOptions(
SymbolDisplayFormat.FullyQualifiedFormat.MiscellaneousOptions
| SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier
);
/// <summary>
/// 输出可直接写入生成源码的完整类型名称,并保留 nullable 标记。
/// </summary>
internal static string ToFullyQualifiedTypeName(ITypeSymbol type) =>
type.ToDisplayString(TypeNameFormat);
/// <summary>
/// 将接口参数默认值转换为方法签名中的 C# 字面量。
/// </summary>
internal static string ToDefaultValueLiteral(IParameterSymbol parameter)
{
if (!parameter.HasExplicitDefaultValue)
{
return string.Empty;
}
if (parameter.ExplicitDefaultValue is null)
{
return " = default";
}
if (parameter.Type.SpecialType == SpecialType.System_String)
{
return " = " + ToCSharpStringLiteral((string)parameter.ExplicitDefaultValue);
}
if (parameter.Type.SpecialType == SpecialType.System_Boolean)
{
return (bool)parameter.ExplicitDefaultValue ? " = true" : " = false";
}
if (parameter.Type.TypeKind == TypeKind.Enum)
{
return " = "
+ ToFullyQualifiedTypeName(parameter.Type)
+ "."
+ parameter.ExplicitDefaultValue;
}
return " = "
+ Convert.ToString(parameter.ExplicitDefaultValue, CultureInfo.InvariantCulture);
}
internal static string ToCSharpStringLiteral(string value)
{
return "\"" + value.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\"";
}
}
⚠⚠ 以下内容为AI分析的结果,请根据实际情况进行判断。
代码解释
这是一个用于 Roslyn 源代码生成器的辅助工具类,主要用于将编译时的符号(Symbol)信息转换为可以直接写入生成代码的字符串格式。
主要功能
1. 类型名称格式化 (TypeNameFormat)
private static readonly SymbolDisplayFormat TypeNameFormat = ...
- 定义了一个静态的显示格式配置
- 基于
FullyQualifiedFormat(完全限定名格式,如global::System.String) - 额外添加了
IncludeNullableReferenceTypeModifier选项,使得可空引用类型标记(?)会被保留
2. 完全限定类型名转换 (ToFullyQualifiedTypeName)
internal static string ToFullyQualifiedTypeName(ITypeSymbol type)
- 将 Roslyn 的
ITypeSymbol转换为完整的类型名称字符串 - 例如:
System.String?→global::System.String? - 这样生成的代码不会有命名空间冲突问题
3. 参数默认值转换 (ToDefaultValueLiteral)
internal static string ToDefaultValueLiteral(IParameterSymbol parameter)
这是核心方法,将接口或方法参数的默认值转换为 C# 代码字符串:
| 情况 | 返回值示例 |
|---|---|
| 无默认值 | "" (空字符串) |
null | " = default" |
| 字符串类型 | " = \"hello\"" |
| 布尔类型 | " = true" 或 " = false" |
| 枚举类型 | " = global::MyNamespace.MyEnum.Value" |
| 数值类型 | " = 42" |
4. 字符串字面量转义 (ToCSharpStringLiteral)
internal static string ToCSharpStringLiteral(string value)
- 将普通字符串转换为 C# 代码中的字符串字面量
- 处理反斜杠和双引号的转义
- 例如:
hello"world→"hello\"world"
应用场景
这个工具类典型用于 Source Generator 中,当需要生成实现接口的代理类时:
// 源接口
interface IService
{
void Method(string? name = "default", int count = 5);
}
// 源生成器会使用此工具类生成:
class ServiceProxy : IService
{
public void Method(string? name = "default", int count = 5) { ... }
}
技术亮点
- ✅ 使用
InvariantCulture确保跨文化数值格式一致性 - ✅ 完整处理可空引用类型(C# 8.0+)
- ✅ 避免生成代码的命名空间污染(使用
global::) - ✅ 正确处理各种特殊类型(枚举、布尔、字符串等)
评论加载中...