mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-05-06 16:16:44 +08:00
refactor(game): 拆分 schema 校验模型类型
- 拆分 schema model 类型到独立同名文件 - 清理 schema 校验模型的文件命名 analyzer 告警 - 更新 warning reduction 批处理收口状态
This commit is contained in:
parent
1395b84439
commit
104ac25dc3
32
GFramework.Game/Config/YamlConfigAllowedValue.cs
Normal file
32
GFramework.Game/Config/YamlConfigAllowedValue.cs
Normal file
@ -0,0 +1,32 @@
|
||||
namespace GFramework.Game.Config;
|
||||
|
||||
/// <summary>
|
||||
/// 表示一个节点上声明的单个 <c>enum</c> 候选值。
|
||||
/// 该模型同时保留稳定比较键与原始 JSON 文本,分别供运行时匹配和诊断输出复用。
|
||||
/// </summary>
|
||||
internal sealed class YamlConfigAllowedValue
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化一个枚举候选值模型。
|
||||
/// </summary>
|
||||
/// <param name="comparableValue">用于与 YAML 节点比较的稳定键。</param>
|
||||
/// <param name="displayValue">用于诊断输出的原始 JSON 文本。</param>
|
||||
public YamlConfigAllowedValue(string comparableValue, string displayValue)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(comparableValue);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(displayValue);
|
||||
|
||||
ComparableValue = comparableValue;
|
||||
DisplayValue = displayValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取用于运行时比较的稳定键。
|
||||
/// </summary>
|
||||
public string ComparableValue { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取用于诊断输出的原始 JSON 文本。
|
||||
/// </summary>
|
||||
public string DisplayValue { get; }
|
||||
}
|
||||
47
GFramework.Game/Config/YamlConfigArrayConstraints.cs
Normal file
47
GFramework.Game/Config/YamlConfigArrayConstraints.cs
Normal file
@ -0,0 +1,47 @@
|
||||
namespace GFramework.Game.Config;
|
||||
|
||||
/// <summary>
|
||||
/// 表示一个数组节点上声明的元素数量、去重与 contains 匹配计数约束。
|
||||
/// 该模型与标量约束拆分保存,避免数组节点继续共享不适用的标量字段。
|
||||
/// </summary>
|
||||
internal sealed class YamlConfigArrayConstraints
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化数组约束模型。
|
||||
/// </summary>
|
||||
/// <param name="minItems">最小元素数量约束。</param>
|
||||
/// <param name="maxItems">最大元素数量约束。</param>
|
||||
/// <param name="uniqueItems">是否要求数组元素唯一。</param>
|
||||
/// <param name="containsConstraints">数组 contains 约束;未声明时为空。</param>
|
||||
public YamlConfigArrayConstraints(
|
||||
int? minItems,
|
||||
int? maxItems,
|
||||
bool uniqueItems,
|
||||
YamlConfigArrayContainsConstraints? containsConstraints)
|
||||
{
|
||||
MinItems = minItems;
|
||||
MaxItems = maxItems;
|
||||
UniqueItems = uniqueItems;
|
||||
ContainsConstraints = containsConstraints;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取最小元素数量约束。
|
||||
/// </summary>
|
||||
public int? MinItems { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取最大元素数量约束。
|
||||
/// </summary>
|
||||
public int? MaxItems { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取是否要求数组元素唯一。
|
||||
/// </summary>
|
||||
public bool UniqueItems { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取数组 contains 约束;未声明时返回空。
|
||||
/// </summary>
|
||||
public YamlConfigArrayContainsConstraints? ContainsConstraints { get; }
|
||||
}
|
||||
41
GFramework.Game/Config/YamlConfigArrayContainsConstraints.cs
Normal file
41
GFramework.Game/Config/YamlConfigArrayContainsConstraints.cs
Normal file
@ -0,0 +1,41 @@
|
||||
namespace GFramework.Game.Config;
|
||||
|
||||
/// <summary>
|
||||
/// 表示数组节点声明的 <c>contains</c> 匹配约束。
|
||||
/// 该模型把 contains 子 schema 与匹配数量边界聚合在一起,避免数组节点再额外散落多组相关成员。
|
||||
/// </summary>
|
||||
internal sealed class YamlConfigArrayContainsConstraints
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化数组 contains 约束模型。
|
||||
/// </summary>
|
||||
/// <param name="containsNode">contains 子 schema。</param>
|
||||
/// <param name="minContains">最小匹配数量;为 <see langword="null" /> 时按 JSON Schema 语义默认 1。</param>
|
||||
/// <param name="maxContains">最大匹配数量。</param>
|
||||
public YamlConfigArrayContainsConstraints(
|
||||
YamlConfigSchemaNode containsNode,
|
||||
int? minContains,
|
||||
int? maxContains)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(containsNode);
|
||||
|
||||
ContainsNode = containsNode;
|
||||
MinContains = minContains;
|
||||
MaxContains = maxContains;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取 contains 子 schema。
|
||||
/// </summary>
|
||||
public YamlConfigSchemaNode ContainsNode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取最小匹配数量;未显式声明时返回空,由调用方按默认值 1 解释。
|
||||
/// </summary>
|
||||
public int? MinContains { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取最大匹配数量。
|
||||
/// </summary>
|
||||
public int? MaxContains { get; }
|
||||
}
|
||||
41
GFramework.Game/Config/YamlConfigConditionalSchemas.cs
Normal file
41
GFramework.Game/Config/YamlConfigConditionalSchemas.cs
Normal file
@ -0,0 +1,41 @@
|
||||
namespace GFramework.Game.Config;
|
||||
|
||||
/// <summary>
|
||||
/// 表示一个对象节点上声明的 object-focused <c>if</c> / <c>then</c> / <c>else</c> 条件约束。
|
||||
/// 三个分支都共享父对象已声明字段集合,不会把分支 schema 扩展成新的生成类型形状。
|
||||
/// </summary>
|
||||
internal sealed class YamlConfigConditionalSchemas
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化条件分支约束模型。
|
||||
/// </summary>
|
||||
/// <param name="ifSchema">条件判断 schema。</param>
|
||||
/// <param name="thenSchema">条件命中时需要满足的 schema。</param>
|
||||
/// <param name="elseSchema">条件未命中时需要满足的 schema。</param>
|
||||
public YamlConfigConditionalSchemas(
|
||||
YamlConfigSchemaNode ifSchema,
|
||||
YamlConfigSchemaNode? thenSchema,
|
||||
YamlConfigSchemaNode? elseSchema)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(ifSchema);
|
||||
|
||||
IfSchema = ifSchema;
|
||||
ThenSchema = thenSchema;
|
||||
ElseSchema = elseSchema;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取条件判断 schema。
|
||||
/// </summary>
|
||||
public YamlConfigSchemaNode IfSchema { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取条件命中时需要满足的 schema。
|
||||
/// </summary>
|
||||
public YamlConfigSchemaNode? ThenSchema { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取条件未命中时需要满足的 schema。
|
||||
/// </summary>
|
||||
public YamlConfigSchemaNode? ElseSchema { get; }
|
||||
}
|
||||
32
GFramework.Game/Config/YamlConfigConstantValue.cs
Normal file
32
GFramework.Game/Config/YamlConfigConstantValue.cs
Normal file
@ -0,0 +1,32 @@
|
||||
namespace GFramework.Game.Config;
|
||||
|
||||
/// <summary>
|
||||
/// 表示一个节点上声明的 <c>const</c> 约束。
|
||||
/// 该模型同时保留稳定比较键与原始 JSON 文本,分别供运行时匹配和诊断输出复用。
|
||||
/// </summary>
|
||||
internal sealed class YamlConfigConstantValue
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化常量约束模型。
|
||||
/// </summary>
|
||||
/// <param name="comparableValue">用于与 YAML 节点比较的稳定键。</param>
|
||||
/// <param name="displayValue">用于诊断输出的原始常量文本。</param>
|
||||
public YamlConfigConstantValue(string comparableValue, string displayValue)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(comparableValue);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(displayValue);
|
||||
|
||||
ComparableValue = comparableValue;
|
||||
DisplayValue = displayValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取用于运行时比较的稳定键。
|
||||
/// </summary>
|
||||
public string ComparableValue { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取用于诊断输出的原始 JSON 常量文本。
|
||||
/// </summary>
|
||||
public string DisplayValue { get; }
|
||||
}
|
||||
55
GFramework.Game/Config/YamlConfigNumericConstraints.cs
Normal file
55
GFramework.Game/Config/YamlConfigNumericConstraints.cs
Normal file
@ -0,0 +1,55 @@
|
||||
namespace GFramework.Game.Config;
|
||||
|
||||
/// <summary>
|
||||
/// 表示标量节点上声明的数值范围与步进约束。
|
||||
/// 该类型只覆盖整数 / 浮点共享的关键字,避免字符串字段继续暴露不相关的成员。
|
||||
/// </summary>
|
||||
internal sealed class YamlConfigNumericConstraints
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化数值约束模型。
|
||||
/// </summary>
|
||||
/// <param name="minimum">最小值约束。</param>
|
||||
/// <param name="maximum">最大值约束。</param>
|
||||
/// <param name="exclusiveMinimum">开区间最小值约束。</param>
|
||||
/// <param name="exclusiveMaximum">开区间最大值约束。</param>
|
||||
/// <param name="multipleOf">数值步进约束。</param>
|
||||
public YamlConfigNumericConstraints(
|
||||
double? minimum,
|
||||
double? maximum,
|
||||
double? exclusiveMinimum,
|
||||
double? exclusiveMaximum,
|
||||
double? multipleOf)
|
||||
{
|
||||
Minimum = minimum;
|
||||
Maximum = maximum;
|
||||
ExclusiveMinimum = exclusiveMinimum;
|
||||
ExclusiveMaximum = exclusiveMaximum;
|
||||
MultipleOf = multipleOf;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取最小值约束。
|
||||
/// </summary>
|
||||
public double? Minimum { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取最大值约束。
|
||||
/// </summary>
|
||||
public double? Maximum { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取开区间最小值约束。
|
||||
/// </summary>
|
||||
public double? ExclusiveMinimum { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取开区间最大值约束。
|
||||
/// </summary>
|
||||
public double? ExclusiveMaximum { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取数值步进约束。
|
||||
/// </summary>
|
||||
public double? MultipleOf { get; }
|
||||
}
|
||||
67
GFramework.Game/Config/YamlConfigObjectConstraints.cs
Normal file
67
GFramework.Game/Config/YamlConfigObjectConstraints.cs
Normal file
@ -0,0 +1,67 @@
|
||||
namespace GFramework.Game.Config;
|
||||
|
||||
/// <summary>
|
||||
/// 表示一个对象节点上声明的属性数量约束、字段依赖约束、条件子 schema 与组合约束。
|
||||
/// 该模型将对象级约束与数组 / 标量约束拆开保存,避免运行时节点继续暴露无关成员。
|
||||
/// </summary>
|
||||
internal sealed class YamlConfigObjectConstraints
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化对象约束模型。
|
||||
/// </summary>
|
||||
/// <param name="minProperties">最小属性数量约束。</param>
|
||||
/// <param name="maxProperties">最大属性数量约束。</param>
|
||||
/// <param name="dependentRequired">对象内字段依赖约束。</param>
|
||||
/// <param name="dependentSchemas">对象内条件 schema 约束。</param>
|
||||
/// <param name="allOfSchemas">对象内组合 schema 约束。</param>
|
||||
/// <param name="conditionalSchemas">对象内条件分支约束。</param>
|
||||
public YamlConfigObjectConstraints(
|
||||
int? minProperties,
|
||||
int? maxProperties,
|
||||
IReadOnlyDictionary<string, IReadOnlyList<string>>? dependentRequired,
|
||||
IReadOnlyDictionary<string, YamlConfigSchemaNode>? dependentSchemas,
|
||||
IReadOnlyList<YamlConfigSchemaNode>? allOfSchemas,
|
||||
YamlConfigConditionalSchemas? conditionalSchemas)
|
||||
{
|
||||
MinProperties = minProperties;
|
||||
MaxProperties = maxProperties;
|
||||
DependentRequired = dependentRequired;
|
||||
DependentSchemas = dependentSchemas;
|
||||
AllOfSchemas = allOfSchemas;
|
||||
ConditionalSchemas = conditionalSchemas;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取最小属性数量约束。
|
||||
/// </summary>
|
||||
public int? MinProperties { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取最大属性数量约束。
|
||||
/// </summary>
|
||||
public int? MaxProperties { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象内字段依赖约束。
|
||||
/// 键表示“触发字段”,值表示“触发字段出现后还必须存在的同级字段集合”。
|
||||
/// </summary>
|
||||
public IReadOnlyDictionary<string, IReadOnlyList<string>>? DependentRequired { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象内条件 schema 约束。
|
||||
/// 键表示“触发字段”,值表示“触发字段出现后当前对象还必须满足的额外 schema 子树”。
|
||||
/// </summary>
|
||||
public IReadOnlyDictionary<string, YamlConfigSchemaNode>? DependentSchemas { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象内 <c>allOf</c> 组合约束。
|
||||
/// 每个条目都表示“当前对象还必须额外满足的 focused constraint block”。
|
||||
/// </summary>
|
||||
public IReadOnlyList<YamlConfigSchemaNode>? AllOfSchemas { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象内 object-focused <c>if</c> / <c>then</c> / <c>else</c> 条件约束。
|
||||
/// 该模型会先用 <c>if</c> 试匹配当前对象,再只对命中的分支叠加 focused constraint block。
|
||||
/// </summary>
|
||||
public YamlConfigConditionalSchemas? ConditionalSchemas { get; }
|
||||
}
|
||||
74
GFramework.Game/Config/YamlConfigReferenceUsage.cs
Normal file
74
GFramework.Game/Config/YamlConfigReferenceUsage.cs
Normal file
@ -0,0 +1,74 @@
|
||||
namespace GFramework.Game.Config;
|
||||
|
||||
/// <summary>
|
||||
/// 表示单个 YAML 文件中提取出的跨表引用。
|
||||
/// 该模型保留源文件、字段路径和目标表等诊断信息,以便加载器在批量校验失败时给出可定位的错误。
|
||||
/// </summary>
|
||||
internal sealed class YamlConfigReferenceUsage
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化一个跨表引用使用记录。
|
||||
/// </summary>
|
||||
/// <param name="yamlPath">源 YAML 文件路径。</param>
|
||||
/// <param name="schemaPath">定义该引用的 schema 文件路径。</param>
|
||||
/// <param name="propertyPath">声明引用的字段路径。</param>
|
||||
/// <param name="rawValue">YAML 中的原始标量值。</param>
|
||||
/// <param name="referencedTableName">目标配置表名称。</param>
|
||||
/// <param name="valueType">引用值的 schema 标量类型。</param>
|
||||
public YamlConfigReferenceUsage(
|
||||
string yamlPath,
|
||||
string schemaPath,
|
||||
string propertyPath,
|
||||
string rawValue,
|
||||
string referencedTableName,
|
||||
YamlConfigSchemaPropertyType valueType)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(yamlPath);
|
||||
ArgumentNullException.ThrowIfNull(schemaPath);
|
||||
ArgumentNullException.ThrowIfNull(propertyPath);
|
||||
ArgumentNullException.ThrowIfNull(rawValue);
|
||||
ArgumentNullException.ThrowIfNull(referencedTableName);
|
||||
|
||||
YamlPath = yamlPath;
|
||||
SchemaPath = schemaPath;
|
||||
PropertyPath = propertyPath;
|
||||
RawValue = rawValue;
|
||||
ReferencedTableName = referencedTableName;
|
||||
ValueType = valueType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取源 YAML 文件路径。
|
||||
/// </summary>
|
||||
public string YamlPath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取定义该引用的 schema 文件路径。
|
||||
/// </summary>
|
||||
public string SchemaPath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取声明引用的字段路径。
|
||||
/// </summary>
|
||||
public string PropertyPath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取 YAML 中的原始标量值。
|
||||
/// </summary>
|
||||
public string RawValue { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取目标配置表名称。
|
||||
/// </summary>
|
||||
public string ReferencedTableName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取引用值的 schema 标量类型。
|
||||
/// </summary>
|
||||
public YamlConfigSchemaPropertyType ValueType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取便于诊断显示的字段路径。
|
||||
/// </summary>
|
||||
public string DisplayPath => PropertyPath;
|
||||
}
|
||||
31
GFramework.Game/Config/YamlConfigScalarConstraints.cs
Normal file
31
GFramework.Game/Config/YamlConfigScalarConstraints.cs
Normal file
@ -0,0 +1,31 @@
|
||||
namespace GFramework.Game.Config;
|
||||
|
||||
/// <summary>
|
||||
/// 聚合一个标量节点上声明的数值约束与字符串约束。
|
||||
/// 该包装层保留“标量字段有约束”的统一入口,同时把不同语义的约束分成更小的专用模型。
|
||||
/// </summary>
|
||||
internal sealed class YamlConfigScalarConstraints
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化标量约束模型。
|
||||
/// </summary>
|
||||
/// <param name="numericConstraints">数值约束分组。</param>
|
||||
/// <param name="stringConstraints">字符串约束分组。</param>
|
||||
public YamlConfigScalarConstraints(
|
||||
YamlConfigNumericConstraints? numericConstraints,
|
||||
YamlConfigStringConstraints? stringConstraints)
|
||||
{
|
||||
NumericConstraints = numericConstraints;
|
||||
StringConstraints = stringConstraints;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取数值约束分组。
|
||||
/// </summary>
|
||||
public YamlConfigNumericConstraints? NumericConstraints { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取字符串约束分组。
|
||||
/// </summary>
|
||||
public YamlConfigStringConstraints? StringConstraints { get; }
|
||||
}
|
||||
44
GFramework.Game/Config/YamlConfigSchema.cs
Normal file
44
GFramework.Game/Config/YamlConfigSchema.cs
Normal file
@ -0,0 +1,44 @@
|
||||
namespace GFramework.Game.Config;
|
||||
|
||||
/// <summary>
|
||||
/// 表示已解析并可用于运行时校验的 JSON Schema。
|
||||
/// 该模型保留根节点与引用依赖集合,避免运行时引入完整 schema 引擎。
|
||||
/// </summary>
|
||||
internal sealed class YamlConfigSchema
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化一个可用于运行时校验的 schema 模型。
|
||||
/// </summary>
|
||||
/// <param name="schemaPath">Schema 文件路径。</param>
|
||||
/// <param name="rootNode">根节点模型。</param>
|
||||
/// <param name="referencedTableNames">Schema 声明的目标引用表名称集合。</param>
|
||||
public YamlConfigSchema(
|
||||
string schemaPath,
|
||||
YamlConfigSchemaNode rootNode,
|
||||
IReadOnlyCollection<string> referencedTableNames)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(schemaPath);
|
||||
ArgumentNullException.ThrowIfNull(rootNode);
|
||||
ArgumentNullException.ThrowIfNull(referencedTableNames);
|
||||
|
||||
SchemaPath = schemaPath;
|
||||
RootNode = rootNode;
|
||||
ReferencedTableNames = referencedTableNames;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取 schema 文件路径。
|
||||
/// </summary>
|
||||
public string SchemaPath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取根节点模型。
|
||||
/// </summary>
|
||||
public YamlConfigSchemaNode RootNode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取 schema 声明的目标引用表名称集合。
|
||||
/// 该信息用于热重载时推导受影响的依赖表闭包。
|
||||
/// </summary>
|
||||
public IReadOnlyCollection<string> ReferencedTableNames { get; }
|
||||
}
|
||||
330
GFramework.Game/Config/YamlConfigSchemaNode.cs
Normal file
330
GFramework.Game/Config/YamlConfigSchemaNode.cs
Normal file
@ -0,0 +1,330 @@
|
||||
namespace GFramework.Game.Config;
|
||||
|
||||
/// <summary>
|
||||
/// 表示单个 schema 节点的最小运行时描述。
|
||||
/// 同一个模型同时覆盖对象、数组和标量,便于递归校验逻辑只依赖一种树结构。
|
||||
/// </summary>
|
||||
internal sealed class YamlConfigSchemaNode
|
||||
{
|
||||
private readonly NodeChildren _children;
|
||||
private readonly NodeValidation _validation;
|
||||
|
||||
private YamlConfigSchemaNode(
|
||||
YamlConfigSchemaPropertyType nodeType,
|
||||
NodeChildren children,
|
||||
NodeValidation validation,
|
||||
string schemaPathHint)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(children);
|
||||
ArgumentNullException.ThrowIfNull(validation);
|
||||
ArgumentNullException.ThrowIfNull(schemaPathHint);
|
||||
|
||||
_children = children;
|
||||
_validation = validation;
|
||||
NodeType = nodeType;
|
||||
Properties = children.Properties;
|
||||
RequiredProperties = children.RequiredProperties;
|
||||
ItemNode = children.ItemNode;
|
||||
ReferenceTableName = validation.ReferenceTableName;
|
||||
AllowedValues = validation.AllowedValues;
|
||||
Constraints = validation.Constraints;
|
||||
ArrayConstraints = validation.ArrayConstraints;
|
||||
ObjectConstraints = validation.ObjectConstraints;
|
||||
ConstantValue = validation.ConstantValue;
|
||||
NegatedSchemaNode = validation.NegatedSchemaNode;
|
||||
SchemaPathHint = schemaPathHint;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取节点类型。
|
||||
/// </summary>
|
||||
public YamlConfigSchemaPropertyType NodeType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象属性集合;非对象节点时返回空。
|
||||
/// </summary>
|
||||
public IReadOnlyDictionary<string, YamlConfigSchemaNode>? Properties { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象必填属性集合;非对象节点时返回空。
|
||||
/// </summary>
|
||||
public IReadOnlyCollection<string>? RequiredProperties { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取数组元素节点;非数组节点时返回空。
|
||||
/// </summary>
|
||||
public YamlConfigSchemaNode? ItemNode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取目标引用表名称;未声明跨表引用时返回空。
|
||||
/// </summary>
|
||||
public string? ReferenceTableName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取节点允许值集合;未声明 <c>enum</c> 时返回空。
|
||||
/// </summary>
|
||||
public IReadOnlyCollection<YamlConfigAllowedValue>? AllowedValues { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取标量范围与长度约束;未声明时返回空。
|
||||
/// </summary>
|
||||
public YamlConfigScalarConstraints? Constraints { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象属性数量约束;未声明时返回空。
|
||||
/// </summary>
|
||||
public YamlConfigObjectConstraints? ObjectConstraints { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取数组元素数量约束;未声明时返回空。
|
||||
/// </summary>
|
||||
public YamlConfigArrayConstraints? ArrayConstraints { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取节点常量约束;未声明 <c>const</c> 时返回空。
|
||||
/// </summary>
|
||||
public YamlConfigConstantValue? ConstantValue { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取节点声明的 <c>not</c> 子 schema;未声明时返回空。
|
||||
/// </summary>
|
||||
public YamlConfigSchemaNode? NegatedSchemaNode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取用于诊断显示的 schema 路径提示。
|
||||
/// 当前节点本身不记录独立路径,因此对象校验会回退到所属根 schema 路径。
|
||||
/// </summary>
|
||||
public string SchemaPathHint { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建对象节点描述。
|
||||
/// </summary>
|
||||
/// <param name="properties">对象属性集合。</param>
|
||||
/// <param name="requiredProperties">对象必填属性集合。</param>
|
||||
/// <param name="objectConstraints">对象属性数量约束。</param>
|
||||
/// <param name="schemaPathHint">用于错误信息的 schema 文件路径提示。</param>
|
||||
/// <returns>对象节点模型。</returns>
|
||||
public static YamlConfigSchemaNode CreateObject(
|
||||
IReadOnlyDictionary<string, YamlConfigSchemaNode>? properties,
|
||||
IReadOnlyCollection<string>? requiredProperties,
|
||||
YamlConfigObjectConstraints? objectConstraints,
|
||||
string schemaPathHint)
|
||||
{
|
||||
return new YamlConfigSchemaNode(
|
||||
YamlConfigSchemaPropertyType.Object,
|
||||
new NodeChildren(properties, requiredProperties, itemNode: null),
|
||||
new NodeValidation(
|
||||
referenceTableName: null,
|
||||
allowedValues: null,
|
||||
constraints: null,
|
||||
arrayConstraints: null,
|
||||
objectConstraints,
|
||||
constantValue: null,
|
||||
negatedSchemaNode: null),
|
||||
schemaPathHint);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建数组节点描述。
|
||||
/// </summary>
|
||||
/// <param name="itemNode">数组元素节点。</param>
|
||||
/// <param name="allowedValues">数组节点允许值集合。</param>
|
||||
/// <param name="arrayConstraints">数组元素数量约束。</param>
|
||||
/// <param name="schemaPathHint">用于错误信息的 schema 文件路径提示。</param>
|
||||
/// <returns>数组节点模型。</returns>
|
||||
public static YamlConfigSchemaNode CreateArray(
|
||||
YamlConfigSchemaNode itemNode,
|
||||
IReadOnlyCollection<YamlConfigAllowedValue>? allowedValues,
|
||||
YamlConfigArrayConstraints? arrayConstraints,
|
||||
string schemaPathHint)
|
||||
{
|
||||
return new YamlConfigSchemaNode(
|
||||
YamlConfigSchemaPropertyType.Array,
|
||||
new NodeChildren(properties: null, requiredProperties: null, itemNode),
|
||||
new NodeValidation(
|
||||
referenceTableName: null,
|
||||
allowedValues,
|
||||
constraints: null,
|
||||
arrayConstraints,
|
||||
objectConstraints: null,
|
||||
constantValue: null,
|
||||
negatedSchemaNode: null),
|
||||
schemaPathHint);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建标量节点描述。
|
||||
/// </summary>
|
||||
/// <param name="nodeType">标量节点类型。</param>
|
||||
/// <param name="referenceTableName">目标引用表名称。</param>
|
||||
/// <param name="allowedValues">标量允许值集合。</param>
|
||||
/// <param name="constraints">标量范围与长度约束。</param>
|
||||
/// <param name="schemaPathHint">用于错误信息的 schema 文件路径提示。</param>
|
||||
/// <returns>标量节点模型。</returns>
|
||||
public static YamlConfigSchemaNode CreateScalar(
|
||||
YamlConfigSchemaPropertyType nodeType,
|
||||
string? referenceTableName,
|
||||
IReadOnlyCollection<YamlConfigAllowedValue>? allowedValues,
|
||||
YamlConfigScalarConstraints? constraints,
|
||||
string schemaPathHint)
|
||||
{
|
||||
return new YamlConfigSchemaNode(
|
||||
nodeType,
|
||||
NodeChildren.None,
|
||||
new NodeValidation(
|
||||
referenceTableName,
|
||||
allowedValues,
|
||||
constraints,
|
||||
arrayConstraints: null,
|
||||
objectConstraints: null,
|
||||
constantValue: null,
|
||||
negatedSchemaNode: null),
|
||||
schemaPathHint);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 基于当前节点复制一个只替换引用表名称的新节点。
|
||||
/// 该方法用于把数组级别的 ref-table 语义挂接到元素节点上。
|
||||
/// </summary>
|
||||
/// <param name="referenceTableName">新的目标引用表名称。</param>
|
||||
/// <returns>复制后的节点。</returns>
|
||||
public YamlConfigSchemaNode WithReferenceTable(string referenceTableName)
|
||||
{
|
||||
return new YamlConfigSchemaNode(
|
||||
NodeType,
|
||||
_children,
|
||||
_validation.WithReferenceTable(referenceTableName),
|
||||
SchemaPathHint);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 基于当前节点复制一个只替换 <c>enum</c> 允许值集合的新节点。
|
||||
/// </summary>
|
||||
/// <param name="allowedValues">新的允许值集合。</param>
|
||||
/// <returns>复制后的节点。</returns>
|
||||
public YamlConfigSchemaNode WithAllowedValues(IReadOnlyCollection<YamlConfigAllowedValue>? allowedValues)
|
||||
{
|
||||
return new YamlConfigSchemaNode(
|
||||
NodeType,
|
||||
_children,
|
||||
_validation.WithAllowedValues(allowedValues),
|
||||
SchemaPathHint);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 基于当前节点复制一个只替换常量约束的新节点。
|
||||
/// </summary>
|
||||
/// <param name="constantValue">新的常量约束。</param>
|
||||
/// <returns>复制后的节点。</returns>
|
||||
public YamlConfigSchemaNode WithConstantValue(YamlConfigConstantValue? constantValue)
|
||||
{
|
||||
return new YamlConfigSchemaNode(
|
||||
NodeType,
|
||||
_children,
|
||||
_validation.WithConstantValue(constantValue),
|
||||
SchemaPathHint);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 基于当前节点复制一个只替换 <c>not</c> 子 schema 的新节点。
|
||||
/// </summary>
|
||||
/// <param name="negatedSchemaNode">新的 negated schema。</param>
|
||||
/// <returns>复制后的节点。</returns>
|
||||
public YamlConfigSchemaNode WithNegatedSchemaNode(YamlConfigSchemaNode? negatedSchemaNode)
|
||||
{
|
||||
return new YamlConfigSchemaNode(
|
||||
NodeType,
|
||||
_children,
|
||||
_validation.WithNegatedSchemaNode(negatedSchemaNode),
|
||||
SchemaPathHint);
|
||||
}
|
||||
|
||||
private sealed class NodeChildren
|
||||
{
|
||||
public NodeChildren(
|
||||
IReadOnlyDictionary<string, YamlConfigSchemaNode>? properties,
|
||||
IReadOnlyCollection<string>? requiredProperties,
|
||||
YamlConfigSchemaNode? itemNode)
|
||||
{
|
||||
Properties = properties;
|
||||
RequiredProperties = requiredProperties;
|
||||
ItemNode = itemNode;
|
||||
}
|
||||
|
||||
public static NodeChildren None { get; } = new(properties: null, requiredProperties: null, itemNode: null);
|
||||
|
||||
public IReadOnlyDictionary<string, YamlConfigSchemaNode>? Properties { get; }
|
||||
|
||||
public IReadOnlyCollection<string>? RequiredProperties { get; }
|
||||
|
||||
public YamlConfigSchemaNode? ItemNode { get; }
|
||||
}
|
||||
|
||||
private sealed class NodeValidation
|
||||
{
|
||||
public NodeValidation(
|
||||
string? referenceTableName,
|
||||
IReadOnlyCollection<YamlConfigAllowedValue>? allowedValues,
|
||||
YamlConfigScalarConstraints? constraints,
|
||||
YamlConfigArrayConstraints? arrayConstraints,
|
||||
YamlConfigObjectConstraints? objectConstraints,
|
||||
YamlConfigConstantValue? constantValue,
|
||||
YamlConfigSchemaNode? negatedSchemaNode)
|
||||
{
|
||||
ReferenceTableName = referenceTableName;
|
||||
AllowedValues = allowedValues;
|
||||
Constraints = constraints;
|
||||
ArrayConstraints = arrayConstraints;
|
||||
ObjectConstraints = objectConstraints;
|
||||
ConstantValue = constantValue;
|
||||
NegatedSchemaNode = negatedSchemaNode;
|
||||
}
|
||||
|
||||
public static NodeValidation None { get; } = new(
|
||||
referenceTableName: null,
|
||||
allowedValues: null,
|
||||
constraints: null,
|
||||
arrayConstraints: null,
|
||||
objectConstraints: null,
|
||||
constantValue: null,
|
||||
negatedSchemaNode: null);
|
||||
|
||||
public string? ReferenceTableName { get; }
|
||||
|
||||
public IReadOnlyCollection<YamlConfigAllowedValue>? AllowedValues { get; }
|
||||
|
||||
public YamlConfigScalarConstraints? Constraints { get; }
|
||||
|
||||
public YamlConfigArrayConstraints? ArrayConstraints { get; }
|
||||
|
||||
public YamlConfigObjectConstraints? ObjectConstraints { get; }
|
||||
|
||||
public YamlConfigConstantValue? ConstantValue { get; }
|
||||
|
||||
public YamlConfigSchemaNode? NegatedSchemaNode { get; }
|
||||
|
||||
public NodeValidation WithReferenceTable(string referenceTableName)
|
||||
{
|
||||
return new NodeValidation(referenceTableName, AllowedValues, Constraints, ArrayConstraints,
|
||||
ObjectConstraints, ConstantValue, NegatedSchemaNode);
|
||||
}
|
||||
|
||||
public NodeValidation WithAllowedValues(IReadOnlyCollection<YamlConfigAllowedValue>? allowedValues)
|
||||
{
|
||||
return new NodeValidation(ReferenceTableName, allowedValues, Constraints, ArrayConstraints,
|
||||
ObjectConstraints, ConstantValue, NegatedSchemaNode);
|
||||
}
|
||||
|
||||
public NodeValidation WithConstantValue(YamlConfigConstantValue? constantValue)
|
||||
{
|
||||
return new NodeValidation(ReferenceTableName, AllowedValues, Constraints, ArrayConstraints,
|
||||
ObjectConstraints, constantValue, NegatedSchemaNode);
|
||||
}
|
||||
|
||||
public NodeValidation WithNegatedSchemaNode(YamlConfigSchemaNode? negatedSchemaNode)
|
||||
{
|
||||
return new NodeValidation(ReferenceTableName, AllowedValues, Constraints, ArrayConstraints,
|
||||
ObjectConstraints, ConstantValue, negatedSchemaNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
37
GFramework.Game/Config/YamlConfigSchemaPropertyType.cs
Normal file
37
GFramework.Game/Config/YamlConfigSchemaPropertyType.cs
Normal file
@ -0,0 +1,37 @@
|
||||
namespace GFramework.Game.Config;
|
||||
|
||||
/// <summary>
|
||||
/// 表示当前运行时 schema 校验器支持的属性类型。
|
||||
/// </summary>
|
||||
internal enum YamlConfigSchemaPropertyType
|
||||
{
|
||||
/// <summary>
|
||||
/// 对象类型。
|
||||
/// </summary>
|
||||
Object,
|
||||
|
||||
/// <summary>
|
||||
/// 整数类型。
|
||||
/// </summary>
|
||||
Integer,
|
||||
|
||||
/// <summary>
|
||||
/// 数值类型。
|
||||
/// </summary>
|
||||
Number,
|
||||
|
||||
/// <summary>
|
||||
/// 布尔类型。
|
||||
/// </summary>
|
||||
Boolean,
|
||||
|
||||
/// <summary>
|
||||
/// 字符串类型。
|
||||
/// </summary>
|
||||
String,
|
||||
|
||||
/// <summary>
|
||||
/// 数组类型。
|
||||
/// </summary>
|
||||
Array
|
||||
}
|
||||
@ -3650,950 +3650,3 @@ internal static partial class YamlConfigSchemaValidator
|
||||
!string.Equals(tag, "tag:yaml.org,2002:null", StringComparison.Ordinal);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 表示已解析并可用于运行时校验的 JSON Schema。
|
||||
/// 该模型保留根节点与引用依赖集合,避免运行时引入完整 schema 引擎。
|
||||
/// </summary>
|
||||
internal sealed class YamlConfigSchema
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化一个可用于运行时校验的 schema 模型。
|
||||
/// </summary>
|
||||
/// <param name="schemaPath">Schema 文件路径。</param>
|
||||
/// <param name="rootNode">根节点模型。</param>
|
||||
/// <param name="referencedTableNames">Schema 声明的目标引用表名称集合。</param>
|
||||
public YamlConfigSchema(
|
||||
string schemaPath,
|
||||
YamlConfigSchemaNode rootNode,
|
||||
IReadOnlyCollection<string> referencedTableNames)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(schemaPath);
|
||||
ArgumentNullException.ThrowIfNull(rootNode);
|
||||
ArgumentNullException.ThrowIfNull(referencedTableNames);
|
||||
|
||||
SchemaPath = schemaPath;
|
||||
RootNode = rootNode;
|
||||
ReferencedTableNames = referencedTableNames;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取 schema 文件路径。
|
||||
/// </summary>
|
||||
public string SchemaPath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取根节点模型。
|
||||
/// </summary>
|
||||
public YamlConfigSchemaNode RootNode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取 schema 声明的目标引用表名称集合。
|
||||
/// 该信息用于热重载时推导受影响的依赖表闭包。
|
||||
/// </summary>
|
||||
public IReadOnlyCollection<string> ReferencedTableNames { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 表示单个 schema 节点的最小运行时描述。
|
||||
/// 同一个模型同时覆盖对象、数组和标量,便于递归校验逻辑只依赖一种树结构。
|
||||
/// </summary>
|
||||
internal sealed class YamlConfigSchemaNode
|
||||
{
|
||||
private readonly NodeChildren _children;
|
||||
private readonly NodeValidation _validation;
|
||||
|
||||
private YamlConfigSchemaNode(
|
||||
YamlConfigSchemaPropertyType nodeType,
|
||||
NodeChildren children,
|
||||
NodeValidation validation,
|
||||
string schemaPathHint)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(children);
|
||||
ArgumentNullException.ThrowIfNull(validation);
|
||||
ArgumentNullException.ThrowIfNull(schemaPathHint);
|
||||
|
||||
_children = children;
|
||||
_validation = validation;
|
||||
NodeType = nodeType;
|
||||
Properties = children.Properties;
|
||||
RequiredProperties = children.RequiredProperties;
|
||||
ItemNode = children.ItemNode;
|
||||
ReferenceTableName = validation.ReferenceTableName;
|
||||
AllowedValues = validation.AllowedValues;
|
||||
Constraints = validation.Constraints;
|
||||
ArrayConstraints = validation.ArrayConstraints;
|
||||
ObjectConstraints = validation.ObjectConstraints;
|
||||
ConstantValue = validation.ConstantValue;
|
||||
NegatedSchemaNode = validation.NegatedSchemaNode;
|
||||
SchemaPathHint = schemaPathHint;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取节点类型。
|
||||
/// </summary>
|
||||
public YamlConfigSchemaPropertyType NodeType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象属性集合;非对象节点时返回空。
|
||||
/// </summary>
|
||||
public IReadOnlyDictionary<string, YamlConfigSchemaNode>? Properties { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象必填属性集合;非对象节点时返回空。
|
||||
/// </summary>
|
||||
public IReadOnlyCollection<string>? RequiredProperties { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取数组元素节点;非数组节点时返回空。
|
||||
/// </summary>
|
||||
public YamlConfigSchemaNode? ItemNode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取目标引用表名称;未声明跨表引用时返回空。
|
||||
/// </summary>
|
||||
public string? ReferenceTableName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取节点允许值集合;未声明 <c>enum</c> 时返回空。
|
||||
/// </summary>
|
||||
public IReadOnlyCollection<YamlConfigAllowedValue>? AllowedValues { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取标量范围与长度约束;未声明时返回空。
|
||||
/// </summary>
|
||||
public YamlConfigScalarConstraints? Constraints { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象属性数量约束;未声明时返回空。
|
||||
/// </summary>
|
||||
public YamlConfigObjectConstraints? ObjectConstraints { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取数组元素数量约束;未声明时返回空。
|
||||
/// </summary>
|
||||
public YamlConfigArrayConstraints? ArrayConstraints { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取节点常量约束;未声明 <c>const</c> 时返回空。
|
||||
/// </summary>
|
||||
public YamlConfigConstantValue? ConstantValue { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取节点声明的 <c>not</c> 子 schema;未声明时返回空。
|
||||
/// </summary>
|
||||
public YamlConfigSchemaNode? NegatedSchemaNode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取用于诊断显示的 schema 路径提示。
|
||||
/// 当前节点本身不记录独立路径,因此对象校验会回退到所属根 schema 路径。
|
||||
/// </summary>
|
||||
public string SchemaPathHint { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建对象节点描述。
|
||||
/// </summary>
|
||||
/// <param name="properties">对象属性集合。</param>
|
||||
/// <param name="requiredProperties">对象必填属性集合。</param>
|
||||
/// <param name="objectConstraints">对象属性数量约束。</param>
|
||||
/// <param name="schemaPathHint">用于错误信息的 schema 文件路径提示。</param>
|
||||
/// <returns>对象节点模型。</returns>
|
||||
public static YamlConfigSchemaNode CreateObject(
|
||||
IReadOnlyDictionary<string, YamlConfigSchemaNode>? properties,
|
||||
IReadOnlyCollection<string>? requiredProperties,
|
||||
YamlConfigObjectConstraints? objectConstraints,
|
||||
string schemaPathHint)
|
||||
{
|
||||
return new YamlConfigSchemaNode(
|
||||
YamlConfigSchemaPropertyType.Object,
|
||||
new NodeChildren(properties, requiredProperties, itemNode: null),
|
||||
new NodeValidation(
|
||||
referenceTableName: null,
|
||||
allowedValues: null,
|
||||
constraints: null,
|
||||
arrayConstraints: null,
|
||||
objectConstraints,
|
||||
constantValue: null,
|
||||
negatedSchemaNode: null),
|
||||
schemaPathHint);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建数组节点描述。
|
||||
/// </summary>
|
||||
/// <param name="itemNode">数组元素节点。</param>
|
||||
/// <param name="allowedValues">数组节点允许值集合。</param>
|
||||
/// <param name="arrayConstraints">数组元素数量约束。</param>
|
||||
/// <param name="schemaPathHint">用于错误信息的 schema 文件路径提示。</param>
|
||||
/// <returns>数组节点模型。</returns>
|
||||
public static YamlConfigSchemaNode CreateArray(
|
||||
YamlConfigSchemaNode itemNode,
|
||||
IReadOnlyCollection<YamlConfigAllowedValue>? allowedValues,
|
||||
YamlConfigArrayConstraints? arrayConstraints,
|
||||
string schemaPathHint)
|
||||
{
|
||||
return new YamlConfigSchemaNode(
|
||||
YamlConfigSchemaPropertyType.Array,
|
||||
new NodeChildren(properties: null, requiredProperties: null, itemNode),
|
||||
new NodeValidation(
|
||||
referenceTableName: null,
|
||||
allowedValues,
|
||||
constraints: null,
|
||||
arrayConstraints,
|
||||
objectConstraints: null,
|
||||
constantValue: null,
|
||||
negatedSchemaNode: null),
|
||||
schemaPathHint);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建标量节点描述。
|
||||
/// </summary>
|
||||
/// <param name="nodeType">标量节点类型。</param>
|
||||
/// <param name="referenceTableName">目标引用表名称。</param>
|
||||
/// <param name="allowedValues">标量允许值集合。</param>
|
||||
/// <param name="constraints">标量范围与长度约束。</param>
|
||||
/// <param name="schemaPathHint">用于错误信息的 schema 文件路径提示。</param>
|
||||
/// <returns>标量节点模型。</returns>
|
||||
public static YamlConfigSchemaNode CreateScalar(
|
||||
YamlConfigSchemaPropertyType nodeType,
|
||||
string? referenceTableName,
|
||||
IReadOnlyCollection<YamlConfigAllowedValue>? allowedValues,
|
||||
YamlConfigScalarConstraints? constraints,
|
||||
string schemaPathHint)
|
||||
{
|
||||
return new YamlConfigSchemaNode(
|
||||
nodeType,
|
||||
NodeChildren.None,
|
||||
new NodeValidation(
|
||||
referenceTableName,
|
||||
allowedValues,
|
||||
constraints,
|
||||
arrayConstraints: null,
|
||||
objectConstraints: null,
|
||||
constantValue: null,
|
||||
negatedSchemaNode: null),
|
||||
schemaPathHint);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 基于当前节点复制一个只替换引用表名称的新节点。
|
||||
/// 该方法用于把数组级别的 ref-table 语义挂接到元素节点上。
|
||||
/// </summary>
|
||||
/// <param name="referenceTableName">新的目标引用表名称。</param>
|
||||
/// <returns>复制后的节点。</returns>
|
||||
public YamlConfigSchemaNode WithReferenceTable(string referenceTableName)
|
||||
{
|
||||
return new YamlConfigSchemaNode(
|
||||
NodeType,
|
||||
_children,
|
||||
_validation.WithReferenceTable(referenceTableName),
|
||||
SchemaPathHint);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 基于当前节点复制一个只替换 <c>enum</c> 允许值集合的新节点。
|
||||
/// </summary>
|
||||
/// <param name="allowedValues">新的允许值集合。</param>
|
||||
/// <returns>复制后的节点。</returns>
|
||||
public YamlConfigSchemaNode WithAllowedValues(IReadOnlyCollection<YamlConfigAllowedValue>? allowedValues)
|
||||
{
|
||||
return new YamlConfigSchemaNode(
|
||||
NodeType,
|
||||
_children,
|
||||
_validation.WithAllowedValues(allowedValues),
|
||||
SchemaPathHint);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 基于当前节点复制一个只替换常量约束的新节点。
|
||||
/// </summary>
|
||||
/// <param name="constantValue">新的常量约束。</param>
|
||||
/// <returns>复制后的节点。</returns>
|
||||
public YamlConfigSchemaNode WithConstantValue(YamlConfigConstantValue? constantValue)
|
||||
{
|
||||
return new YamlConfigSchemaNode(
|
||||
NodeType,
|
||||
_children,
|
||||
_validation.WithConstantValue(constantValue),
|
||||
SchemaPathHint);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 基于当前节点复制一个只替换 <c>not</c> 子 schema 的新节点。
|
||||
/// </summary>
|
||||
/// <param name="negatedSchemaNode">新的 negated schema。</param>
|
||||
/// <returns>复制后的节点。</returns>
|
||||
public YamlConfigSchemaNode WithNegatedSchemaNode(YamlConfigSchemaNode? negatedSchemaNode)
|
||||
{
|
||||
return new YamlConfigSchemaNode(
|
||||
NodeType,
|
||||
_children,
|
||||
_validation.WithNegatedSchemaNode(negatedSchemaNode),
|
||||
SchemaPathHint);
|
||||
}
|
||||
|
||||
private sealed class NodeChildren
|
||||
{
|
||||
public NodeChildren(
|
||||
IReadOnlyDictionary<string, YamlConfigSchemaNode>? properties,
|
||||
IReadOnlyCollection<string>? requiredProperties,
|
||||
YamlConfigSchemaNode? itemNode)
|
||||
{
|
||||
Properties = properties;
|
||||
RequiredProperties = requiredProperties;
|
||||
ItemNode = itemNode;
|
||||
}
|
||||
|
||||
public static NodeChildren None { get; } = new(properties: null, requiredProperties: null, itemNode: null);
|
||||
|
||||
public IReadOnlyDictionary<string, YamlConfigSchemaNode>? Properties { get; }
|
||||
|
||||
public IReadOnlyCollection<string>? RequiredProperties { get; }
|
||||
|
||||
public YamlConfigSchemaNode? ItemNode { get; }
|
||||
}
|
||||
|
||||
private sealed class NodeValidation
|
||||
{
|
||||
public NodeValidation(
|
||||
string? referenceTableName,
|
||||
IReadOnlyCollection<YamlConfigAllowedValue>? allowedValues,
|
||||
YamlConfigScalarConstraints? constraints,
|
||||
YamlConfigArrayConstraints? arrayConstraints,
|
||||
YamlConfigObjectConstraints? objectConstraints,
|
||||
YamlConfigConstantValue? constantValue,
|
||||
YamlConfigSchemaNode? negatedSchemaNode)
|
||||
{
|
||||
ReferenceTableName = referenceTableName;
|
||||
AllowedValues = allowedValues;
|
||||
Constraints = constraints;
|
||||
ArrayConstraints = arrayConstraints;
|
||||
ObjectConstraints = objectConstraints;
|
||||
ConstantValue = constantValue;
|
||||
NegatedSchemaNode = negatedSchemaNode;
|
||||
}
|
||||
|
||||
public static NodeValidation None { get; } = new(
|
||||
referenceTableName: null,
|
||||
allowedValues: null,
|
||||
constraints: null,
|
||||
arrayConstraints: null,
|
||||
objectConstraints: null,
|
||||
constantValue: null,
|
||||
negatedSchemaNode: null);
|
||||
|
||||
public string? ReferenceTableName { get; }
|
||||
|
||||
public IReadOnlyCollection<YamlConfigAllowedValue>? AllowedValues { get; }
|
||||
|
||||
public YamlConfigScalarConstraints? Constraints { get; }
|
||||
|
||||
public YamlConfigArrayConstraints? ArrayConstraints { get; }
|
||||
|
||||
public YamlConfigObjectConstraints? ObjectConstraints { get; }
|
||||
|
||||
public YamlConfigConstantValue? ConstantValue { get; }
|
||||
|
||||
public YamlConfigSchemaNode? NegatedSchemaNode { get; }
|
||||
|
||||
public NodeValidation WithReferenceTable(string referenceTableName)
|
||||
{
|
||||
return new NodeValidation(referenceTableName, AllowedValues, Constraints, ArrayConstraints,
|
||||
ObjectConstraints, ConstantValue, NegatedSchemaNode);
|
||||
}
|
||||
|
||||
public NodeValidation WithAllowedValues(IReadOnlyCollection<YamlConfigAllowedValue>? allowedValues)
|
||||
{
|
||||
return new NodeValidation(ReferenceTableName, allowedValues, Constraints, ArrayConstraints,
|
||||
ObjectConstraints, ConstantValue, NegatedSchemaNode);
|
||||
}
|
||||
|
||||
public NodeValidation WithConstantValue(YamlConfigConstantValue? constantValue)
|
||||
{
|
||||
return new NodeValidation(ReferenceTableName, AllowedValues, Constraints, ArrayConstraints,
|
||||
ObjectConstraints, constantValue, NegatedSchemaNode);
|
||||
}
|
||||
|
||||
public NodeValidation WithNegatedSchemaNode(YamlConfigSchemaNode? negatedSchemaNode)
|
||||
{
|
||||
return new NodeValidation(ReferenceTableName, AllowedValues, Constraints, ArrayConstraints,
|
||||
ObjectConstraints, ConstantValue, negatedSchemaNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 表示一个节点上声明的 <c>const</c> 约束。
|
||||
/// 该模型同时保留稳定比较键与原始 JSON 文本,分别供运行时匹配和诊断输出复用。
|
||||
/// </summary>
|
||||
internal sealed class YamlConfigConstantValue
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化常量约束模型。
|
||||
/// </summary>
|
||||
/// <param name="comparableValue">用于与 YAML 节点比较的稳定键。</param>
|
||||
/// <param name="displayValue">用于诊断输出的原始常量文本。</param>
|
||||
public YamlConfigConstantValue(string comparableValue, string displayValue)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(comparableValue);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(displayValue);
|
||||
|
||||
ComparableValue = comparableValue;
|
||||
DisplayValue = displayValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取用于运行时比较的稳定键。
|
||||
/// </summary>
|
||||
public string ComparableValue { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取用于诊断输出的原始 JSON 常量文本。
|
||||
/// </summary>
|
||||
public string DisplayValue { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 表示一个节点上声明的单个 <c>enum</c> 候选值。
|
||||
/// 该模型同时保留稳定比较键与原始 JSON 文本,分别供运行时匹配和诊断输出复用。
|
||||
/// </summary>
|
||||
internal sealed class YamlConfigAllowedValue
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化一个枚举候选值模型。
|
||||
/// </summary>
|
||||
/// <param name="comparableValue">用于与 YAML 节点比较的稳定键。</param>
|
||||
/// <param name="displayValue">用于诊断输出的原始 JSON 文本。</param>
|
||||
public YamlConfigAllowedValue(string comparableValue, string displayValue)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(comparableValue);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(displayValue);
|
||||
|
||||
ComparableValue = comparableValue;
|
||||
DisplayValue = displayValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取用于运行时比较的稳定键。
|
||||
/// </summary>
|
||||
public string ComparableValue { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取用于诊断输出的原始 JSON 文本。
|
||||
/// </summary>
|
||||
public string DisplayValue { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 表示一个对象节点上声明的属性数量约束、字段依赖约束、条件子 schema 与组合约束。
|
||||
/// 该模型将对象级约束与数组 / 标量约束拆开保存,避免运行时节点继续暴露无关成员。
|
||||
/// </summary>
|
||||
internal sealed class YamlConfigObjectConstraints
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化对象约束模型。
|
||||
/// </summary>
|
||||
/// <param name="minProperties">最小属性数量约束。</param>
|
||||
/// <param name="maxProperties">最大属性数量约束。</param>
|
||||
/// <param name="dependentRequired">对象内字段依赖约束。</param>
|
||||
/// <param name="dependentSchemas">对象内条件 schema 约束。</param>
|
||||
/// <param name="allOfSchemas">对象内组合 schema 约束。</param>
|
||||
/// <param name="conditionalSchemas">对象内条件分支约束。</param>
|
||||
public YamlConfigObjectConstraints(
|
||||
int? minProperties,
|
||||
int? maxProperties,
|
||||
IReadOnlyDictionary<string, IReadOnlyList<string>>? dependentRequired,
|
||||
IReadOnlyDictionary<string, YamlConfigSchemaNode>? dependentSchemas,
|
||||
IReadOnlyList<YamlConfigSchemaNode>? allOfSchemas,
|
||||
YamlConfigConditionalSchemas? conditionalSchemas)
|
||||
{
|
||||
MinProperties = minProperties;
|
||||
MaxProperties = maxProperties;
|
||||
DependentRequired = dependentRequired;
|
||||
DependentSchemas = dependentSchemas;
|
||||
AllOfSchemas = allOfSchemas;
|
||||
ConditionalSchemas = conditionalSchemas;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取最小属性数量约束。
|
||||
/// </summary>
|
||||
public int? MinProperties { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取最大属性数量约束。
|
||||
/// </summary>
|
||||
public int? MaxProperties { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象内字段依赖约束。
|
||||
/// 键表示“触发字段”,值表示“触发字段出现后还必须存在的同级字段集合”。
|
||||
/// </summary>
|
||||
public IReadOnlyDictionary<string, IReadOnlyList<string>>? DependentRequired { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象内条件 schema 约束。
|
||||
/// 键表示“触发字段”,值表示“触发字段出现后当前对象还必须满足的额外 schema 子树”。
|
||||
/// </summary>
|
||||
public IReadOnlyDictionary<string, YamlConfigSchemaNode>? DependentSchemas { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象内 <c>allOf</c> 组合约束。
|
||||
/// 每个条目都表示“当前对象还必须额外满足的 focused constraint block”。
|
||||
/// </summary>
|
||||
public IReadOnlyList<YamlConfigSchemaNode>? AllOfSchemas { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取对象内 object-focused <c>if</c> / <c>then</c> / <c>else</c> 条件约束。
|
||||
/// 该模型会先用 <c>if</c> 试匹配当前对象,再只对命中的分支叠加 focused constraint block。
|
||||
/// </summary>
|
||||
public YamlConfigConditionalSchemas? ConditionalSchemas { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 表示一个对象节点上声明的 object-focused <c>if</c> / <c>then</c> / <c>else</c> 条件约束。
|
||||
/// 三个分支都共享父对象已声明字段集合,不会把分支 schema 扩展成新的生成类型形状。
|
||||
/// </summary>
|
||||
internal sealed class YamlConfigConditionalSchemas
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化条件分支约束模型。
|
||||
/// </summary>
|
||||
/// <param name="ifSchema">条件判断 schema。</param>
|
||||
/// <param name="thenSchema">条件命中时需要满足的 schema。</param>
|
||||
/// <param name="elseSchema">条件未命中时需要满足的 schema。</param>
|
||||
public YamlConfigConditionalSchemas(
|
||||
YamlConfigSchemaNode ifSchema,
|
||||
YamlConfigSchemaNode? thenSchema,
|
||||
YamlConfigSchemaNode? elseSchema)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(ifSchema);
|
||||
|
||||
IfSchema = ifSchema;
|
||||
ThenSchema = thenSchema;
|
||||
ElseSchema = elseSchema;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取条件判断 schema。
|
||||
/// </summary>
|
||||
public YamlConfigSchemaNode IfSchema { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取条件命中时需要满足的 schema。
|
||||
/// </summary>
|
||||
public YamlConfigSchemaNode? ThenSchema { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取条件未命中时需要满足的 schema。
|
||||
/// </summary>
|
||||
public YamlConfigSchemaNode? ElseSchema { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 聚合一个标量节点上声明的数值约束与字符串约束。
|
||||
/// 该包装层保留“标量字段有约束”的统一入口,同时把不同语义的约束分成更小的专用模型。
|
||||
/// </summary>
|
||||
internal sealed class YamlConfigScalarConstraints
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化标量约束模型。
|
||||
/// </summary>
|
||||
/// <param name="numericConstraints">数值约束分组。</param>
|
||||
/// <param name="stringConstraints">字符串约束分组。</param>
|
||||
public YamlConfigScalarConstraints(
|
||||
YamlConfigNumericConstraints? numericConstraints,
|
||||
YamlConfigStringConstraints? stringConstraints)
|
||||
{
|
||||
NumericConstraints = numericConstraints;
|
||||
StringConstraints = stringConstraints;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取数值约束分组。
|
||||
/// </summary>
|
||||
public YamlConfigNumericConstraints? NumericConstraints { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取字符串约束分组。
|
||||
/// </summary>
|
||||
public YamlConfigStringConstraints? StringConstraints { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 表示标量节点上声明的数值范围与步进约束。
|
||||
/// 该类型只覆盖整数 / 浮点共享的关键字,避免字符串字段继续暴露不相关的成员。
|
||||
/// </summary>
|
||||
internal sealed class YamlConfigNumericConstraints
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化数值约束模型。
|
||||
/// </summary>
|
||||
/// <param name="minimum">最小值约束。</param>
|
||||
/// <param name="maximum">最大值约束。</param>
|
||||
/// <param name="exclusiveMinimum">开区间最小值约束。</param>
|
||||
/// <param name="exclusiveMaximum">开区间最大值约束。</param>
|
||||
/// <param name="multipleOf">数值步进约束。</param>
|
||||
public YamlConfigNumericConstraints(
|
||||
double? minimum,
|
||||
double? maximum,
|
||||
double? exclusiveMinimum,
|
||||
double? exclusiveMaximum,
|
||||
double? multipleOf)
|
||||
{
|
||||
Minimum = minimum;
|
||||
Maximum = maximum;
|
||||
ExclusiveMinimum = exclusiveMinimum;
|
||||
ExclusiveMaximum = exclusiveMaximum;
|
||||
MultipleOf = multipleOf;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取最小值约束。
|
||||
/// </summary>
|
||||
public double? Minimum { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取最大值约束。
|
||||
/// </summary>
|
||||
public double? Maximum { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取开区间最小值约束。
|
||||
/// </summary>
|
||||
public double? ExclusiveMinimum { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取开区间最大值约束。
|
||||
/// </summary>
|
||||
public double? ExclusiveMaximum { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取数值步进约束。
|
||||
/// </summary>
|
||||
public double? MultipleOf { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 表示标量节点上声明的字符串长度、模式与 format 约束。
|
||||
/// 该模型将正则原文、预编译正则和共享 format 枚举绑定保存,
|
||||
/// 保证诊断内容与运行时匹配逻辑保持一致。
|
||||
/// </summary>
|
||||
internal sealed class YamlConfigStringConstraints
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化字符串约束模型。
|
||||
/// </summary>
|
||||
/// <param name="minLength">最小长度约束。</param>
|
||||
/// <param name="maxLength">最大长度约束。</param>
|
||||
/// <param name="pattern">正则模式约束原文。</param>
|
||||
/// <param name="patternRegex">已编译的正则表达式。</param>
|
||||
/// <param name="formatConstraint">字符串 format 约束。</param>
|
||||
public YamlConfigStringConstraints(
|
||||
int? minLength,
|
||||
int? maxLength,
|
||||
string? pattern,
|
||||
Regex? patternRegex,
|
||||
YamlConfigStringFormatConstraint? formatConstraint)
|
||||
{
|
||||
MinLength = minLength;
|
||||
MaxLength = maxLength;
|
||||
Pattern = pattern;
|
||||
PatternRegex = patternRegex;
|
||||
FormatConstraint = formatConstraint;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取最小长度约束。
|
||||
/// </summary>
|
||||
public int? MinLength { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取最大长度约束。
|
||||
/// </summary>
|
||||
public int? MaxLength { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取正则模式约束原文。
|
||||
/// </summary>
|
||||
public string? Pattern { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取已编译的正则表达式。
|
||||
/// </summary>
|
||||
public Regex? PatternRegex { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取字符串 format 约束。
|
||||
/// </summary>
|
||||
public YamlConfigStringFormatConstraint? FormatConstraint { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 表示一个已归一化的字符串 format 约束。
|
||||
/// 该模型同时保留 schema 原文与共享枚举,方便诊断信息稳定展示,又避免运行时校验反复解析字符串。
|
||||
/// </summary>
|
||||
internal sealed class YamlConfigStringFormatConstraint
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化字符串 format 约束模型。
|
||||
/// </summary>
|
||||
/// <param name="schemaName">schema 中声明的 format 名称。</param>
|
||||
/// <param name="kind">归一化后的共享 format 枚举。</param>
|
||||
public YamlConfigStringFormatConstraint(
|
||||
string schemaName,
|
||||
YamlConfigStringFormatKind kind)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(schemaName);
|
||||
|
||||
SchemaName = schemaName;
|
||||
Kind = kind;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取 schema 中声明的 format 名称。
|
||||
/// </summary>
|
||||
public string SchemaName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取归一化后的共享 format 枚举。
|
||||
/// </summary>
|
||||
public YamlConfigStringFormatKind Kind { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 表示当前 Runtime / Generator / Tooling 共享支持的字符串 format 子集。
|
||||
/// </summary>
|
||||
internal enum YamlConfigStringFormatKind
|
||||
{
|
||||
/// <summary>
|
||||
/// 表示 <c>yyyy-MM-dd</c> 形式的日期。
|
||||
/// </summary>
|
||||
Date,
|
||||
|
||||
/// <summary>
|
||||
/// 表示带显式时区偏移的 RFC 3339 日期时间。
|
||||
/// </summary>
|
||||
DateTime,
|
||||
|
||||
/// <summary>
|
||||
/// 表示 day-time duration 形式的持续时间。
|
||||
/// </summary>
|
||||
Duration,
|
||||
|
||||
/// <summary>
|
||||
/// 表示基础电子邮件地址格式。
|
||||
/// </summary>
|
||||
Email,
|
||||
|
||||
/// <summary>
|
||||
/// 表示带显式时区偏移的 RFC 3339 时间。
|
||||
/// </summary>
|
||||
Time,
|
||||
|
||||
/// <summary>
|
||||
/// 表示绝对 URI。
|
||||
/// </summary>
|
||||
Uri,
|
||||
|
||||
/// <summary>
|
||||
/// 表示连字符分隔的 UUID 文本。
|
||||
/// </summary>
|
||||
Uuid
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 表示一个数组节点上声明的元素数量、去重与 contains 匹配计数约束。
|
||||
/// 该模型与标量约束拆分保存,避免数组节点继续共享不适用的标量字段。
|
||||
/// </summary>
|
||||
internal sealed class YamlConfigArrayConstraints
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化数组约束模型。
|
||||
/// </summary>
|
||||
/// <param name="minItems">最小元素数量约束。</param>
|
||||
/// <param name="maxItems">最大元素数量约束。</param>
|
||||
/// <param name="uniqueItems">是否要求数组元素唯一。</param>
|
||||
/// <param name="containsConstraints">数组 contains 约束;未声明时为空。</param>
|
||||
public YamlConfigArrayConstraints(
|
||||
int? minItems,
|
||||
int? maxItems,
|
||||
bool uniqueItems,
|
||||
YamlConfigArrayContainsConstraints? containsConstraints)
|
||||
{
|
||||
MinItems = minItems;
|
||||
MaxItems = maxItems;
|
||||
UniqueItems = uniqueItems;
|
||||
ContainsConstraints = containsConstraints;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取最小元素数量约束。
|
||||
/// </summary>
|
||||
public int? MinItems { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取最大元素数量约束。
|
||||
/// </summary>
|
||||
public int? MaxItems { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取是否要求数组元素唯一。
|
||||
/// </summary>
|
||||
public bool UniqueItems { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取数组 contains 约束;未声明时返回空。
|
||||
/// </summary>
|
||||
public YamlConfigArrayContainsConstraints? ContainsConstraints { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 表示数组节点声明的 <c>contains</c> 匹配约束。
|
||||
/// 该模型把 contains 子 schema 与匹配数量边界聚合在一起,避免数组节点再额外散落多组相关成员。
|
||||
/// </summary>
|
||||
internal sealed class YamlConfigArrayContainsConstraints
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化数组 contains 约束模型。
|
||||
/// </summary>
|
||||
/// <param name="containsNode">contains 子 schema。</param>
|
||||
/// <param name="minContains">最小匹配数量;为 <see langword="null" /> 时按 JSON Schema 语义默认 1。</param>
|
||||
/// <param name="maxContains">最大匹配数量。</param>
|
||||
public YamlConfigArrayContainsConstraints(
|
||||
YamlConfigSchemaNode containsNode,
|
||||
int? minContains,
|
||||
int? maxContains)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(containsNode);
|
||||
|
||||
ContainsNode = containsNode;
|
||||
MinContains = minContains;
|
||||
MaxContains = maxContains;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取 contains 子 schema。
|
||||
/// </summary>
|
||||
public YamlConfigSchemaNode ContainsNode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取最小匹配数量;未显式声明时返回空,由调用方按默认值 1 解释。
|
||||
/// </summary>
|
||||
public int? MinContains { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取最大匹配数量。
|
||||
/// </summary>
|
||||
public int? MaxContains { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 表示单个 YAML 文件中提取出的跨表引用。
|
||||
/// 该模型保留源文件、字段路径和目标表等诊断信息,以便加载器在批量校验失败时给出可定位的错误。
|
||||
/// </summary>
|
||||
internal sealed class YamlConfigReferenceUsage
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化一个跨表引用使用记录。
|
||||
/// </summary>
|
||||
/// <param name="yamlPath">源 YAML 文件路径。</param>
|
||||
/// <param name="schemaPath">定义该引用的 schema 文件路径。</param>
|
||||
/// <param name="propertyPath">声明引用的字段路径。</param>
|
||||
/// <param name="rawValue">YAML 中的原始标量值。</param>
|
||||
/// <param name="referencedTableName">目标配置表名称。</param>
|
||||
/// <param name="valueType">引用值的 schema 标量类型。</param>
|
||||
public YamlConfigReferenceUsage(
|
||||
string yamlPath,
|
||||
string schemaPath,
|
||||
string propertyPath,
|
||||
string rawValue,
|
||||
string referencedTableName,
|
||||
YamlConfigSchemaPropertyType valueType)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(yamlPath);
|
||||
ArgumentNullException.ThrowIfNull(schemaPath);
|
||||
ArgumentNullException.ThrowIfNull(propertyPath);
|
||||
ArgumentNullException.ThrowIfNull(rawValue);
|
||||
ArgumentNullException.ThrowIfNull(referencedTableName);
|
||||
|
||||
YamlPath = yamlPath;
|
||||
SchemaPath = schemaPath;
|
||||
PropertyPath = propertyPath;
|
||||
RawValue = rawValue;
|
||||
ReferencedTableName = referencedTableName;
|
||||
ValueType = valueType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取源 YAML 文件路径。
|
||||
/// </summary>
|
||||
public string YamlPath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取定义该引用的 schema 文件路径。
|
||||
/// </summary>
|
||||
public string SchemaPath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取声明引用的字段路径。
|
||||
/// </summary>
|
||||
public string PropertyPath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取 YAML 中的原始标量值。
|
||||
/// </summary>
|
||||
public string RawValue { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取目标配置表名称。
|
||||
/// </summary>
|
||||
public string ReferencedTableName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取引用值的 schema 标量类型。
|
||||
/// </summary>
|
||||
public YamlConfigSchemaPropertyType ValueType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取便于诊断显示的字段路径。
|
||||
/// </summary>
|
||||
public string DisplayPath => PropertyPath;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 表示当前运行时 schema 校验器支持的属性类型。
|
||||
/// </summary>
|
||||
internal enum YamlConfigSchemaPropertyType
|
||||
{
|
||||
/// <summary>
|
||||
/// 对象类型。
|
||||
/// </summary>
|
||||
Object,
|
||||
|
||||
/// <summary>
|
||||
/// 整数类型。
|
||||
/// </summary>
|
||||
Integer,
|
||||
|
||||
/// <summary>
|
||||
/// 数值类型。
|
||||
/// </summary>
|
||||
Number,
|
||||
|
||||
/// <summary>
|
||||
/// 布尔类型。
|
||||
/// </summary>
|
||||
Boolean,
|
||||
|
||||
/// <summary>
|
||||
/// 字符串类型。
|
||||
/// </summary>
|
||||
String,
|
||||
|
||||
/// <summary>
|
||||
/// 数组类型。
|
||||
/// </summary>
|
||||
Array
|
||||
}
|
||||
|
||||
58
GFramework.Game/Config/YamlConfigStringConstraints.cs
Normal file
58
GFramework.Game/Config/YamlConfigStringConstraints.cs
Normal file
@ -0,0 +1,58 @@
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace GFramework.Game.Config;
|
||||
|
||||
/// <summary>
|
||||
/// 表示标量节点上声明的字符串长度、模式与 format 约束。
|
||||
/// 该模型将正则原文、预编译正则和共享 format 枚举绑定保存,
|
||||
/// 保证诊断内容与运行时匹配逻辑保持一致。
|
||||
/// </summary>
|
||||
internal sealed class YamlConfigStringConstraints
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化字符串约束模型。
|
||||
/// </summary>
|
||||
/// <param name="minLength">最小长度约束。</param>
|
||||
/// <param name="maxLength">最大长度约束。</param>
|
||||
/// <param name="pattern">正则模式约束原文。</param>
|
||||
/// <param name="patternRegex">已编译的正则表达式。</param>
|
||||
/// <param name="formatConstraint">字符串 format 约束。</param>
|
||||
public YamlConfigStringConstraints(
|
||||
int? minLength,
|
||||
int? maxLength,
|
||||
string? pattern,
|
||||
Regex? patternRegex,
|
||||
YamlConfigStringFormatConstraint? formatConstraint)
|
||||
{
|
||||
MinLength = minLength;
|
||||
MaxLength = maxLength;
|
||||
Pattern = pattern;
|
||||
PatternRegex = patternRegex;
|
||||
FormatConstraint = formatConstraint;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取最小长度约束。
|
||||
/// </summary>
|
||||
public int? MinLength { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取最大长度约束。
|
||||
/// </summary>
|
||||
public int? MaxLength { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取正则模式约束原文。
|
||||
/// </summary>
|
||||
public string? Pattern { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取已编译的正则表达式。
|
||||
/// </summary>
|
||||
public Regex? PatternRegex { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取字符串 format 约束。
|
||||
/// </summary>
|
||||
public YamlConfigStringFormatConstraint? FormatConstraint { get; }
|
||||
}
|
||||
33
GFramework.Game/Config/YamlConfigStringFormatConstraint.cs
Normal file
33
GFramework.Game/Config/YamlConfigStringFormatConstraint.cs
Normal file
@ -0,0 +1,33 @@
|
||||
namespace GFramework.Game.Config;
|
||||
|
||||
/// <summary>
|
||||
/// 表示一个已归一化的字符串 format 约束。
|
||||
/// 该模型同时保留 schema 原文与共享枚举,方便诊断信息稳定展示,又避免运行时校验反复解析字符串。
|
||||
/// </summary>
|
||||
internal sealed class YamlConfigStringFormatConstraint
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化字符串 format 约束模型。
|
||||
/// </summary>
|
||||
/// <param name="schemaName">schema 中声明的 format 名称。</param>
|
||||
/// <param name="kind">归一化后的共享 format 枚举。</param>
|
||||
public YamlConfigStringFormatConstraint(
|
||||
string schemaName,
|
||||
YamlConfigStringFormatKind kind)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(schemaName);
|
||||
|
||||
SchemaName = schemaName;
|
||||
Kind = kind;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取 schema 中声明的 format 名称。
|
||||
/// </summary>
|
||||
public string SchemaName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取归一化后的共享 format 枚举。
|
||||
/// </summary>
|
||||
public YamlConfigStringFormatKind Kind { get; }
|
||||
}
|
||||
42
GFramework.Game/Config/YamlConfigStringFormatKind.cs
Normal file
42
GFramework.Game/Config/YamlConfigStringFormatKind.cs
Normal file
@ -0,0 +1,42 @@
|
||||
namespace GFramework.Game.Config;
|
||||
|
||||
/// <summary>
|
||||
/// 表示当前 Runtime / Generator / Tooling 共享支持的字符串 format 子集。
|
||||
/// </summary>
|
||||
internal enum YamlConfigStringFormatKind
|
||||
{
|
||||
/// <summary>
|
||||
/// 表示 <c>yyyy-MM-dd</c> 形式的日期。
|
||||
/// </summary>
|
||||
Date,
|
||||
|
||||
/// <summary>
|
||||
/// 表示带显式时区偏移的 RFC 3339 日期时间。
|
||||
/// </summary>
|
||||
DateTime,
|
||||
|
||||
/// <summary>
|
||||
/// 表示 day-time duration 形式的持续时间。
|
||||
/// </summary>
|
||||
Duration,
|
||||
|
||||
/// <summary>
|
||||
/// 表示基础电子邮件地址格式。
|
||||
/// </summary>
|
||||
Email,
|
||||
|
||||
/// <summary>
|
||||
/// 表示带显式时区偏移的 RFC 3339 时间。
|
||||
/// </summary>
|
||||
Time,
|
||||
|
||||
/// <summary>
|
||||
/// 表示绝对 URI。
|
||||
/// </summary>
|
||||
Uri,
|
||||
|
||||
/// <summary>
|
||||
/// 表示连字符分隔的 UUID 文本。
|
||||
/// </summary>
|
||||
Uuid
|
||||
}
|
||||
@ -12,7 +12,8 @@
|
||||
- `2026-04-29` 使用 `$gframework-batch-boot 50` 从 clean build warning 基线继续分批清理 analyzer warnings
|
||||
- 已接受三个 worker 的 `GFramework.Cqrs.Tests/Mediator/*` 独立切片,三个 Mediator 测试文件的 warning 已清零
|
||||
- 主线程补齐 `YamlConfigSchemaValidator` 运行时正则 timeout 与 ordinal 字符串比较,先收掉低风险 `MA0009` / `MA0006`
|
||||
- 当前停止条件为相对 `origin/main` 接近 `50` 个变更文件;本轮尚未接近阈值,下一批可继续处理 `GFramework.Game/Config/YamlConfigSchemaValidator*`
|
||||
- 已收口两个 Game 追加切片:`YamlConfigSchemaValidator.ObjectKeywords.cs` 方法拆分与 schema model 类型拆文件
|
||||
- 当前停止条件为相对 `origin/main` 接近 `50` 个变更文件;本轮按用户要求到此结束,不再继续开新切片
|
||||
|
||||
## 当前活跃事实
|
||||
|
||||
@ -21,27 +22,30 @@
|
||||
- `dotnet clean -p:RestoreFallbackFolders= -v:quiet`
|
||||
- 最新结果:成功;标准 `dotnet clean` 仍会先命中当前 WSL 环境的 Windows NuGet fallback 目录,已按既有环境口径先执行 `dotnet restore GFramework.sln -p:RestoreFallbackFolders= --disable-parallel` 后清理
|
||||
- `dotnet build -p:RestoreFallbackFolders= -clp:WarningsOnly -v:minimal -m:1 -nodeReuse:false`
|
||||
- 最新结果:成功;`75` warnings、`0` errors;warning 从本轮基线 `236` 降到 `75`
|
||||
- 最新结果:成功;`15` warnings、`0` errors;warning 从本轮基线 `236` 降到 `15`
|
||||
- `dotnet build GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release -p:RestoreFallbackFolders= -m:1 -nodeReuse:false -clp:Summary`
|
||||
- 最新结果:成功;`0 Warning(s)`、`0 Error(s)`
|
||||
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --no-build -p:RestoreFallbackFolders= -m:1 -nodeReuse:false --filter "FullyQualifiedName~Mediator"`
|
||||
- 最新结果:成功;`45` 通过、`0` 失败
|
||||
- `dotnet build GFramework.Game/GFramework.Game.csproj -c Release -p:RestoreFallbackFolders= -m:1 -nodeReuse:false -clp:Summary`
|
||||
- 最新结果:成功;`75 Warning(s)`、`0 Error(s)`;剩余均为 `YamlConfigSchemaValidator*` 的 `MA0048` / `MA0051`
|
||||
- 最新结果:成功;`0 Warning(s)`、`0 Error(s)`
|
||||
- `dotnet test GFramework.Game.Tests/GFramework.Game.Tests.csproj -c Release -p:RestoreFallbackFolders= -m:1 -nodeReuse:false --filter "FullyQualifiedName~YamlConfigLoaderTests|FullyQualifiedName~YamlConfigSchemaValidatorTests"`
|
||||
- 最新结果:成功;`80` 通过、`0` 失败
|
||||
- 当前批次摘要:
|
||||
- 当前已提交分支相对 `origin/main...HEAD` 包含 `3` 个变更文件;本次主线程待提交的 `GFramework.Game/Config/YamlConfigSchemaValidator.cs` 与 `ai-plan` 文档会把累计变更推到约 `6` 个文件,低于 `50` 个文件阈值
|
||||
- 当前分支提交后预计相对 `origin/main...HEAD` 包含 `22` 个变更文件,低于 `50` 个文件阈值
|
||||
- 已完成 worker 切片:
|
||||
- `ed269d4`:`MediatorArchitectureIntegrationTests.cs`,清理 `MA0048` / `MA0004` / `MA0016`
|
||||
- `121df44`:`MediatorAdvancedFeaturesTests.cs`,清理 `MA0048` / `MA0004` / `MA0015`
|
||||
- `9109eec`:`MediatorComprehensiveTests.cs`,清理 `MA0048` / `MA0004` / `MA0016` / `MA0002` / `MA0015`
|
||||
- 主线程切片:`YamlConfigSchemaValidator.cs` 正则 timeout 与 ordinal equality,清理 `MA0009` / `MA0006`
|
||||
- Game 追加切片:
|
||||
- `1395b84`:`YamlConfigSchemaValidator.ObjectKeywords.cs`,清理该文件 `MA0051`
|
||||
- 待提交:将 `YamlConfigSchemaValidator.cs` 末尾 schema model 类型拆到独立同名文件,清理 `MA0048`
|
||||
|
||||
## 当前风险
|
||||
|
||||
- `GFramework.Game/Config/YamlConfigSchemaValidator*` 仍然是仓库根 warning 热点,剩余 `45` 条 `MA0048` 与 `30` 条 `MA0051`。
|
||||
- 缓解措施:下一批优先把 `YamlConfigSchemaValidator.cs` 末尾 schema model 类型拆到独立文件,再评估 `MA0051` 方法拆分。
|
||||
- `GFramework.Game/Config/YamlConfigSchemaValidator.cs` 仍有 `5` 个 `MA0051` 方法长度 warning,跨 `net8.0` / `net9.0` / `net10.0` 重复为 `15` 条。
|
||||
- 缓解措施:下一轮只做主 validator 方法拆分,不再混入拆文件或正则安全修复。
|
||||
- 标准 `dotnet clean` 在当前 WSL 环境仍会读取失效的 Windows fallback package folder。
|
||||
- 缓解措施:本主题验证继续沿用 `-p:RestoreFallbackFolders=`,必要时先执行 solution restore 刷新 Linux 侧资产。
|
||||
|
||||
@ -65,12 +69,12 @@
|
||||
|
||||
- 权威验证结果统一维护在“当前活跃事实”。
|
||||
- `GFramework.Cqrs.Tests` 的当前受影响项目 Release 构建已清零,并通过 Mediator 定向测试回归。
|
||||
- `GFramework.Game` 当前低风险正则 / 字符串比较切片通过 Release 构建与 config 定向测试;剩余 warning 属于拆文件与复杂度拆分。
|
||||
- `GFramework.Game` 当前 Release 构建已清零,并通过 config 定向测试;仓库 Debug 构建剩余 warning 属于主 validator 方法复杂度拆分。
|
||||
- `git diff --check` 结果为空,说明本轮新增改动没有引入新的尾随空格或冲突标记。
|
||||
- warning reduction 的仓库级真值以同轮 `dotnet build`、定向 `dotnet test` 与 `git diff --check` 为准,并与 trace 中的验证里程碑保持一致。
|
||||
|
||||
## 下一步建议
|
||||
|
||||
1. 提交主线程 `YamlConfigSchemaValidator` 正则安全补丁与本轮 `ai-plan` 同步。
|
||||
2. 继续下一批 `GFramework.Game/Config/YamlConfigSchemaValidator.cs` 末尾 schema model 类型拆文件,目标清理 `MA0048`。
|
||||
3. 再评估 `YamlConfigSchemaValidator.ObjectKeywords.cs` 与主 validator 的 `MA0051` 方法拆分,避免单批触碰过多高耦合逻辑。
|
||||
1. 提交 schema model 拆文件与本轮 `ai-plan` 收口。
|
||||
2. 下一轮只处理 `GFramework.Game/Config/YamlConfigSchemaValidator.cs` 剩余 `MA0051` 方法拆分。
|
||||
3. 保持 `RestoreFallbackFolders=` 验证口径,避免当前 WSL fallback package folder 干扰。
|
||||
|
||||
@ -17,27 +17,33 @@
|
||||
- 主线程实施:
|
||||
- 在 `GFramework.Game/Config/YamlConfigSchemaValidator.cs` 为固定格式正则与 schema `pattern` 正则补充 timeout,避免运行时正则输入继续触发 `MA0009`
|
||||
- 将三处字符串等值比较改为 ordinal `string.Equals`,清理 `MA0006`
|
||||
- 接受 `1395b84` 的 `YamlConfigSchemaValidator.ObjectKeywords.cs` 方法拆分,清理该文件 `MA0051`
|
||||
- 收口被中止 worker 留下的 schema model 拆文件变更,将 `YamlConfigSchemaValidator.cs` 末尾类型移动到同名文件,清理 `MA0048`
|
||||
- 验证里程碑:
|
||||
- `dotnet build GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release -p:RestoreFallbackFolders= -m:1 -nodeReuse:false -clp:Summary`
|
||||
- 结果:成功;`0 Warning(s)`、`0 Error(s)`
|
||||
- `dotnet test GFramework.Cqrs.Tests/GFramework.Cqrs.Tests.csproj -c Release --no-build -p:RestoreFallbackFolders= -m:1 -nodeReuse:false --filter "FullyQualifiedName~Mediator"`
|
||||
- 结果:成功;`45` 通过、`0` 失败
|
||||
- `dotnet build GFramework.Game/GFramework.Game.csproj -c Release -p:RestoreFallbackFolders= -m:1 -nodeReuse:false -clp:Summary`
|
||||
- 结果:成功;`75 Warning(s)`、`0 Error(s)`
|
||||
- 结果:成功;`0 Warning(s)`、`0 Error(s)`
|
||||
- `dotnet test GFramework.Game.Tests/GFramework.Game.Tests.csproj -c Release -p:RestoreFallbackFolders= -m:1 -nodeReuse:false --filter "FullyQualifiedName~YamlConfigLoaderTests|FullyQualifiedName~YamlConfigSchemaValidatorTests"`
|
||||
- 结果:成功;`80` 通过、`0` 失败
|
||||
- `dotnet clean -p:RestoreFallbackFolders= -v:quiet`
|
||||
- 结果:成功
|
||||
- `dotnet build -p:RestoreFallbackFolders= -clp:WarningsOnly -v:minimal -m:1 -nodeReuse:false`
|
||||
- 结果:成功;`75` warnings、`0` errors
|
||||
- 中间结果:成功;`75` warnings、`0` errors
|
||||
- `dotnet clean -p:RestoreFallbackFolders= -v:quiet`
|
||||
- 结果:成功
|
||||
- `dotnet build -p:RestoreFallbackFolders= -clp:Summary -v:minimal -m:1 -nodeReuse:false`
|
||||
- 结果:成功;`15 Warning(s)`、`0 Error(s)`
|
||||
- `git diff --check`
|
||||
- 结果:成功;无新增 whitespace / conflict-marker 问题
|
||||
- 当前指标:
|
||||
- warning 总数:`236` -> `75`
|
||||
- 剩余 warning 分布:`GFramework.Game/Config/YamlConfigSchemaValidator.cs` `60` 条,`GFramework.Game/Config/YamlConfigSchemaValidator.ObjectKeywords.cs` `15` 条;规则为 `MA0048` `45` 条、`MA0051` `30` 条
|
||||
- 已提交分支 diff:`3` 个文件;主线程待提交后预计约 `6` 个文件,低于 `50` 个文件阈值
|
||||
- warning 总数:`236` -> `15`
|
||||
- 剩余 warning 分布:`GFramework.Game/Config/YamlConfigSchemaValidator.cs` 的 `MA0051` `15` 条(5 个方法跨 3 个 TFM)
|
||||
- 本轮提交后预计分支 diff:`22` 个文件,低于 `50` 个文件阈值
|
||||
- 下一步:
|
||||
- 提交主线程 Game / ai-plan 同步后,继续 `YamlConfigSchemaValidator.cs` 末尾 schema model 类型拆文件,优先清理 `MA0048`
|
||||
- 按用户要求本轮到此结束;下一轮只处理 `YamlConfigSchemaValidator.cs` 剩余 `MA0051` 方法拆分
|
||||
|
||||
## 2026-04-28 — RP-092
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user