mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-05-08 01:24:31 +08:00
fix(config): 修复条件分支诊断与文档摘要
- 修复 then/else 非 object 分支诊断定位到具体条件路径 - 优化 if/then/else 文档摘要,补充 properties 内约束说明 - 补充生成器回归测试,覆盖分支路径与文档输出
This commit is contained in:
parent
68d653623a
commit
0da15f6ffd
@ -1590,7 +1590,7 @@ public sealed class SchemaConfigGenerator : IIncrementalGenerator
|
||||
ConfigSchemaDiagnostics.InvalidConditionalSchemaMetadata,
|
||||
CreateFileLocation(filePath),
|
||||
Path.GetFileName(filePath),
|
||||
displayPath,
|
||||
branchPath,
|
||||
$"The '{keywordName}' value must be an object-valued schema.");
|
||||
return false;
|
||||
}
|
||||
@ -4214,7 +4214,7 @@ public sealed class SchemaConfigGenerator : IIncrementalGenerator
|
||||
return null;
|
||||
}
|
||||
|
||||
var ifSummary = TryBuildInlineSchemaSummary(ifElement, includeRequiredProperties: true);
|
||||
var ifSummary = TryBuildConditionalBranchSummary(ifElement);
|
||||
if (ifSummary is null)
|
||||
{
|
||||
return null;
|
||||
@ -4224,7 +4224,7 @@ public sealed class SchemaConfigGenerator : IIncrementalGenerator
|
||||
if (element.TryGetProperty("then", out var thenElement) &&
|
||||
thenElement.ValueKind == JsonValueKind.Object)
|
||||
{
|
||||
var thenSummary = TryBuildInlineSchemaSummary(thenElement, includeRequiredProperties: true);
|
||||
var thenSummary = TryBuildConditionalBranchSummary(thenElement);
|
||||
if (thenSummary is not null)
|
||||
{
|
||||
parts.Add($"then {thenSummary}");
|
||||
@ -4234,7 +4234,7 @@ public sealed class SchemaConfigGenerator : IIncrementalGenerator
|
||||
if (element.TryGetProperty("else", out var elseElement) &&
|
||||
elseElement.ValueKind == JsonValueKind.Object)
|
||||
{
|
||||
var elseSummary = TryBuildInlineSchemaSummary(elseElement, includeRequiredProperties: true);
|
||||
var elseSummary = TryBuildConditionalBranchSummary(elseElement);
|
||||
if (elseSummary is not null)
|
||||
{
|
||||
parts.Add($"else {elseSummary}");
|
||||
@ -4246,6 +4246,58 @@ public sealed class SchemaConfigGenerator : IIncrementalGenerator
|
||||
: null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 汇总条件分支的对象级约束与子属性约束,避免生成文档只保留笼统的 object 描述。
|
||||
/// </summary>
|
||||
/// <param name="branchElement">条件分支 schema。</param>
|
||||
/// <returns>格式化后的条件分支摘要。</returns>
|
||||
private static string? TryBuildConditionalBranchSummary(JsonElement branchElement)
|
||||
{
|
||||
var branchSummary = TryBuildInlineSchemaSummary(branchElement, includeRequiredProperties: true);
|
||||
if (branchSummary is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var propertiesSummary = TryBuildInlineObjectPropertiesSummary(branchElement);
|
||||
return propertiesSummary is null
|
||||
? branchSummary
|
||||
: $"{branchSummary}; properties = {propertiesSummary}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 汇总对象 <c>properties</c> 内每个字段的紧凑约束,补足条件分支文档里的触发条件细节。
|
||||
/// </summary>
|
||||
/// <param name="schemaElement">对象 schema 节点。</param>
|
||||
/// <returns>格式化后的子属性约束摘要。</returns>
|
||||
private static string? TryBuildInlineObjectPropertiesSummary(JsonElement schemaElement)
|
||||
{
|
||||
if (!schemaElement.TryGetProperty("properties", out var propertiesElement) ||
|
||||
propertiesElement.ValueKind != JsonValueKind.Object)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var parts = new List<string>();
|
||||
foreach (var property in propertiesElement.EnumerateObject())
|
||||
{
|
||||
if (property.Value.ValueKind != JsonValueKind.Object)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var propertySummary = TryBuildInlineSchemaSummary(property.Value);
|
||||
if (propertySummary is not null)
|
||||
{
|
||||
parts.Add($"{property.Name}: {propertySummary}");
|
||||
}
|
||||
}
|
||||
|
||||
return parts.Count == 0
|
||||
? null
|
||||
: $"{{ {string.Join("; ", parts)} }}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将数组 <c>contains</c> 子 schema 整理成 XML 文档可读字符串。
|
||||
/// 输出优先保持紧凑,只展示消费者在强类型 API 上最需要看到的匹配摘要。
|
||||
|
||||
@ -1338,7 +1338,10 @@ public class SchemaConfigGeneratorTests
|
||||
Assert.That(result.Results.Single().Diagnostics, Is.Empty);
|
||||
Assert.That(
|
||||
generatedSources["MonsterConfig.g.cs"],
|
||||
Does.Contain("Constraints: if/then/else = if object; then object (required = [itemCount]); else object (required = [bonus])."));
|
||||
Does.Contain(
|
||||
"Constraints: if/then/else = if object; properties = { itemId: string (const = \"potion\") }; " +
|
||||
"then object (required = [itemCount]); properties = { itemCount: integer }; " +
|
||||
"else object (required = [bonus]); properties = { bonus: integer }."));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -1394,6 +1397,63 @@ public class SchemaConfigGeneratorTests
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证条件分支不是 object schema 时,诊断路径会定位到具体分支而不是父对象。
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Run_Should_Report_Diagnostic_With_Branch_Path_When_Then_Schema_Is_Not_Object()
|
||||
{
|
||||
const string source = """
|
||||
namespace TestApp
|
||||
{
|
||||
public sealed class Dummy
|
||||
{
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
const string schema = """
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["id", "reward"],
|
||||
"properties": {
|
||||
"id": { "type": "integer" },
|
||||
"reward": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"itemId": { "type": "string" },
|
||||
"itemCount": { "type": "integer" }
|
||||
},
|
||||
"if": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"itemId": {
|
||||
"type": "string",
|
||||
"const": "potion"
|
||||
}
|
||||
}
|
||||
},
|
||||
"then": []
|
||||
}
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
var result = SchemaGeneratorTestDriver.Run(
|
||||
source,
|
||||
("monster.schema.json", schema));
|
||||
|
||||
var diagnostic = result.Results.Single().Diagnostics.Single();
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(diagnostic.Id, Is.EqualTo("GF_ConfigSchema_013"));
|
||||
Assert.That(diagnostic.Severity, Is.EqualTo(DiagnosticSeverity.Error));
|
||||
Assert.That(diagnostic.GetMessage(), Does.Contain("reward[then]"));
|
||||
Assert.That(diagnostic.GetMessage(), Does.Contain("must be an object-valued schema"));
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证条件分支不能引用父对象未声明的字段。
|
||||
/// </summary>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user