mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-05-09 10:19:00 +08:00
refactor(source-generators-tests): 收敛 Logger 快照测试告警
- 重构 LoggerGeneratorSnapshotTests 的重复场景源码构造,收口单文件 MA0051 告警 - 补充 LoggerGeneratorSnapshotTests 的 XML 文档并保持快照场景语义不变 - 更新 analyzer-warning-reduction 的 tracking 与 trace,记录 RP-031 验证结果和下一步恢复点
This commit is contained in:
parent
d0e86933cf
commit
31ae1460a9
@ -4,559 +4,232 @@ using GFramework.SourceGenerators.Tests.Core;
|
||||
|
||||
namespace GFramework.SourceGenerators.Tests.Logging;
|
||||
|
||||
/// <summary>
|
||||
/// 验证 <see cref="LoggerGenerator" /> 在常见日志声明配置下的快照输出保持稳定。
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class LoggerGeneratorSnapshotTests
|
||||
{
|
||||
/// <summary>
|
||||
/// 验证默认配置下的类日志字段快照。
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Snapshot_DefaultConfiguration_Class()
|
||||
public Task Snapshot_DefaultConfiguration_Class()
|
||||
{
|
||||
const string source = """
|
||||
using System;
|
||||
|
||||
namespace GFramework.Core.SourceGenerators.Abstractions.Logging
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public sealed class LogAttribute : Attribute
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string FieldName { get; set; }
|
||||
public string AccessModifier { get; set; }
|
||||
public bool IsStatic { get; set; } = true;
|
||||
}
|
||||
}
|
||||
|
||||
namespace GFramework.Core.Abstractions.Logging
|
||||
{
|
||||
public interface ILogger
|
||||
{
|
||||
void Info(string message);
|
||||
void Error(string message);
|
||||
void Warn(string message);
|
||||
void Debug(string message);
|
||||
void Trace(string message);
|
||||
void Fatal(string message);
|
||||
}
|
||||
}
|
||||
|
||||
namespace GFramework.Core.Logging
|
||||
{
|
||||
using GFramework.Core.Abstractions.Logging;
|
||||
|
||||
public static class LoggerFactoryResolver
|
||||
{
|
||||
public static ILoggerProvider Provider { get; set; }
|
||||
|
||||
public static ILoggerProvider CreateLogger(string name)
|
||||
{
|
||||
return Provider ?? new MockLoggerProvider();
|
||||
}
|
||||
}
|
||||
|
||||
public interface ILoggerProvider
|
||||
{
|
||||
ILogger CreateLogger(string name);
|
||||
}
|
||||
|
||||
internal class MockLoggerProvider : ILoggerProvider
|
||||
{
|
||||
public ILogger CreateLogger(string name)
|
||||
{
|
||||
return new MockLogger(name);
|
||||
}
|
||||
}
|
||||
|
||||
internal class MockLogger : ILogger
|
||||
{
|
||||
private readonly string _name;
|
||||
|
||||
public MockLogger(string name)
|
||||
{
|
||||
_name = name;
|
||||
}
|
||||
|
||||
public void Info(string message) { }
|
||||
public void Error(string message) { }
|
||||
public void Warn(string message) { }
|
||||
public void Debug(string message) { }
|
||||
public void Trace(string message) { }
|
||||
public void Fatal(string message) { }
|
||||
}
|
||||
}
|
||||
|
||||
namespace TestApp
|
||||
{
|
||||
using GFramework.Core.SourceGenerators.Abstractions.Logging;
|
||||
|
||||
[Log]
|
||||
public partial class MyService
|
||||
{
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
await GeneratorSnapshotTest<LoggerGenerator>.RunAsync(
|
||||
source,
|
||||
GetSnapshotFolder("DefaultConfiguration_Class"));
|
||||
return RunScenarioAsync(
|
||||
"DefaultConfiguration_Class",
|
||||
"[Log]",
|
||||
"public partial class MyService");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证自定义 logger 名称会反映到生成快照。
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Snapshot_CustomName_Class()
|
||||
public Task Snapshot_CustomName_Class()
|
||||
{
|
||||
const string source = """
|
||||
using System;
|
||||
|
||||
namespace GFramework.Core.SourceGenerators.Abstractions.Logging
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public sealed class LogAttribute : Attribute
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string FieldName { get; set; }
|
||||
public string AccessModifier { get; set; }
|
||||
public bool IsStatic { get; set; } = true;
|
||||
}
|
||||
}
|
||||
|
||||
namespace GFramework.Core.Abstractions.Logging
|
||||
{
|
||||
public interface ILogger
|
||||
{
|
||||
void Info(string message);
|
||||
void Error(string message);
|
||||
void Warn(string message);
|
||||
void Debug(string message);
|
||||
void Trace(string message);
|
||||
void Fatal(string message);
|
||||
}
|
||||
}
|
||||
|
||||
namespace GFramework.Core.Logging
|
||||
{
|
||||
using GFramework.Core.Abstractions.Logging;
|
||||
|
||||
public static class LoggerFactoryResolver
|
||||
{
|
||||
public static ILoggerProvider Provider { get; set; }
|
||||
|
||||
public static ILoggerProvider CreateLogger(string name)
|
||||
{
|
||||
return Provider ?? new MockLoggerProvider();
|
||||
}
|
||||
}
|
||||
|
||||
public interface ILoggerProvider
|
||||
{
|
||||
ILogger CreateLogger(string name);
|
||||
}
|
||||
|
||||
internal class MockLoggerProvider : ILoggerProvider
|
||||
{
|
||||
public ILogger CreateLogger(string name)
|
||||
{
|
||||
return new MockLogger(name);
|
||||
}
|
||||
}
|
||||
|
||||
internal class MockLogger : ILogger
|
||||
{
|
||||
private readonly string _name;
|
||||
|
||||
public MockLogger(string name)
|
||||
{
|
||||
_name = name;
|
||||
}
|
||||
|
||||
public void Info(string message) { }
|
||||
public void Error(string message) { }
|
||||
public void Warn(string message) { }
|
||||
public void Debug(string message) { }
|
||||
public void Trace(string message) { }
|
||||
public void Fatal(string message) { }
|
||||
}
|
||||
}
|
||||
|
||||
namespace TestApp
|
||||
{
|
||||
using GFramework.Core.SourceGenerators.Abstractions.Logging;
|
||||
|
||||
[Log(Name = "CustomLogger")]
|
||||
public partial class MyService
|
||||
{
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
await GeneratorSnapshotTest<LoggerGenerator>.RunAsync(
|
||||
source,
|
||||
GetSnapshotFolder("CustomName_Class"));
|
||||
return RunScenarioAsync(
|
||||
"CustomName_Class",
|
||||
"[Log(Name = \"CustomLogger\")]",
|
||||
"public partial class MyService");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证自定义字段名会反映到生成快照。
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Snapshot_CustomFieldName_Class()
|
||||
public Task Snapshot_CustomFieldName_Class()
|
||||
{
|
||||
const string source = """
|
||||
using System;
|
||||
|
||||
namespace GFramework.Core.SourceGenerators.Abstractions.Logging
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public sealed class LogAttribute : Attribute
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string FieldName { get; set; }
|
||||
public string AccessModifier { get; set; }
|
||||
public bool IsStatic { get; set; } = true;
|
||||
}
|
||||
}
|
||||
|
||||
namespace GFramework.Core.Abstractions.Logging
|
||||
{
|
||||
public interface ILogger
|
||||
{
|
||||
void Info(string message);
|
||||
void Error(string message);
|
||||
void Warn(string message);
|
||||
void Debug(string message);
|
||||
void Trace(string message);
|
||||
void Fatal(string message);
|
||||
}
|
||||
}
|
||||
|
||||
namespace GFramework.Core.Logging
|
||||
{
|
||||
using GFramework.Core.Abstractions.Logging;
|
||||
|
||||
public static class LoggerFactoryResolver
|
||||
{
|
||||
public static ILoggerProvider Provider { get; set; }
|
||||
|
||||
public static ILoggerProvider CreateLogger(string name)
|
||||
{
|
||||
return Provider ?? new MockLoggerProvider();
|
||||
}
|
||||
}
|
||||
|
||||
public interface ILoggerProvider
|
||||
{
|
||||
ILogger CreateLogger(string name);
|
||||
}
|
||||
|
||||
internal class MockLoggerProvider : ILoggerProvider
|
||||
{
|
||||
public ILogger CreateLogger(string name)
|
||||
{
|
||||
return new MockLogger(name);
|
||||
}
|
||||
}
|
||||
|
||||
internal class MockLogger : ILogger
|
||||
{
|
||||
private readonly string _name;
|
||||
|
||||
public MockLogger(string name)
|
||||
{
|
||||
_name = name;
|
||||
}
|
||||
|
||||
public void Info(string message) { }
|
||||
public void Error(string message) { }
|
||||
public void Warn(string message) { }
|
||||
public void Debug(string message) { }
|
||||
public void Trace(string message) { }
|
||||
public void Fatal(string message) { }
|
||||
}
|
||||
}
|
||||
|
||||
namespace TestApp
|
||||
{
|
||||
using GFramework.Core.SourceGenerators.Abstractions.Logging;
|
||||
|
||||
[Log(FieldName = "MyLogger")]
|
||||
public partial class MyService
|
||||
{
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
await GeneratorSnapshotTest<LoggerGenerator>.RunAsync(
|
||||
source,
|
||||
GetSnapshotFolder("CustomFieldName_Class"));
|
||||
return RunScenarioAsync(
|
||||
"CustomFieldName_Class",
|
||||
"[Log(FieldName = \"MyLogger\")]",
|
||||
"public partial class MyService");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证实例字段模式会反映到生成快照。
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Snapshot_InstanceField_Class()
|
||||
public Task Snapshot_InstanceField_Class()
|
||||
{
|
||||
const string source = """
|
||||
using System;
|
||||
|
||||
namespace GFramework.Core.SourceGenerators.Abstractions.Logging
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public sealed class LogAttribute : Attribute
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string FieldName { get; set; }
|
||||
public string AccessModifier { get; set; }
|
||||
public bool IsStatic { get; set; } = true;
|
||||
}
|
||||
}
|
||||
|
||||
namespace GFramework.Core.Abstractions.Logging
|
||||
{
|
||||
public interface ILogger
|
||||
{
|
||||
void Info(string message);
|
||||
void Error(string message);
|
||||
void Warn(string message);
|
||||
void Debug(string message);
|
||||
void Trace(string message);
|
||||
void Fatal(string message);
|
||||
}
|
||||
}
|
||||
|
||||
namespace GFramework.Core.Logging
|
||||
{
|
||||
using GFramework.Core.Abstractions.Logging;
|
||||
|
||||
public static class LoggerFactoryResolver
|
||||
{
|
||||
public static ILoggerProvider Provider { get; set; }
|
||||
|
||||
public static ILoggerProvider CreateLogger(string name)
|
||||
{
|
||||
return Provider ?? new MockLoggerProvider();
|
||||
}
|
||||
}
|
||||
|
||||
public interface ILoggerProvider
|
||||
{
|
||||
ILogger CreateLogger(string name);
|
||||
}
|
||||
|
||||
internal class MockLoggerProvider : ILoggerProvider
|
||||
{
|
||||
public ILogger CreateLogger(string name)
|
||||
{
|
||||
return new MockLogger(name);
|
||||
}
|
||||
}
|
||||
|
||||
internal class MockLogger : ILogger
|
||||
{
|
||||
private readonly string _name;
|
||||
|
||||
public MockLogger(string name)
|
||||
{
|
||||
_name = name;
|
||||
}
|
||||
|
||||
public void Info(string message) { }
|
||||
public void Error(string message) { }
|
||||
public void Warn(string message) { }
|
||||
public void Debug(string message) { }
|
||||
public void Trace(string message) { }
|
||||
public void Fatal(string message) { }
|
||||
}
|
||||
}
|
||||
|
||||
namespace TestApp
|
||||
{
|
||||
using GFramework.Core.SourceGenerators.Abstractions.Logging;
|
||||
|
||||
[Log(IsStatic = false)]
|
||||
public partial class MyService
|
||||
{
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
await GeneratorSnapshotTest<LoggerGenerator>.RunAsync(
|
||||
source,
|
||||
GetSnapshotFolder("InstanceField_Class"));
|
||||
return RunScenarioAsync(
|
||||
"InstanceField_Class",
|
||||
"[Log(IsStatic = false)]",
|
||||
"public partial class MyService");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证公共字段可见性会反映到生成快照。
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Snapshot_PublicField_Class()
|
||||
public Task Snapshot_PublicField_Class()
|
||||
{
|
||||
const string source = """
|
||||
using System;
|
||||
|
||||
namespace GFramework.Core.SourceGenerators.Abstractions.Logging
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public sealed class LogAttribute : Attribute
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string FieldName { get; set; }
|
||||
public string AccessModifier { get; set; }
|
||||
public bool IsStatic { get; set; } = true;
|
||||
}
|
||||
}
|
||||
|
||||
namespace GFramework.Core.Abstractions.Logging
|
||||
{
|
||||
public interface ILogger
|
||||
{
|
||||
void Info(string message);
|
||||
void Error(string message);
|
||||
void Warn(string message);
|
||||
void Debug(string message);
|
||||
void Trace(string message);
|
||||
void Fatal(string message);
|
||||
}
|
||||
}
|
||||
|
||||
namespace GFramework.Core.Logging
|
||||
{
|
||||
using GFramework.Core.Abstractions.Logging;
|
||||
|
||||
public static class LoggerFactoryResolver
|
||||
{
|
||||
public static ILoggerProvider Provider { get; set; }
|
||||
|
||||
public static ILoggerProvider CreateLogger(string name)
|
||||
{
|
||||
return Provider ?? new MockLoggerProvider();
|
||||
}
|
||||
}
|
||||
|
||||
public interface ILoggerProvider
|
||||
{
|
||||
ILogger CreateLogger(string name);
|
||||
}
|
||||
|
||||
internal class MockLoggerProvider : ILoggerProvider
|
||||
{
|
||||
public ILogger CreateLogger(string name)
|
||||
{
|
||||
return new MockLogger(name);
|
||||
}
|
||||
}
|
||||
|
||||
internal class MockLogger : ILogger
|
||||
{
|
||||
private readonly string _name;
|
||||
|
||||
public MockLogger(string name)
|
||||
{
|
||||
_name = name;
|
||||
}
|
||||
|
||||
public void Info(string message) { }
|
||||
public void Error(string message) { }
|
||||
public void Warn(string message) { }
|
||||
public void Debug(string message) { }
|
||||
public void Trace(string message) { }
|
||||
public void Fatal(string message) { }
|
||||
}
|
||||
}
|
||||
|
||||
namespace TestApp
|
||||
{
|
||||
using GFramework.Core.SourceGenerators.Abstractions.Logging;
|
||||
|
||||
[Log(AccessModifier = "public")]
|
||||
public partial class MyService
|
||||
{
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
await GeneratorSnapshotTest<LoggerGenerator>.RunAsync(
|
||||
source,
|
||||
GetSnapshotFolder("PublicField_Class"));
|
||||
return RunScenarioAsync(
|
||||
"PublicField_Class",
|
||||
"[Log(AccessModifier = \"public\")]",
|
||||
"public partial class MyService");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证泛型类声明的日志字段快照。
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task Snapshot_GenericClass()
|
||||
public Task Snapshot_GenericClass()
|
||||
{
|
||||
const string source = """
|
||||
using System;
|
||||
return RunScenarioAsync(
|
||||
"GenericClass",
|
||||
"[Log]",
|
||||
"public partial class MyService<T>");
|
||||
}
|
||||
|
||||
namespace GFramework.Core.SourceGenerators.Abstractions.Logging
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public sealed class LogAttribute : Attribute
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string FieldName { get; set; }
|
||||
public string AccessModifier { get; set; }
|
||||
public bool IsStatic { get; set; } = true;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 为给定场景组装最小测试源并执行快照校验。
|
||||
/// </summary>
|
||||
/// <param name="scenarioName">快照场景名称。</param>
|
||||
/// <param name="logAttributeLine">目标类型上的 <c>[Log(...)]</c> 声明。</param>
|
||||
/// <param name="classDeclaration">目标 partial 类型声明。</param>
|
||||
/// <returns>表示快照测试完成的异步任务。</returns>
|
||||
private static Task RunScenarioAsync(string scenarioName, string logAttributeLine, string classDeclaration)
|
||||
{
|
||||
return GeneratorSnapshotTest<LoggerGenerator>.RunAsync(
|
||||
CreateSource(logAttributeLine, classDeclaration),
|
||||
GetSnapshotFolder(scenarioName));
|
||||
}
|
||||
|
||||
namespace GFramework.Core.Abstractions.Logging
|
||||
{
|
||||
public interface ILogger
|
||||
{
|
||||
void Info(string message);
|
||||
void Error(string message);
|
||||
void Warn(string message);
|
||||
void Debug(string message);
|
||||
void Trace(string message);
|
||||
void Fatal(string message);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 生成日志源生成器测试所需的最小宿主源代码。
|
||||
/// </summary>
|
||||
/// <param name="logAttributeLine">目标类型上的 <c>[Log(...)]</c> 声明。</param>
|
||||
/// <param name="classDeclaration">目标 partial 类型声明。</param>
|
||||
/// <returns>可直接送入快照测试的完整源码字符串。</returns>
|
||||
private static string CreateSource(string logAttributeLine, string classDeclaration)
|
||||
{
|
||||
return string.Join(
|
||||
$"{Environment.NewLine}{Environment.NewLine}",
|
||||
CreateLoggingAttributeSource(),
|
||||
CreateLoggingContractsSource(),
|
||||
CreateLoggingRuntimeSource(),
|
||||
CreateTestAppSource(logAttributeLine, classDeclaration));
|
||||
}
|
||||
|
||||
namespace GFramework.Core.Logging
|
||||
{
|
||||
using GFramework.Core.Abstractions.Logging;
|
||||
/// <summary>
|
||||
/// 生成日志测试使用的 attribute 定义源码。
|
||||
/// </summary>
|
||||
/// <returns>包含 <c>LogAttribute</c> 的源码片段。</returns>
|
||||
private static string CreateLoggingAttributeSource()
|
||||
{
|
||||
return """
|
||||
using System;
|
||||
|
||||
public static class LoggerFactoryResolver
|
||||
{
|
||||
public static ILoggerProvider Provider { get; set; }
|
||||
namespace GFramework.Core.SourceGenerators.Abstractions.Logging
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public sealed class LogAttribute : Attribute
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string FieldName { get; set; }
|
||||
public string AccessModifier { get; set; }
|
||||
public bool IsStatic { get; set; } = true;
|
||||
}
|
||||
}
|
||||
""";
|
||||
}
|
||||
|
||||
public static ILoggerProvider CreateLogger(string name)
|
||||
{
|
||||
return Provider ?? new MockLoggerProvider();
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 生成日志抽象契约源码,供测试编译图引用。
|
||||
/// </summary>
|
||||
/// <returns>包含 <c>ILogger</c> 的源码片段。</returns>
|
||||
private static string CreateLoggingContractsSource()
|
||||
{
|
||||
return """
|
||||
namespace GFramework.Core.Abstractions.Logging
|
||||
{
|
||||
public interface ILogger
|
||||
{
|
||||
void Info(string message);
|
||||
void Error(string message);
|
||||
void Warn(string message);
|
||||
void Debug(string message);
|
||||
void Trace(string message);
|
||||
void Fatal(string message);
|
||||
}
|
||||
}
|
||||
""";
|
||||
}
|
||||
|
||||
public interface ILoggerProvider
|
||||
{
|
||||
ILogger CreateLogger(string name);
|
||||
}
|
||||
/// <summary>
|
||||
/// 生成最小运行时宿主源码,供生成器解析 logger provider 依赖。
|
||||
/// </summary>
|
||||
/// <returns>包含 provider 与 mock logger 的源码片段。</returns>
|
||||
private static string CreateLoggingRuntimeSource()
|
||||
{
|
||||
return """
|
||||
namespace GFramework.Core.Logging
|
||||
{
|
||||
using GFramework.Core.Abstractions.Logging;
|
||||
|
||||
internal class MockLoggerProvider : ILoggerProvider
|
||||
{
|
||||
public ILogger CreateLogger(string name)
|
||||
{
|
||||
return new MockLogger(name);
|
||||
}
|
||||
}
|
||||
public static class LoggerFactoryResolver
|
||||
{
|
||||
public static ILoggerProvider Provider { get; set; }
|
||||
|
||||
internal class MockLogger : ILogger
|
||||
{
|
||||
private readonly string _name;
|
||||
public static ILoggerProvider CreateLogger(string name)
|
||||
{
|
||||
return Provider ?? new MockLoggerProvider();
|
||||
}
|
||||
}
|
||||
|
||||
public MockLogger(string name)
|
||||
{
|
||||
_name = name;
|
||||
}
|
||||
public interface ILoggerProvider
|
||||
{
|
||||
ILogger CreateLogger(string name);
|
||||
}
|
||||
|
||||
public void Info(string message) { }
|
||||
public void Error(string message) { }
|
||||
public void Warn(string message) { }
|
||||
public void Debug(string message) { }
|
||||
public void Trace(string message) { }
|
||||
public void Fatal(string message) { }
|
||||
}
|
||||
}
|
||||
internal class MockLoggerProvider : ILoggerProvider
|
||||
{
|
||||
public ILogger CreateLogger(string name)
|
||||
{
|
||||
return new MockLogger(name);
|
||||
}
|
||||
}
|
||||
|
||||
namespace TestApp
|
||||
{
|
||||
using GFramework.Core.SourceGenerators.Abstractions.Logging;
|
||||
internal class MockLogger : ILogger
|
||||
{
|
||||
private readonly string _name;
|
||||
|
||||
[Log]
|
||||
public partial class MyService<T>
|
||||
{
|
||||
}
|
||||
}
|
||||
""";
|
||||
public MockLogger(string name)
|
||||
{
|
||||
_name = name;
|
||||
}
|
||||
|
||||
await GeneratorSnapshotTest<LoggerGenerator>.RunAsync(
|
||||
source,
|
||||
GetSnapshotFolder("GenericClass"));
|
||||
public void Info(string message) { }
|
||||
public void Error(string message) { }
|
||||
public void Warn(string message) { }
|
||||
public void Debug(string message) { }
|
||||
public void Trace(string message) { }
|
||||
public void Fatal(string message) { }
|
||||
}
|
||||
}
|
||||
""";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 生成实际承载 <c>[Log]</c> 声明的测试类型源码。
|
||||
/// </summary>
|
||||
/// <param name="logAttributeLine">目标类型上的 <c>[Log(...)]</c> 声明。</param>
|
||||
/// <param name="classDeclaration">目标 partial 类型声明。</param>
|
||||
/// <returns>测试应用命名空间下的目标类型源码片段。</returns>
|
||||
private static string CreateTestAppSource(string logAttributeLine, string classDeclaration)
|
||||
{
|
||||
return $$"""
|
||||
namespace TestApp
|
||||
{
|
||||
using GFramework.Core.SourceGenerators.Abstractions.Logging;
|
||||
|
||||
{{logAttributeLine}}
|
||||
{{classDeclaration}}
|
||||
{
|
||||
}
|
||||
}
|
||||
""";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -7,8 +7,8 @@
|
||||
|
||||
## 当前恢复点
|
||||
|
||||
- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-030`
|
||||
- 当前阶段:`Phase 30`
|
||||
- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-031`
|
||||
- 当前阶段:`Phase 31`
|
||||
- 当前焦点:
|
||||
- 已完成 `GFramework.Core` 当前 `MA0016` / `MA0002` / `MA0015` / `MA0077` 低风险收口批次
|
||||
- 已复核 `net10.0` 下的 `MA0158` 基线:`GFramework.Core` / `GFramework.Cqrs` 当前共有 `16` 个 object lock
|
||||
@ -53,10 +53,14 @@
|
||||
- 已完成 `GFramework.SourceGenerators.Tests` 低风险 `MA0004` / `MA0048` 收口:测试辅助器改为直接返回 `Task`,
|
||||
文件 I/O 显式补齐 `ConfigureAwait(false)`,`AnalyzerTestDriver` 文件名与类型名重新对齐
|
||||
- 当前 `GFramework.SourceGenerators.Tests` warnings-only 基线已从 `61` 条降到 `49` 条,剩余 warning 均为 `MA0051`
|
||||
- 已完成 `GFramework.SourceGenerators.Tests/Logging/LoggerGeneratorSnapshotTests.cs` 的 `MA0051` 收口:同构 snapshot
|
||||
场景已收敛为模板化 helper,保留原有快照目录与生成器输入语义不变
|
||||
- 当前 `GFramework.SourceGenerators.Tests` Release build 基线已从 `49` 条降到 `43` 条;`LoggerGeneratorSnapshotTests.cs`
|
||||
已不再出现在 `MA0051` 列表中
|
||||
- `GFramework.Godot` 的 `Timing.cs` 已同步适配新事件签名,但当前 worktree 的 Godot restore 资产仍受 Windows fallback package folder 干扰,独立 build 需在修复资产后补跑
|
||||
- 后续继续按 warning 类型和数量批处理,而不是回退到按单文件切片推进
|
||||
- 下一轮默认继续拆分 `GFramework.SourceGenerators.Tests` 的 `MA0051` 热点,或评估跨 target 的 `MA0158`
|
||||
锁替换风险
|
||||
- 下一轮默认继续拆分 `GFramework.SourceGenerators.Tests` 的 `MA0051` 热点,优先处理
|
||||
`AutoRegisterModuleGeneratorTests`、`GeneratorSnapshotTest` 或 `ContextGetGeneratorTests`
|
||||
- 单次 `boot` 的工作树改动上限控制在约 `100` 个文件以内,避免 recovery context 与 review 面同时失控
|
||||
- 若任务边界互不冲突,允许使用不同模型的 subagent 并行处理不同 warning 类型或不同目录,但必须遵守显式 ownership
|
||||
|
||||
@ -92,6 +96,8 @@
|
||||
- 已完成 `GFramework.Game.SourceGenerators` 中 `SchemaConfigGenerator` 的剩余 `MA0051` 收口;warnings-only 基线已降到 `0` 条
|
||||
- 已完成 `GFramework.SourceGenerators.Tests` 的首轮低风险 warning 清理;当前项目已清空 `MA0004` / `MA0048`,剩余 warning
|
||||
全部收敛为 `MA0051`
|
||||
- 已完成 `LoggerGeneratorSnapshotTests` 的单文件 `MA0051` 收口;当前 `GFramework.SourceGenerators.Tests` Release build 基线已降到
|
||||
`43` 条,并通过 focused snapshot tests 保持行为不变
|
||||
|
||||
## 当前活跃事实
|
||||
|
||||
@ -152,6 +158,8 @@
|
||||
- `RP-030` 已完成 `GFramework.SourceGenerators.Tests` 低风险 `MA0004` / `MA0048` 收口:`AnalyzerTestDriver` 文件名已与
|
||||
类型名一致,测试辅助器与 schema snapshot 断言路径已改为直接返回 `Task` 或显式使用 `ConfigureAwait(false)`;
|
||||
当前测试项目 warnings-only 基线从 `61` 条降到 `49` 条,剩余均为 `MA0051`
|
||||
- `RP-031` 已完成 `LoggerGeneratorSnapshotTests` 的 `MA0051` 收口:重复场景源码改为模板化 helper 生成,
|
||||
当前 `GFramework.SourceGenerators.Tests` Release build 基线从 `49` 条降到 `43` 条,并通过 focused test 验证 6 个用例全部通过
|
||||
- 当前工作树分支 `fix/analyzer-warning-reduction-batch` 已在 `ai-plan/public/README.md` 建立 topic 映射
|
||||
|
||||
## 当前风险
|
||||
@ -167,7 +175,7 @@
|
||||
- source generator warning 外溢风险:运行 `GFramework.SourceGenerators.Tests` 会构建相邻 generator/test 项目,并在输出中混入
|
||||
测试项目自身的结构性 warning 基线
|
||||
- 缓解措施:继续以被修改项目的独立 warnings-only build 作为主验收,并用 focused generator test 验证行为
|
||||
- source generator test warning 治理风险:`GFramework.SourceGenerators.Tests` 当前仍有 `49` 条既有 `MA0051` warning;
|
||||
- source generator test warning 治理风险:`GFramework.SourceGenerators.Tests` 当前仍有 `43` 条既有 `MA0051` warning;
|
||||
一旦继续进入该写集,就必须把测试项目 warning 一并纳入本轮完成条件
|
||||
- 缓解措施:已先清空低风险 `MA0004` / `MA0048`,后续继续保持“单 warning family、单测试域”的节奏推进 `MA0051`
|
||||
- ContextAware 基类命名隐藏风险:若生成器只看当前类型声明成员,派生规则会重新占用基类已声明的
|
||||
@ -339,13 +347,20 @@
|
||||
- 结果:`49 Warning(s)`,`0 Error(s)`;当前项目已不再出现 `MA0004` / `MA0048`,剩余 warning 全部为 `MA0051`
|
||||
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --no-restore --filter "FullyQualifiedName~GeneratorSnapshotTestSecurityTests|FullyQualifiedName~SchemaConfigGeneratorSnapshotTests|FullyQualifiedName~SchemaConfigGeneratorEnumTests" -m:1 -p:RestoreFallbackFolders="" -nologo`
|
||||
- 结果:`6 Passed`,`0 Failed`
|
||||
- `RP-031` 的验证结果:
|
||||
- `dotnet restore GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -p:RestoreFallbackFolders="" -nologo`
|
||||
- 结果:通过;刷新 Linux 侧 restore 资产以支持后续串行 build/test 验证
|
||||
- `dotnet build GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --no-restore --disable-build-servers -m:1 -p:UseSharedCompilation=false -p:RestoreFallbackFolders="" -nologo -clp:Summary`
|
||||
- 结果:`43 Warning(s)`,`0 Error(s)`;`LoggerGeneratorSnapshotTests.cs` 已不再出现在 `MA0051` 列表中
|
||||
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --no-build --disable-build-servers --filter FullyQualifiedName~LoggerGeneratorSnapshotTests -m:1 -p:RestoreFallbackFolders="" -nologo`
|
||||
- 结果:`6 Passed`,`0 Failed`
|
||||
- active 跟踪文件只保留当前恢复点、活跃事实、风险与下一步,不再重复保存已完成阶段的长篇历史
|
||||
|
||||
## 下一步
|
||||
|
||||
1. 若要继续该主题,先读 active tracking,再按需展开历史归档中的 warning 热点与验证记录
|
||||
2. 下一轮优先继续 `GFramework.SourceGenerators.Tests` 的 `MA0051` 收口,先在单一测试域内选择一个文件或一组同构 snapshot
|
||||
用例拆分,不再把已清零的 `MA0004` / `MA0048` 混回写集
|
||||
2. 下一轮优先继续 `GFramework.SourceGenerators.Tests` 的 `MA0051` 收口,先在 `AutoRegisterModuleGeneratorTests`、
|
||||
`GeneratorSnapshotTest` 或 `ContextGetGeneratorTests` 中选择一个单写集推进,不再把已清零的 `MA0004` / `MA0048` 混回写集
|
||||
3. 若改回推进 `MA0158`,先设计 `net8.0` / `net9.0` / `net10.0` 多 target 条件编译方案,不直接批量替换共享源码中的
|
||||
`object` lock
|
||||
4. 若后续继续改动 `GFramework.Godot`,先修复该项目的 Linux 侧 restore 资产,再补跑独立 build
|
||||
|
||||
@ -1,5 +1,37 @@
|
||||
# Analyzer Warning Reduction 追踪
|
||||
|
||||
## 2026-04-23 — RP-031
|
||||
|
||||
### 阶段:`LoggerGeneratorSnapshotTests.cs` `MA0051` 收口(RP-031)
|
||||
|
||||
- 启动复核:
|
||||
- 按 `gframework-boot` 流程恢复当前 worktree,读取 `AGENTS.md`、`.ai/environment/tools.ai.yaml`、
|
||||
`ai-plan/public/README.md` 与 active topic 跟踪文件,确认当前分支 `fix/analyzer-warning-reduction-batch`
|
||||
仍映射到 `analyzer-warning-reduction`
|
||||
- 结合 `RP-030` 的下一步建议与当前文件规模,优先选择 `GFramework.SourceGenerators.Tests/Logging/LoggerGeneratorSnapshotTests.cs`
|
||||
作为单文件、同构 snapshot 场景的低风险写集
|
||||
- 决策:
|
||||
- 保持 `LoggerGenerator` 现有快照资产、场景命名与输入语义不变,只压缩测试方法和样板源码构造的结构复杂度
|
||||
- 先把重复场景统一为模板化 helper,再根据 analyzer 结果继续拆分 helper,直到 `LoggerGeneratorSnapshotTests.cs`
|
||||
不再出现在 `MA0051` 输出中
|
||||
- 验证阶段避免并行运行同一测试项目的 build/test,防止 WSL worktree 上的 `bin/Release` 文件占用噪音污染结果
|
||||
- 实施调整:
|
||||
- 为 `LoggerGeneratorSnapshotTests` 补齐类与测试方法 XML 文档
|
||||
- 将 6 个 snapshot 场景改为统一调用 `RunScenarioAsync(...)`
|
||||
- 将原先重复内联的完整测试源码拆成 `CreateLoggingAttributeSource()`、
|
||||
`CreateLoggingContractsSource()`、`CreateLoggingRuntimeSource()` 与 `CreateTestAppSource(...)`
|
||||
- 验证结果:
|
||||
- `dotnet restore GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -p:RestoreFallbackFolders="" -nologo`
|
||||
- 结果:通过
|
||||
- `dotnet build GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --no-restore --disable-build-servers -m:1 -p:UseSharedCompilation=false -p:RestoreFallbackFolders="" -nologo -clp:Summary`
|
||||
- 结果:`43 Warning(s)`,`0 Error(s)`;`LoggerGeneratorSnapshotTests.cs` 已不再出现在 `MA0051` 列表中
|
||||
- `dotnet test GFramework.SourceGenerators.Tests/GFramework.SourceGenerators.Tests.csproj -c Release --no-build --disable-build-servers --filter FullyQualifiedName~LoggerGeneratorSnapshotTests -m:1 -p:RestoreFallbackFolders="" -nologo`
|
||||
- 结果:`6 Passed`,`0 Failed`
|
||||
- 下一步建议:
|
||||
- 若继续 `GFramework.SourceGenerators.Tests` 的 `MA0051` 治理,优先选择 `AutoRegisterModuleGeneratorTests` 或
|
||||
`GeneratorSnapshotTest` 作为下一批单写集
|
||||
- 若需要先压缩 warning 数量而不是单文件难度,可转向 `ContextGetGeneratorTests`,但应先明确本轮允许的文件数上限
|
||||
|
||||
## 2026-04-23 — RP-030
|
||||
|
||||
### 阶段:`GFramework.SourceGenerators.Tests` 低风险 `MA0004` / `MA0048` 收口(RP-030)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user