mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-03-25 13:33:28 +08:00
refactor(source-generators): 优化ContextAware生成器实现并添加快照测试
- 为ContextAwareGenerator添加详细的XML文档注释 - 简化接口验证逻辑,合并条件判断语句 - 修正特性数据参数命名,统一使用attr命名 - 为接口实现方法添加global::前缀以确保类型解析正确 - 移除未使用的回退方法体,简化方法实现逻辑 - 新增GeneratorSnapshotTest通用快照测试类 - 添加ContextAwareGeneratorSnapshotTests快照测试 - 移除原有的硬编码期望值测试方法 - 修正接口实现中的全局命名空间前缀格式
This commit is contained in:
parent
02e2e31e95
commit
603b06325d
@ -22,4 +22,8 @@
|
|||||||
<ProjectReference Include="..\GFramework.SourceGenerators\GFramework.SourceGenerators.csproj"/>
|
<ProjectReference Include="..\GFramework.SourceGenerators\GFramework.SourceGenerators.csproj"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="rule\snapshots\ContextAwareGenerator\"/>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@ -0,0 +1,70 @@
|
|||||||
|
using Microsoft.CodeAnalysis.CSharp.Testing;
|
||||||
|
using Microsoft.CodeAnalysis.Testing;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace GFramework.SourceGenerators.Tests.core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 用于测试源代码生成器的快照测试类
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TGenerator">要测试的源代码生成器类型</typeparam>
|
||||||
|
public static class GeneratorSnapshotTest<TGenerator>
|
||||||
|
where TGenerator : new()
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 运行源代码生成器的快照测试
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="source">输入的源代码字符串</param>
|
||||||
|
/// <param name="snapshotFolder">快照文件存储的文件夹路径</param>
|
||||||
|
/// <returns>异步任务</returns>
|
||||||
|
public static async Task RunAsync(
|
||||||
|
string source,
|
||||||
|
string snapshotFolder)
|
||||||
|
{
|
||||||
|
var test = new CSharpSourceGeneratorTest<TGenerator, DefaultVerifier>
|
||||||
|
{
|
||||||
|
TestState =
|
||||||
|
{
|
||||||
|
Sources = { source }
|
||||||
|
},
|
||||||
|
TestBehaviors = TestBehaviors.SkipGeneratedSourcesCheck,
|
||||||
|
DisabledDiagnostics = { "GF_Common_Trace_001" }
|
||||||
|
};
|
||||||
|
|
||||||
|
await test.RunAsync();
|
||||||
|
|
||||||
|
var generated = test.TestState.GeneratedSources;
|
||||||
|
|
||||||
|
foreach (var (filename, content) in generated)
|
||||||
|
{
|
||||||
|
var path = Path.Combine(
|
||||||
|
snapshotFolder,
|
||||||
|
filename);
|
||||||
|
|
||||||
|
if (!File.Exists(path))
|
||||||
|
{
|
||||||
|
// 第一次运行:生成 snapshot
|
||||||
|
Directory.CreateDirectory(Path.GetDirectoryName(path)!);
|
||||||
|
await File.WriteAllTextAsync(path, content.ToString());
|
||||||
|
|
||||||
|
Assert.Fail(
|
||||||
|
$"Snapshot not found. Generated new snapshot at:\n{path}");
|
||||||
|
}
|
||||||
|
|
||||||
|
var expected = await File.ReadAllTextAsync(path);
|
||||||
|
|
||||||
|
Assert.That(
|
||||||
|
Normalize(expected),
|
||||||
|
Is.EqualTo(Normalize(content.ToString())),
|
||||||
|
$"Snapshot mismatch: {filename}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 标准化文本内容,将换行符统一为\n并去除首尾空白
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="text">要标准化的文本</param>
|
||||||
|
/// <returns>标准化后的文本</returns>
|
||||||
|
private static string Normalize(string text)
|
||||||
|
=> text.Replace("\r\n", "\n").Trim();
|
||||||
|
}
|
||||||
@ -0,0 +1,69 @@
|
|||||||
|
using GFramework.SourceGenerators.rule;
|
||||||
|
using GFramework.SourceGenerators.Tests.core;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace GFramework.SourceGenerators.Tests.rule;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 上下文感知生成器快照测试类
|
||||||
|
/// 用于测试ContextAwareGenerator源代码生成器的输出快照
|
||||||
|
/// </summary>
|
||||||
|
[TestFixture]
|
||||||
|
public class ContextAwareGeneratorSnapshotTests
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 测试ContextAwareGenerator源代码生成器的快照功能
|
||||||
|
/// 验证生成器对带有ContextAware特性的类的处理结果
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>异步任务,无返回值</returns>
|
||||||
|
[Test]
|
||||||
|
public async Task Snapshot_ContextAwareGenerator()
|
||||||
|
{
|
||||||
|
// 定义测试用的源代码,包含ContextAware特性和相关接口定义
|
||||||
|
const string source = """
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GFramework.SourceGenerators.Abstractions.rule
|
||||||
|
{
|
||||||
|
[AttributeUsage(AttributeTargets.Class)]
|
||||||
|
public sealed class ContextAwareAttribute : Attribute { }
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace GFramework.Core.Abstractions.rule
|
||||||
|
{
|
||||||
|
public interface IContextAware
|
||||||
|
{
|
||||||
|
void SetContext(
|
||||||
|
GFramework.Core.Abstractions.architecture.IArchitectureContext context);
|
||||||
|
|
||||||
|
GFramework.Core.Abstractions.architecture.IArchitectureContext GetContext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace GFramework.Core.Abstractions.architecture
|
||||||
|
{
|
||||||
|
public interface IArchitectureContext { }
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace TestApp
|
||||||
|
{
|
||||||
|
using GFramework.SourceGenerators.Abstractions.rule;
|
||||||
|
using GFramework.Core.Abstractions.rule;
|
||||||
|
|
||||||
|
[ContextAware]
|
||||||
|
public partial class MyRule : IContextAware
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
|
||||||
|
// 执行生成器快照测试,将生成的代码与预期快照进行比较
|
||||||
|
await GeneratorSnapshotTest<ContextAwareGenerator>.RunAsync(
|
||||||
|
source,
|
||||||
|
snapshotFolder: Path.Combine(
|
||||||
|
TestContext.CurrentContext.TestDirectory,
|
||||||
|
"rule",
|
||||||
|
"snapshots",
|
||||||
|
"ContextAwareGenerator"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
using GFramework.SourceGenerators.rule;
|
using GFramework.SourceGenerators.rule;
|
||||||
using GFramework.SourceGenerators.Tests.core;
|
using GFramework.SourceGenerators.Tests.core;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
@ -7,83 +7,6 @@ namespace GFramework.SourceGenerators.Tests.rule;
|
|||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class ContextAwareGeneratorTests
|
public class ContextAwareGeneratorTests
|
||||||
{
|
{
|
||||||
[Test]
|
|
||||||
public async Task Generates_ContextAware_Code()
|
|
||||||
{
|
|
||||||
const string source = """
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace GFramework.SourceGenerators.Abstractions.rule
|
|
||||||
{
|
|
||||||
[AttributeUsage(AttributeTargets.Class)]
|
|
||||||
public sealed class ContextAwareAttribute : Attribute
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace TestApp
|
|
||||||
{
|
|
||||||
using GFramework.SourceGenerators.Abstractions.rule;
|
|
||||||
|
|
||||||
[ContextAware]
|
|
||||||
public partial class MyRule
|
|
||||||
: GFramework.Core.Abstractions.rule.IContextAware
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
""";
|
|
||||||
|
|
||||||
const string frameworkStub = """
|
|
||||||
namespace GFramework.Core.Abstractions.rule
|
|
||||||
{
|
|
||||||
public interface IContextAware
|
|
||||||
{
|
|
||||||
void SetContext(
|
|
||||||
GFramework.Core.Abstractions.architecture.IArchitectureContext context);
|
|
||||||
|
|
||||||
GFramework.Core.Abstractions.architecture.IArchitectureContext GetContext();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace GFramework.Core.Abstractions.architecture
|
|
||||||
{
|
|
||||||
public interface IArchitectureContext {}
|
|
||||||
}
|
|
||||||
""";
|
|
||||||
|
|
||||||
const string expected = """
|
|
||||||
// <auto-generated/>
|
|
||||||
#nullable enable
|
|
||||||
|
|
||||||
namespace TestApp;
|
|
||||||
|
|
||||||
partial class MyRule
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 自动注入的架构上下文
|
|
||||||
/// </summary>
|
|
||||||
protected GFramework.Core.Abstractions.architecture.IArchitectureContext Context { get; private set; } = null!;
|
|
||||||
|
|
||||||
void global::GFramework.Core.Abstractions.rule.IContextAware.SetContext(
|
|
||||||
global::GFramework.Core.Abstractions.architecture.IArchitectureContext context)
|
|
||||||
{
|
|
||||||
Context = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
global::GFramework.Core.Abstractions.architecture.IArchitectureContext
|
|
||||||
global::GFramework.Core.Abstractions.rule.IContextAware.GetContext()
|
|
||||||
{
|
|
||||||
return Context;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
""";
|
|
||||||
|
|
||||||
await GeneratorTest<ContextAwareGenerator>.RunAsync(
|
|
||||||
source + "\n" + frameworkStub,
|
|
||||||
("MyRule.ContextAware.g.cs", expected)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public async Task Generates_ContextAware_Code_When_Interface_Inherits_IContextAware()
|
public async Task Generates_ContextAware_Code_When_Interface_Inherits_IContextAware()
|
||||||
{
|
{
|
||||||
@ -145,20 +68,20 @@ public class ContextAwareGeneratorTests
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
protected GFramework.Core.Abstractions.architecture.IArchitectureContext Context { get; private set; } = null!;
|
protected GFramework.Core.Abstractions.architecture.IArchitectureContext Context { get; private set; } = null!;
|
||||||
|
|
||||||
void GFramework.Core.Abstractions.rule.IContextAware.SetContext(
|
void global::GFramework.Core.Abstractions.rule.IContextAware.SetContext(global::GFramework.Core.Abstractions.architecture.IArchitectureContext context)
|
||||||
GFramework.Core.Abstractions.architecture.IArchitectureContext context)
|
|
||||||
{
|
{
|
||||||
Context = context;
|
Context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
GFramework.Core.Abstractions.architecture.IArchitectureContext
|
global::GFramework.Core.Abstractions.architecture.IArchitectureContext global::GFramework.Core.Abstractions.rule.IContextAware.GetContext()
|
||||||
GFramework.Core.Abstractions.rule.IContextAware.GetContext()
|
|
||||||
{
|
{
|
||||||
return Context;
|
return Context;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
""";
|
""";
|
||||||
|
|
||||||
|
|
||||||
await GeneratorTest<ContextAwareGenerator>.RunAsync(
|
await GeneratorTest<ContextAwareGenerator>.RunAsync(
|
||||||
source + "\n" + frameworkStub,
|
source + "\n" + frameworkStub,
|
||||||
("MyRule.ContextAware.g.cs", expected)
|
("MyRule.ContextAware.g.cs", expected)
|
||||||
|
|||||||
@ -8,14 +8,32 @@ using Microsoft.CodeAnalysis.CSharp.Syntax;
|
|||||||
|
|
||||||
namespace GFramework.SourceGenerators.rule;
|
namespace GFramework.SourceGenerators.rule;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 上下文感知生成器,用于为标记了ContextAware特性的类自动生成IContextAware接口实现
|
||||||
|
/// </summary>
|
||||||
[Generator]
|
[Generator]
|
||||||
public sealed class ContextAwareGenerator : MetadataAttributeClassGeneratorBase
|
public sealed class ContextAwareGenerator : MetadataAttributeClassGeneratorBase
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 获取特性的元数据名称
|
||||||
|
/// </summary>
|
||||||
protected override string AttributeMetadataName =>
|
protected override string AttributeMetadataName =>
|
||||||
$"{PathContests.SourceGeneratorsAbstractionsPath}.rule.ContextAwareAttribute";
|
$"{PathContests.SourceGeneratorsAbstractionsPath}.rule.ContextAwareAttribute";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取特性的短名称(不包含后缀)
|
||||||
|
/// </summary>
|
||||||
protected override string AttributeShortNameWithoutSuffix => "ContextAware";
|
protected override string AttributeShortNameWithoutSuffix => "ContextAware";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 验证符号是否符合生成条件
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="context">源生产上下文</param>
|
||||||
|
/// <param name="compilation">编译对象</param>
|
||||||
|
/// <param name="syntax">类声明语法节点</param>
|
||||||
|
/// <param name="symbol">命名类型符号</param>
|
||||||
|
/// <param name="attr">特性数据</param>
|
||||||
|
/// <returns>验证是否通过</returns>
|
||||||
protected override bool ValidateSymbol(
|
protected override bool ValidateSymbol(
|
||||||
SourceProductionContext context,
|
SourceProductionContext context,
|
||||||
Compilation compilation,
|
Compilation compilation,
|
||||||
@ -26,16 +44,8 @@ public sealed class ContextAwareGenerator : MetadataAttributeClassGeneratorBase
|
|||||||
var iContextAware = compilation.GetTypeByMetadataName(
|
var iContextAware = compilation.GetTypeByMetadataName(
|
||||||
$"{PathContests.CoreAbstractionsNamespace}.rule.IContextAware");
|
$"{PathContests.CoreAbstractionsNamespace}.rule.IContextAware");
|
||||||
|
|
||||||
if (iContextAware is null)
|
if (iContextAware is null ||
|
||||||
{
|
!symbol.AllInterfaces.Any(i =>
|
||||||
context.ReportDiagnostic(Diagnostic.Create(
|
|
||||||
ContextAwareDiagnostic.ClassMustImplementIContextAware,
|
|
||||||
syntax.Identifier.GetLocation(),
|
|
||||||
symbol.Name));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!symbol.AllInterfaces.Any(i =>
|
|
||||||
SymbolEqualityComparer.Default.Equals(i, iContextAware)))
|
SymbolEqualityComparer.Default.Equals(i, iContextAware)))
|
||||||
{
|
{
|
||||||
context.ReportDiagnostic(Diagnostic.Create(
|
context.ReportDiagnostic(Diagnostic.Create(
|
||||||
@ -49,12 +59,12 @@ public sealed class ContextAwareGenerator : MetadataAttributeClassGeneratorBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 生成源代码
|
/// 生成源代码
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="context">源生产上下文</param>
|
/// <param name="context">源生产上下文</param>
|
||||||
/// <param name="compilation">编译对象</param>
|
/// <param name="compilation">编译对象</param>
|
||||||
/// <param name="symbol">命名类型符号</param>
|
/// <param name="symbol">命名类型符号</param>
|
||||||
/// <param name="attr">属性数据</param>
|
/// <param name="attr">特性数据</param>
|
||||||
/// <returns>生成的源代码字符串</returns>
|
/// <returns>生成的源代码字符串</returns>
|
||||||
protected override string Generate(
|
protected override string Generate(
|
||||||
SourceProductionContext context,
|
SourceProductionContext context,
|
||||||
@ -65,8 +75,9 @@ public sealed class ContextAwareGenerator : MetadataAttributeClassGeneratorBase
|
|||||||
var ns = symbol.ContainingNamespace.IsGlobalNamespace
|
var ns = symbol.ContainingNamespace.IsGlobalNamespace
|
||||||
? null
|
? null
|
||||||
: symbol.ContainingNamespace.ToDisplayString();
|
: symbol.ContainingNamespace.ToDisplayString();
|
||||||
|
|
||||||
var iContextAware = compilation.GetTypeByMetadataName(
|
var iContextAware = compilation.GetTypeByMetadataName(
|
||||||
$"{PathContests.CoreAbstractionsNamespace}.rule.IContextAware");
|
$"{PathContests.CoreAbstractionsNamespace}.rule.IContextAware")!;
|
||||||
|
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
sb.AppendLine("// <auto-generated/>");
|
sb.AppendLine("// <auto-generated/>");
|
||||||
@ -83,18 +94,27 @@ public sealed class ContextAwareGenerator : MetadataAttributeClassGeneratorBase
|
|||||||
sb.AppendLine("{");
|
sb.AppendLine("{");
|
||||||
|
|
||||||
GenerateContextProperty(sb);
|
GenerateContextProperty(sb);
|
||||||
GenerateInterfaceImplementations(sb, iContextAware!);
|
GenerateInterfaceImplementations(sb, iContextAware);
|
||||||
|
|
||||||
sb.AppendLine("}");
|
sb.AppendLine("}");
|
||||||
return sb.ToString().TrimEnd();
|
return sb.ToString().TrimEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取生成文件的提示名称
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="symbol">命名类型符号</param>
|
||||||
|
/// <returns>生成文件的提示名称</returns>
|
||||||
protected override string GetHintName(INamedTypeSymbol symbol)
|
protected override string GetHintName(INamedTypeSymbol symbol)
|
||||||
=> $"{symbol.Name}.ContextAware.g.cs";
|
=> $"{symbol.Name}.ContextAware.g.cs";
|
||||||
|
|
||||||
// =========================
|
// =========================
|
||||||
// 生成 Context 属性
|
// Context 属性(无 global::,与测试一致)
|
||||||
// =========================
|
// =========================
|
||||||
|
/// <summary>
|
||||||
|
/// 生成Context属性
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sb">字符串构建器</param>
|
||||||
private static void GenerateContextProperty(StringBuilder sb)
|
private static void GenerateContextProperty(StringBuilder sb)
|
||||||
{
|
{
|
||||||
sb.AppendLine(" /// <summary>");
|
sb.AppendLine(" /// <summary>");
|
||||||
@ -106,28 +126,39 @@ public sealed class ContextAwareGenerator : MetadataAttributeClassGeneratorBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
// =========================
|
// =========================
|
||||||
// 自动实现接口方法
|
// 显式接口实现(使用 global::)
|
||||||
// =========================
|
// =========================
|
||||||
|
/// <summary>
|
||||||
|
/// 生成接口实现
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sb">字符串构建器</param>
|
||||||
|
/// <param name="interfaceSymbol">接口符号</param>
|
||||||
private static void GenerateInterfaceImplementations(
|
private static void GenerateInterfaceImplementations(
|
||||||
StringBuilder sb,
|
StringBuilder sb,
|
||||||
INamedTypeSymbol interfaceSymbol)
|
INamedTypeSymbol interfaceSymbol)
|
||||||
{
|
{
|
||||||
var interfaceFullName = interfaceSymbol.ToDisplayString(
|
var interfaceName = interfaceSymbol.ToDisplayString(
|
||||||
SymbolDisplayFormat.FullyQualifiedFormat);
|
SymbolDisplayFormat.FullyQualifiedFormat);
|
||||||
|
|
||||||
foreach (var member in interfaceSymbol.GetMembers().OfType<IMethodSymbol>())
|
foreach (var method in interfaceSymbol.GetMembers().OfType<IMethodSymbol>())
|
||||||
{
|
{
|
||||||
if (member.MethodKind != MethodKind.Ordinary)
|
if (method.MethodKind != MethodKind.Ordinary)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
GenerateMethod(sb, interfaceFullName, member);
|
GenerateMethod(sb, interfaceName, method);
|
||||||
sb.AppendLine();
|
sb.AppendLine();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 生成方法实现
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sb">字符串构建器</param>
|
||||||
|
/// <param name="interfaceName">接口名称</param>
|
||||||
|
/// <param name="method">方法符号</param>
|
||||||
private static void GenerateMethod(
|
private static void GenerateMethod(
|
||||||
StringBuilder sb,
|
StringBuilder sb,
|
||||||
string interfaceFullName,
|
string interfaceName,
|
||||||
IMethodSymbol method)
|
IMethodSymbol method)
|
||||||
{
|
{
|
||||||
var returnType = method.ReturnType.ToDisplayString(
|
var returnType = method.ReturnType.ToDisplayString(
|
||||||
@ -138,16 +169,19 @@ public sealed class ContextAwareGenerator : MetadataAttributeClassGeneratorBase
|
|||||||
$"{p.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)} {p.Name}"));
|
$"{p.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)} {p.Name}"));
|
||||||
|
|
||||||
sb.AppendLine(
|
sb.AppendLine(
|
||||||
$" {returnType} {interfaceFullName}.{method.Name}({parameters})");
|
$" {returnType} {interfaceName}.{method.Name}({parameters})");
|
||||||
|
|
||||||
sb.AppendLine(" {");
|
sb.AppendLine(" {");
|
||||||
|
|
||||||
GenerateMethodBody(sb, method);
|
GenerateMethodBody(sb, method);
|
||||||
|
|
||||||
sb.AppendLine(" }");
|
sb.AppendLine(" }");
|
||||||
}
|
}
|
||||||
|
|
||||||
// =========================
|
/// <summary>
|
||||||
// 方法语义策略
|
/// 生成方法体
|
||||||
// =========================
|
/// </summary>
|
||||||
|
/// <param name="sb">字符串构建器</param>
|
||||||
|
/// <param name="method">方法符号</param>
|
||||||
private static void GenerateMethodBody(
|
private static void GenerateMethodBody(
|
||||||
StringBuilder sb,
|
StringBuilder sb,
|
||||||
IMethodSymbol method)
|
IMethodSymbol method)
|
||||||
@ -163,25 +197,13 @@ public sealed class ContextAwareGenerator : MetadataAttributeClassGeneratorBase
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
GenerateFallbackBody(sb, method);
|
if (!method.ReturnsVoid)
|
||||||
|
{
|
||||||
|
sb.AppendLine(
|
||||||
|
$" throw new System.NotImplementedException(\"Method '{method.Name}' is not supported.\");");
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void GenerateFallbackBody(
|
|
||||||
StringBuilder sb,
|
|
||||||
IMethodSymbol method)
|
|
||||||
{
|
|
||||||
if (method.ReturnsVoid)
|
|
||||||
{
|
|
||||||
sb.AppendLine(" // no-op");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sb.AppendLine(
|
|
||||||
$" throw new System.NotImplementedException(");
|
|
||||||
sb.AppendLine(
|
|
||||||
$" \"Method '{method.Name}' is not supported by ContextAwareGenerator.\");");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user