mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-05-11 04:04:29 +08:00
feat(config): 添加YAML配置序列化和校验功能
- 实现YamlConfigTextSerializer提供YAML文本序列化功能 - 实现YamlConfigTextValidator提供YAML文本校验功能 - 添加缓存机制优化schema文件加载性能 - 实现同步和异步校验接口支持 - 添加集成测试验证生成配置绑定功能 - 扩展SchemaConfigGenerator支持配置类型生成 - 实现GeneratedConfigConsumerIntegrationTests完整测试覆盖
This commit is contained in:
parent
7473adb789
commit
12e54ce637
@ -263,7 +263,7 @@ public class GeneratedConfigConsumerIntegrationTests
|
||||
Assert.That(yaml, Does.Contain("name: Bat"));
|
||||
Assert.That(yaml, Does.Contain("hp: 12"));
|
||||
Assert.That(yaml, Does.Contain("faction: cave"));
|
||||
Assert.That(yaml.EndsWith(Environment.NewLine, StringComparison.Ordinal), Is.True);
|
||||
Assert.That(yaml.EndsWith("\n", StringComparison.Ordinal), Is.True);
|
||||
});
|
||||
|
||||
Assert.DoesNotThrow(() =>
|
||||
|
||||
@ -0,0 +1,60 @@
|
||||
using GFramework.Game.Config;
|
||||
|
||||
namespace GFramework.Game.Tests.Config;
|
||||
|
||||
/// <summary>
|
||||
/// 验证公开 YAML 文本序列化入口的换行与参数契约。
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public sealed class YamlConfigTextSerializerTests
|
||||
{
|
||||
/// <summary>
|
||||
/// 验证序列化结果会稳定地以 LF 作为尾随换行,
|
||||
/// 避免不同宿主平台的行尾约定影响生成内容。
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Serialize_Should_Use_Trailing_Lf_Newline()
|
||||
{
|
||||
var yaml = YamlConfigTextSerializer.Serialize(new MonsterYamlStub
|
||||
{
|
||||
Id = 1,
|
||||
Name = "Slime"
|
||||
});
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(yaml, Does.Contain("id: 1"));
|
||||
Assert.That(yaml, Does.Contain("name: Slime"));
|
||||
Assert.That(yaml.EndsWith("\n", StringComparison.Ordinal), Is.True);
|
||||
Assert.That(yaml.EndsWith("\r\n", StringComparison.Ordinal), Is.False);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证空对象引用会继续通过参数异常暴露给调用方。
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Serialize_Should_Throw_When_Value_Is_Null()
|
||||
{
|
||||
var exception = Assert.Throws<ArgumentNullException>(() =>
|
||||
YamlConfigTextSerializer.Serialize<MonsterYamlStub>(null!));
|
||||
|
||||
Assert.That(exception!.ParamName, Is.EqualTo("value"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 用于 YAML 序列化测试的最小配置对象。
|
||||
/// </summary>
|
||||
private sealed class MonsterYamlStub
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置配置标识。
|
||||
/// </summary>
|
||||
public int Id { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置配置名称。
|
||||
/// </summary>
|
||||
public string Name { get; init; } = string.Empty;
|
||||
}
|
||||
}
|
||||
@ -143,6 +143,60 @@ public sealed class YamlConfigTextValidatorTests
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证公开校验入口会在 schema 文件发生变化后失效旧缓存,
|
||||
/// 避免保存路径持续沿用过期的字段约束。
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Validate_Should_Refresh_Cached_Schema_When_File_Timestamp_Changes()
|
||||
{
|
||||
var schemaPath = CreateSchemaFile(
|
||||
"schemas/monster.schema.json",
|
||||
"""
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["id", "name", "hp"],
|
||||
"properties": {
|
||||
"id": { "type": "integer" },
|
||||
"name": { "type": "string" },
|
||||
"hp": { "type": "integer" }
|
||||
}
|
||||
}
|
||||
""");
|
||||
var yaml = """
|
||||
id: 1
|
||||
name: Slime
|
||||
hp: 10
|
||||
""";
|
||||
|
||||
Assert.DoesNotThrow(() =>
|
||||
YamlConfigTextValidator.Validate("monster", schemaPath, "monster/generated.yaml", yaml));
|
||||
|
||||
File.WriteAllText(
|
||||
schemaPath,
|
||||
"""
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["id", "name"],
|
||||
"properties": {
|
||||
"id": { "type": "integer" },
|
||||
"name": { "type": "string" }
|
||||
}
|
||||
}
|
||||
""".Replace("\n", Environment.NewLine, StringComparison.Ordinal));
|
||||
File.SetLastWriteTimeUtc(schemaPath, new DateTime(2040, 1, 1, 0, 0, 1, DateTimeKind.Utc));
|
||||
|
||||
var exception = Assert.Throws<ConfigLoadException>(() =>
|
||||
YamlConfigTextValidator.Validate("monster", schemaPath, "monster/generated.yaml", yaml));
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(exception, Is.Not.Null);
|
||||
Assert.That(exception!.Diagnostic.FailureKind, Is.EqualTo(ConfigLoadFailureKind.UnknownProperty));
|
||||
Assert.That(exception.Diagnostic.SchemaPath, Is.EqualTo(schemaPath));
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在临时目录中创建 schema 文件。
|
||||
/// </summary>
|
||||
|
||||
@ -8,26 +8,36 @@ namespace GFramework.Game.Config;
|
||||
/// </summary>
|
||||
public static class YamlConfigTextSerializer
|
||||
{
|
||||
private static readonly ISerializer Serializer = new SerializerBuilder()
|
||||
.WithNamingConvention(CamelCaseNamingConvention.Instance)
|
||||
.DisableAliases()
|
||||
.ConfigureDefaultValuesHandling(DefaultValuesHandling.Preserve)
|
||||
.Build();
|
||||
|
||||
/// <summary>
|
||||
/// 将配置对象序列化为 YAML 文本。
|
||||
/// 将配置对象序列化为 YAML 文本,并统一以 LF 作为尾随换行。
|
||||
/// 该约定与底层 YamlDotNet 输出保持一致,避免不同操作系统的宿主行尾约定影响生成结果。
|
||||
/// </summary>
|
||||
/// <typeparam name="TValue">配置对象类型。</typeparam>
|
||||
/// <param name="value">要序列化的配置对象。</param>
|
||||
/// <returns>带尾随换行的 YAML 文本。</returns>
|
||||
/// <returns>带尾随 LF 换行的 YAML 文本。</returns>
|
||||
/// <exception cref="ArgumentNullException">当 <paramref name="value" /> 为 <see langword="null" /> 时抛出。</exception>
|
||||
public static string Serialize<TValue>(TValue value)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(value);
|
||||
|
||||
var yaml = Serializer.Serialize(value);
|
||||
// Build one serializer per call so the helper does not rely on undocumented
|
||||
// cross-thread safety guarantees from YamlDotNet's serializer implementation.
|
||||
var yaml = CreateSerializer().Serialize(value);
|
||||
return yaml.EndsWith('\n')
|
||||
? yaml
|
||||
: $"{yaml}{Environment.NewLine}";
|
||||
: $"{yaml}\n";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建与运行时配置绑定共享的 YAML 序列化器。
|
||||
/// </summary>
|
||||
/// <returns>复用统一命名与默认值策略的序列化器。</returns>
|
||||
private static ISerializer CreateSerializer()
|
||||
{
|
||||
return new SerializerBuilder()
|
||||
.WithNamingConvention(CamelCaseNamingConvention.Instance)
|
||||
.DisableAliases()
|
||||
.ConfigureDefaultValuesHandling(DefaultValuesHandling.Preserve)
|
||||
.Build();
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,6 +5,10 @@ namespace GFramework.Game.Config;
|
||||
/// </summary>
|
||||
public static class YamlConfigTextValidator
|
||||
{
|
||||
// Cache parsed schemas by table/path plus last write time so save-path validation can
|
||||
// avoid repeated disk IO and JSON parsing while still observing schema edits.
|
||||
private static readonly ConcurrentDictionary<SchemaCacheKey, SchemaCacheEntry> SchemaCache = new();
|
||||
|
||||
/// <summary>
|
||||
/// 使用指定 schema 文件同步校验 YAML 文本。
|
||||
/// </summary>
|
||||
@ -21,7 +25,7 @@ public static class YamlConfigTextValidator
|
||||
string yamlPath,
|
||||
string yamlText)
|
||||
{
|
||||
var schema = YamlConfigSchemaValidator.Load(tableName, schemaPath);
|
||||
var schema = GetOrLoadSchema(tableName, schemaPath);
|
||||
YamlConfigSchemaValidator.Validate(tableName, schema, yamlPath, yamlText);
|
||||
}
|
||||
|
||||
@ -44,8 +48,134 @@ public static class YamlConfigTextValidator
|
||||
string yamlText,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var schema = await YamlConfigSchemaValidator.LoadAsync(tableName, schemaPath, cancellationToken)
|
||||
var schema = await GetOrLoadSchemaAsync(tableName, schemaPath, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
YamlConfigSchemaValidator.Validate(tableName, schema, yamlPath, yamlText);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取可复用的 schema 模型,必要时从磁盘重新加载。
|
||||
/// </summary>
|
||||
/// <param name="tableName">所属配置表名称。</param>
|
||||
/// <param name="schemaPath">Schema 文件绝对路径。</param>
|
||||
/// <returns>与当前 schema 文件内容匹配的已解析模型。</returns>
|
||||
/// <exception cref="ArgumentException">当 <paramref name="tableName" /> 或 <paramref name="schemaPath" /> 为空白时抛出。</exception>
|
||||
/// <exception cref="GFramework.Game.Abstractions.Config.ConfigLoadException">当 schema 文件不可用或内容非法时抛出。</exception>
|
||||
private static YamlConfigSchema GetOrLoadSchema(
|
||||
string tableName,
|
||||
string schemaPath)
|
||||
{
|
||||
var cacheKey = CreateCacheKey(tableName, schemaPath);
|
||||
if (TryGetCachedSchema(cacheKey, out var cachedSchema))
|
||||
{
|
||||
return cachedSchema;
|
||||
}
|
||||
|
||||
var schema = YamlConfigSchemaValidator.Load(tableName, schemaPath);
|
||||
CacheSchema(cacheKey, schema);
|
||||
return schema;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步获取可复用的 schema 模型,必要时从磁盘重新加载。
|
||||
/// </summary>
|
||||
/// <param name="tableName">所属配置表名称。</param>
|
||||
/// <param name="schemaPath">Schema 文件绝对路径。</param>
|
||||
/// <param name="cancellationToken">取消令牌。</param>
|
||||
/// <returns>与当前 schema 文件内容匹配的已解析模型。</returns>
|
||||
/// <exception cref="ArgumentException">当 <paramref name="tableName" /> 或 <paramref name="schemaPath" /> 为空白时抛出。</exception>
|
||||
/// <exception cref="GFramework.Game.Abstractions.Config.ConfigLoadException">当 schema 文件不可用或内容非法时抛出。</exception>
|
||||
private static async Task<YamlConfigSchema> GetOrLoadSchemaAsync(
|
||||
string tableName,
|
||||
string schemaPath,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var cacheKey = CreateCacheKey(tableName, schemaPath);
|
||||
if (TryGetCachedSchema(cacheKey, out var cachedSchema))
|
||||
{
|
||||
return cachedSchema;
|
||||
}
|
||||
|
||||
var schema = await YamlConfigSchemaValidator.LoadAsync(tableName, schemaPath, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
CacheSchema(cacheKey, schema);
|
||||
return schema;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建 schema 缓存键,并提前执行与公开入口一致的参数契约检查。
|
||||
/// </summary>
|
||||
/// <param name="tableName">所属配置表名称。</param>
|
||||
/// <param name="schemaPath">Schema 文件绝对路径。</param>
|
||||
/// <returns>用于缓存查找的稳定键。</returns>
|
||||
/// <exception cref="ArgumentException">当 <paramref name="tableName" /> 或 <paramref name="schemaPath" /> 为空白时抛出。</exception>
|
||||
private static SchemaCacheKey CreateCacheKey(
|
||||
string tableName,
|
||||
string schemaPath)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(tableName))
|
||||
{
|
||||
throw new ArgumentException("Table name cannot be null or whitespace.", nameof(tableName));
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(schemaPath))
|
||||
{
|
||||
throw new ArgumentException("Schema path cannot be null or whitespace.", nameof(schemaPath));
|
||||
}
|
||||
|
||||
return new SchemaCacheKey(tableName, schemaPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 尝试命中当前 schema 文件版本对应的缓存项。
|
||||
/// </summary>
|
||||
/// <param name="cacheKey">缓存键。</param>
|
||||
/// <param name="schema">命中的 schema;未命中时为 <see langword="null" />。</param>
|
||||
/// <returns>当缓存项仍与当前文件时间戳一致时返回 <see langword="true" />。</returns>
|
||||
private static bool TryGetCachedSchema(
|
||||
SchemaCacheKey cacheKey,
|
||||
out YamlConfigSchema schema)
|
||||
{
|
||||
var lastWriteTimeUtc = File.GetLastWriteTimeUtc(cacheKey.SchemaPath);
|
||||
if (SchemaCache.TryGetValue(cacheKey, out var cacheEntry) &&
|
||||
cacheEntry.LastWriteTimeUtc == lastWriteTimeUtc)
|
||||
{
|
||||
schema = cacheEntry.Schema;
|
||||
return true;
|
||||
}
|
||||
|
||||
schema = null!;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 使用最新的文件时间戳刷新 schema 缓存。
|
||||
/// </summary>
|
||||
/// <param name="cacheKey">缓存键。</param>
|
||||
/// <param name="schema">最新加载的 schema。</param>
|
||||
private static void CacheSchema(
|
||||
SchemaCacheKey cacheKey,
|
||||
YamlConfigSchema schema)
|
||||
{
|
||||
var lastWriteTimeUtc = File.GetLastWriteTimeUtc(cacheKey.SchemaPath);
|
||||
SchemaCache[cacheKey] = new SchemaCacheEntry(lastWriteTimeUtc, schema);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 表示一个 schema 缓存键。
|
||||
/// </summary>
|
||||
/// <param name="TableName">所属配置表名称。</param>
|
||||
/// <param name="SchemaPath">Schema 文件绝对路径。</param>
|
||||
private readonly record struct SchemaCacheKey(
|
||||
string TableName,
|
||||
string SchemaPath);
|
||||
|
||||
/// <summary>
|
||||
/// 表示一个带文件时间戳的 schema 缓存条目。
|
||||
/// </summary>
|
||||
/// <param name="LastWriteTimeUtc">加载时观察到的 schema 文件修改时间。</param>
|
||||
/// <param name="Schema">已解析的 schema 模型。</param>
|
||||
private readonly record struct SchemaCacheEntry(
|
||||
DateTime LastWriteTimeUtc,
|
||||
YamlConfigSchema Schema);
|
||||
}
|
||||
|
||||
@ -454,8 +454,14 @@ public class SchemaConfigGeneratorTests
|
||||
Does.Contain("public static void ValidateYaml(string configRootPath, string yamlPath, string yamlText)"));
|
||||
Assert.That(generatedSources["MonsterConfigBindings.g.cs"],
|
||||
Does.Contain("public static global::System.Threading.Tasks.Task ValidateYamlAsync("));
|
||||
Assert.That(generatedSources["MonsterConfigBindings.g.cs"],
|
||||
Does.Contain("GeneratedConfigCatalog.ResolveAbsolutePath(configRootPath, Metadata.ConfigRelativePath)"));
|
||||
Assert.That(generatedSources["MonsterConfigBindings.g.cs"],
|
||||
Does.Not.Contain("private static string ResolveAbsolutePath"));
|
||||
Assert.That(generatedSources["GeneratedConfigCatalog.g.cs"],
|
||||
Does.Contain("MonsterConfigBindings.Metadata.ConfigRelativePath"));
|
||||
Assert.That(generatedSources["GeneratedConfigCatalog.g.cs"],
|
||||
Does.Contain("internal static string ResolveAbsolutePath(string configRootPath, string relativePath)"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -66,6 +66,31 @@ public static class GeneratedConfigCatalog
|
||||
MonsterConfigBindings.Metadata.SchemaRelativePath),
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
/// Resolves one generated relative config path against the caller-supplied config root directory.
|
||||
/// </summary>
|
||||
/// <param name="configRootPath">Absolute or workspace-local config root directory.</param>
|
||||
/// <param name="relativePath">Generated relative config or schema path.</param>
|
||||
/// <returns>The combined absolute path.</returns>
|
||||
/// <exception cref="global::System.ArgumentException">When <paramref name="configRootPath"/> is null, empty, or whitespace.</exception>
|
||||
/// <exception cref="global::System.ArgumentNullException">When <paramref name="relativePath"/> is null.</exception>
|
||||
internal static string ResolveAbsolutePath(string configRootPath, string relativePath)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(configRootPath))
|
||||
{
|
||||
throw new global::System.ArgumentException("Config root path cannot be null or whitespace.", nameof(configRootPath));
|
||||
}
|
||||
|
||||
if (relativePath is null)
|
||||
{
|
||||
throw new global::System.ArgumentNullException(nameof(relativePath));
|
||||
}
|
||||
|
||||
var normalizedRelativePath = relativePath.Replace('/', global::System.IO.Path.DirectorySeparatorChar)
|
||||
.Replace('\\', global::System.IO.Path.DirectorySeparatorChar);
|
||||
return global::System.IO.Path.Combine(configRootPath, normalizedRelativePath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to resolve generated table metadata by runtime registration name.
|
||||
/// </summary>
|
||||
|
||||
@ -119,7 +119,7 @@ public static class MonsterConfigBindings
|
||||
/// <exception cref="global::System.ArgumentException">Thrown when <paramref name="configRootPath"/> is null, empty, or whitespace.</exception>
|
||||
public static string GetConfigDirectoryPath(string configRootPath)
|
||||
{
|
||||
return ResolveAbsolutePath(configRootPath, Metadata.ConfigRelativePath);
|
||||
return GeneratedConfigCatalog.ResolveAbsolutePath(configRootPath, Metadata.ConfigRelativePath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -130,7 +130,7 @@ public static class MonsterConfigBindings
|
||||
/// <exception cref="global::System.ArgumentException">Thrown when <paramref name="configRootPath"/> is null, empty, or whitespace.</exception>
|
||||
public static string GetSchemaPath(string configRootPath)
|
||||
{
|
||||
return ResolveAbsolutePath(configRootPath, Metadata.SchemaRelativePath);
|
||||
return GeneratedConfigCatalog.ResolveAbsolutePath(configRootPath, Metadata.SchemaRelativePath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -176,23 +176,6 @@ public static class MonsterConfigBindings
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
private static string ResolveAbsolutePath(string configRootPath, string relativePath)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(configRootPath))
|
||||
{
|
||||
throw new global::System.ArgumentException("Config root path cannot be null or whitespace.", nameof(configRootPath));
|
||||
}
|
||||
|
||||
if (relativePath is null)
|
||||
{
|
||||
throw new global::System.ArgumentNullException(nameof(relativePath));
|
||||
}
|
||||
|
||||
var normalizedRelativePath = relativePath.Replace('/', global::System.IO.Path.DirectorySeparatorChar)
|
||||
.Replace('\\', global::System.IO.Path.DirectorySeparatorChar);
|
||||
return global::System.IO.Path.Combine(configRootPath, normalizedRelativePath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Exposes generated metadata for schema properties that declare <c>x-gframework-ref-table</c>.
|
||||
/// </summary>
|
||||
|
||||
@ -1403,6 +1403,40 @@ public sealed class SchemaConfigGenerator : IIncrementalGenerator
|
||||
builder.AppendLine(" });");
|
||||
builder.AppendLine();
|
||||
builder.AppendLine(" /// <summary>");
|
||||
builder.AppendLine(
|
||||
" /// Resolves one generated relative config path against the caller-supplied config root directory.");
|
||||
builder.AppendLine(" /// </summary>");
|
||||
builder.AppendLine(
|
||||
" /// <param name=\"configRootPath\">Absolute or workspace-local config root directory.</param>");
|
||||
builder.AppendLine(" /// <param name=\"relativePath\">Generated relative config or schema path.</param>");
|
||||
builder.AppendLine(" /// <returns>The combined absolute path.</returns>");
|
||||
builder.AppendLine(
|
||||
" /// <exception cref=\"global::System.ArgumentException\">When <paramref name=\"configRootPath\"/> is null, empty, or whitespace.</exception>");
|
||||
builder.AppendLine(
|
||||
" /// <exception cref=\"global::System.ArgumentNullException\">When <paramref name=\"relativePath\"/> is null.</exception>");
|
||||
builder.AppendLine(
|
||||
" internal static string ResolveAbsolutePath(string configRootPath, string relativePath)");
|
||||
builder.AppendLine(" {");
|
||||
builder.AppendLine(" if (string.IsNullOrWhiteSpace(configRootPath))");
|
||||
builder.AppendLine(" {");
|
||||
builder.AppendLine(
|
||||
" throw new global::System.ArgumentException(\"Config root path cannot be null or whitespace.\", nameof(configRootPath));");
|
||||
builder.AppendLine(" }");
|
||||
builder.AppendLine();
|
||||
builder.AppendLine(" if (relativePath is null)");
|
||||
builder.AppendLine(" {");
|
||||
builder.AppendLine(" throw new global::System.ArgumentNullException(nameof(relativePath));");
|
||||
builder.AppendLine(" }");
|
||||
builder.AppendLine();
|
||||
builder.AppendLine(
|
||||
" var normalizedRelativePath = relativePath.Replace('/', global::System.IO.Path.DirectorySeparatorChar)");
|
||||
builder.AppendLine(
|
||||
" .Replace('\\\\', global::System.IO.Path.DirectorySeparatorChar);");
|
||||
builder.AppendLine(
|
||||
" return global::System.IO.Path.Combine(configRootPath, normalizedRelativePath);");
|
||||
builder.AppendLine(" }");
|
||||
builder.AppendLine();
|
||||
builder.AppendLine(" /// <summary>");
|
||||
builder.AppendLine(" /// Tries to resolve generated table metadata by runtime registration name.");
|
||||
builder.AppendLine(" /// </summary>");
|
||||
builder.AppendLine(" /// <param name=\"tableName\">Runtime registration name.</param>");
|
||||
@ -1709,7 +1743,8 @@ public sealed class SchemaConfigGenerator : IIncrementalGenerator
|
||||
" /// <exception cref=\"global::System.ArgumentException\">Thrown when <paramref name=\"configRootPath\"/> is null, empty, or whitespace.</exception>");
|
||||
builder.AppendLine(" public static string GetConfigDirectoryPath(string configRootPath)");
|
||||
builder.AppendLine(" {");
|
||||
builder.AppendLine(" return ResolveAbsolutePath(configRootPath, Metadata.ConfigRelativePath);");
|
||||
builder.AppendLine(
|
||||
" return GeneratedConfigCatalog.ResolveAbsolutePath(configRootPath, Metadata.ConfigRelativePath);");
|
||||
builder.AppendLine(" }");
|
||||
builder.AppendLine();
|
||||
builder.AppendLine(" /// <summary>");
|
||||
@ -1723,7 +1758,8 @@ public sealed class SchemaConfigGenerator : IIncrementalGenerator
|
||||
" /// <exception cref=\"global::System.ArgumentException\">Thrown when <paramref name=\"configRootPath\"/> is null, empty, or whitespace.</exception>");
|
||||
builder.AppendLine(" public static string GetSchemaPath(string configRootPath)");
|
||||
builder.AppendLine(" {");
|
||||
builder.AppendLine(" return ResolveAbsolutePath(configRootPath, Metadata.SchemaRelativePath);");
|
||||
builder.AppendLine(
|
||||
" return GeneratedConfigCatalog.ResolveAbsolutePath(configRootPath, Metadata.SchemaRelativePath);");
|
||||
builder.AppendLine(" }");
|
||||
builder.AppendLine();
|
||||
builder.AppendLine(" /// <summary>");
|
||||
@ -1782,27 +1818,6 @@ public sealed class SchemaConfigGenerator : IIncrementalGenerator
|
||||
builder.AppendLine(" yamlText,");
|
||||
builder.AppendLine(" cancellationToken);");
|
||||
builder.AppendLine(" }");
|
||||
builder.AppendLine();
|
||||
builder.AppendLine(" private static string ResolveAbsolutePath(string configRootPath, string relativePath)");
|
||||
builder.AppendLine(" {");
|
||||
builder.AppendLine(" if (string.IsNullOrWhiteSpace(configRootPath))");
|
||||
builder.AppendLine(" {");
|
||||
builder.AppendLine(
|
||||
" throw new global::System.ArgumentException(\"Config root path cannot be null or whitespace.\", nameof(configRootPath));");
|
||||
builder.AppendLine(" }");
|
||||
builder.AppendLine();
|
||||
builder.AppendLine(" if (relativePath is null)");
|
||||
builder.AppendLine(" {");
|
||||
builder.AppendLine(" throw new global::System.ArgumentNullException(nameof(relativePath));");
|
||||
builder.AppendLine(" }");
|
||||
builder.AppendLine();
|
||||
builder.AppendLine(
|
||||
" var normalizedRelativePath = relativePath.Replace('/', global::System.IO.Path.DirectorySeparatorChar)");
|
||||
builder.AppendLine(
|
||||
" .Replace('\\\\', global::System.IO.Path.DirectorySeparatorChar);");
|
||||
builder.AppendLine(
|
||||
" return global::System.IO.Path.Combine(configRootPath, normalizedRelativePath);");
|
||||
builder.AppendLine(" }");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user