Questionable/QuestPathGenerator/Utils.cs

135 lines
5.0 KiB
C#
Raw Normal View History

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;
}
}