2024-08-02 16:30:21 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Globalization;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text.Json.Nodes;
|
|
|
|
|
using Json.Schema;
|
|
|
|
|
using Microsoft.CodeAnalysis;
|
|
|
|
|
using Microsoft.CodeAnalysis.CSharp;
|
|
|
|
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
|
|
|
|
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
|
|
|
|
|
|
|
|
|
|
namespace Questionable.QuestPathGenerator;
|
|
|
|
|
|
|
|
|
|
public static class Utils
|
|
|
|
|
{
|
2024-08-16 20:52:43 +00:00
|
|
|
|
public static List<AdditionalText> RegisterSchemas(GeneratorExecutionContext context)
|
2024-08-02 16:30:21 +00:00
|
|
|
|
{
|
|
|
|
|
var commonSchemaFile = context.AdditionalFiles.Single(x => Path.GetFileName(x.Path) == "common-schema.json");
|
2024-08-16 20:52:43 +00:00
|
|
|
|
var gatheringSchemaFile =
|
|
|
|
|
context.AdditionalFiles.SingleOrDefault(x => Path.GetFileName(x.Path) == "gatheringlocation-v1.json");
|
|
|
|
|
var questSchemaFile = context.AdditionalFiles.SingleOrDefault(x => Path.GetFileName(x.Path) == "quest-v1.json");
|
2024-08-02 16:30:21 +00:00
|
|
|
|
|
|
|
|
|
SchemaRegistry.Global.Register(
|
|
|
|
|
new Uri("https://git.carvel.li/liza/Questionable/raw/branch/master/Questionable.Model/common-schema.json"),
|
|
|
|
|
JsonSchema.FromText(commonSchemaFile.GetText()!.ToString()));
|
|
|
|
|
|
2024-08-16 20:52:43 +00:00
|
|
|
|
if (gatheringSchemaFile != null)
|
|
|
|
|
{
|
|
|
|
|
SchemaRegistry.Global.Register(
|
|
|
|
|
new Uri(
|
|
|
|
|
"https://git.carvel.li/liza/Questionable/raw/branch/master/GatheringPaths/gatheringlocation-v1.json"),
|
|
|
|
|
JsonSchema.FromText(gatheringSchemaFile.GetText()!.ToString()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (questSchemaFile != null)
|
|
|
|
|
{
|
|
|
|
|
SchemaRegistry.Global.Register(
|
|
|
|
|
new Uri("https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json"),
|
|
|
|
|
JsonSchema.FromText(questSchemaFile.GetText()!.ToString()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
List<AdditionalText?> jsonSchemaFiles = [commonSchemaFile, gatheringSchemaFile, questSchemaFile];
|
|
|
|
|
return jsonSchemaFiles.Where(x => x != null).Cast<AdditionalText>().ToList();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static IEnumerable<(T, JsonNode)> GetAdditionalFiles<T>(GeneratorExecutionContext context,
|
|
|
|
|
List<AdditionalText> jsonSchemaFiles, JsonSchema jsonSchema, DiagnosticDescriptor invalidJson,
|
|
|
|
|
Func<string, T> idParser)
|
|
|
|
|
{
|
2024-08-02 16:30:21 +00:00
|
|
|
|
foreach (var additionalFile in context.AdditionalFiles)
|
|
|
|
|
{
|
|
|
|
|
if (additionalFile == null || jsonSchemaFiles.Contains(additionalFile))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (Path.GetExtension(additionalFile.Path) != ".json")
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
string name = Path.GetFileName(additionalFile.Path);
|
|
|
|
|
if (!name.Contains("_"))
|
|
|
|
|
continue;
|
|
|
|
|
|
2024-08-05 05:51:34 +00:00
|
|
|
|
T id = idParser(name.Substring(0, name.IndexOf('_')));
|
2024-08-02 16:30:21 +00:00
|
|
|
|
|
|
|
|
|
var text = additionalFile.GetText();
|
|
|
|
|
if (text == null)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
var node = JsonNode.Parse(text.ToString());
|
|
|
|
|
if (node == null)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
string? schemaLocation = node["$schema"]?.GetValue<string?>();
|
|
|
|
|
if (schemaLocation == null || new Uri(schemaLocation) != jsonSchema.GetId())
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
var evaluationResult = jsonSchema.Evaluate(node, new EvaluationOptions
|
|
|
|
|
{
|
|
|
|
|
Culture = CultureInfo.InvariantCulture,
|
|
|
|
|
OutputFormat = OutputFormat.List,
|
|
|
|
|
});
|
2024-08-02 18:04:45 +00:00
|
|
|
|
if (evaluationResult.HasErrors)
|
2024-08-02 16:30:21 +00:00
|
|
|
|
{
|
|
|
|
|
var error = Diagnostic.Create(invalidJson,
|
|
|
|
|
null,
|
|
|
|
|
Path.GetFileName(additionalFile.Path));
|
|
|
|
|
context.ReportDiagnostic(error);
|
2024-08-02 18:04:45 +00:00
|
|
|
|
continue;
|
2024-08-02 16:30:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
yield return (id, node);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-05 05:51:34 +00:00
|
|
|
|
public static List<MethodDeclarationSyntax> CreateMethods<TId, TQuest>(string prefix,
|
|
|
|
|
List<IGrouping<string, (TId, TQuest)>> partitions,
|
|
|
|
|
Func<List<(TId, TQuest)>, StatementSyntax[]> toInitializers)
|
2024-08-02 16:30:21 +00:00
|
|
|
|
{
|
|
|
|
|
List<MethodDeclarationSyntax> methods =
|
|
|
|
|
[
|
|
|
|
|
MethodDeclaration(
|
|
|
|
|
PredefinedType(
|
|
|
|
|
Token(SyntaxKind.VoidKeyword)),
|
|
|
|
|
Identifier(prefix))
|
|
|
|
|
.WithModifiers(
|
|
|
|
|
TokenList(
|
|
|
|
|
Token(SyntaxKind.PrivateKeyword),
|
|
|
|
|
Token(SyntaxKind.StaticKeyword)))
|
|
|
|
|
.WithBody(
|
|
|
|
|
Block(
|
|
|
|
|
partitions
|
|
|
|
|
.Select(x =>
|
|
|
|
|
ExpressionStatement(
|
|
|
|
|
InvocationExpression(
|
|
|
|
|
IdentifierName(x.Key))))))
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
foreach (var partition in partitions)
|
|
|
|
|
{
|
|
|
|
|
methods.Add(MethodDeclaration(
|
|
|
|
|
PredefinedType(
|
|
|
|
|
Token(SyntaxKind.VoidKeyword)),
|
|
|
|
|
Identifier(partition.Key))
|
|
|
|
|
.WithModifiers(
|
|
|
|
|
TokenList(
|
|
|
|
|
Token(SyntaxKind.PrivateKeyword),
|
|
|
|
|
Token(SyntaxKind.StaticKeyword)))
|
|
|
|
|
.WithBody(
|
|
|
|
|
Block(toInitializers(partition.ToList()))));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return methods;
|
|
|
|
|
}
|
|
|
|
|
}
|