mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-11-02 05:47:21 +00:00
Generated the JSON contracts of backups and the provenance store at compile time
This commit is contained in:
5 files changed
+58
-4
No files matched your search
@@ -51,12 +51,13 @@ public static class DataBackupFormat
|
||||
/// How the manifest and the plan of a restore are written: readable for anybody who opens them,
|
||||
/// and for the runtime, which applies the plan.
|
||||
/// </summary>
|
||||
public static readonly JsonSerializerOptions JSON_OPTIONS = new()
|
||||
public static readonly JsonSerializerOptions JSON_OPTIONS = new JsonSerializerOptions
|
||||
{
|
||||
WriteIndented = true,
|
||||
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
|
||||
Converters = { new JsonStringEnumConverter() },
|
||||
};
|
||||
TypeInfoResolver = DataBackupJsonContext.Default,
|
||||
}.AsReadOnly();
|
||||
|
||||
/// <summary>
|
||||
/// File types which are compressed already. Compressing them once more costs time and makes the
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace AIStudio.Tools.DataBackup;
|
||||
|
||||
/// <summary>
|
||||
/// The contracts with which System.Text.Json reads and writes the manifest of a backup and the plan and report of
|
||||
/// a restore, built at compile time.
|
||||
/// </summary>
|
||||
[JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Metadata)]
|
||||
[JsonSerializable(typeof(DataBackupManifest))]
|
||||
[JsonSerializable(typeof(DataRestorePlan))]
|
||||
[JsonSerializable(typeof(DataRestoreReport))]
|
||||
internal sealed partial class DataBackupJsonContext : JsonSerializerContext;
|
||||
@@ -0,0 +1,11 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace AIStudio.Tools.Databases.ProvenanceStore;
|
||||
|
||||
/// <summary>
|
||||
/// The contracts with which System.Text.Json reads and writes the content around a passage, built at compile time.
|
||||
/// </summary>
|
||||
[JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Metadata)]
|
||||
[JsonSerializable(typeof(IReadOnlyList<string>))]
|
||||
[JsonSerializable(typeof(List<string>))]
|
||||
internal sealed partial class ProvenanceJsonContext : JsonSerializerContext;
|
||||
+6
-2
@@ -39,7 +39,11 @@ public sealed class SqliteProvenanceStoreClientImplementation(string name, strin
|
||||
/// Writes the content around a passage the way it reads: the default encoder would turn every
|
||||
/// character outside ASCII into an escape, cf. ToolExecutionResult.MODEL_CONTENT_OPTIONS.
|
||||
/// </summary>
|
||||
internal static readonly JsonSerializerOptions JSON_OPTIONS = new() { Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping };
|
||||
internal static readonly JsonSerializerOptions JSON_OPTIONS = new JsonSerializerOptions
|
||||
{
|
||||
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
|
||||
TypeInfoResolver = ProvenanceJsonContext.Default,
|
||||
}.AsReadOnly();
|
||||
|
||||
private readonly string databasePath = databasePath;
|
||||
private readonly string lastCleanupPath = Path.Join(basePath, LAST_CLEANUP_FILENAME);
|
||||
@@ -351,7 +355,7 @@ public sealed class SqliteProvenanceStoreClientImplementation(string name, strin
|
||||
|
||||
try
|
||||
{
|
||||
return JsonSerializer.Deserialize<List<string>>(row.SurroundingContent) ?? [];
|
||||
return JsonSerializer.Deserialize<List<string>>(row.SurroundingContent, JSON_OPTIONS) ?? [];
|
||||
}
|
||||
catch (JsonException exception)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace AIStudio.Tests.Serialization;
|
||||
|
||||
/// <summary>
|
||||
/// Checks that every contract AI Studio uses for its JSON comes from source generation, never from reflection.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// A type which no context of the options knows makes System.Text.Json throw, unless the options fall back to
|
||||
/// reflection. Such a fallback hides the missing type until a trimmed build removes what reflection needs, and
|
||||
/// only a published build shows it then.
|
||||
/// </remarks>
|
||||
[TestFixture]
|
||||
public sealed class JsonCoverageTests
|
||||
{
|
||||
[TestCaseSource(typeof(JsonTestRoots), nameof(JsonTestRoots.Stored))]
|
||||
public void EveryContractComesFromSourceGeneration(JsonTestRoot root)
|
||||
{
|
||||
var typesWithoutGeneratedContract = JsonTypeGraph.Collect(root.Type, root.Options)
|
||||
.Where(type => root.Options.GetTypeInfo(type).OriginatingResolver is not JsonSerializerContext)
|
||||
.Select(JsonContractDescription.TypeName);
|
||||
|
||||
Assert.That(typesWithoutGeneratedContract, Is.Empty);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user