This repository has been archived on 2024-12-22. You can view files and clone it, but cannot push or open issues or pull requests.
elliebot/src/EllieBot.Generators/LocalizedStringsGenerator.cs

144 lines
4.1 KiB
C#
Raw Normal View History

2024-03-23 01:54:27 +00:00
#nullable enable
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
namespace EllieBot.Generators
{
internal readonly struct TranslationPair
{
public string Name { get; }
public string Value { get; }
public TranslationPair(string name, string value)
{
Name = name;
Value = value;
}
}
[Generator]
public class LocalizedStringsGenerator : ISourceGenerator
{
private const string LOC_STR_SOURCE = @"namespace EllieBot
{
public readonly struct LocStr
{
public readonly string Key;
public readonly object[] Params;
public LocStr(string key, params object[] data)
{
Key = key;
Params = data;
}
}
}";
public void Initialize(GeneratorInitializationContext context)
{
}
public void Execute(GeneratorExecutionContext context)
{
var file = context.AdditionalFiles.First(x => x.Path.EndsWith("responses.en-US.json"));
var fields = GetFields(file.GetText()?.ToString());
using (var stringWriter = new StringWriter())
using (var sw = new IndentedTextWriter(stringWriter))
{
sw.WriteLine("namespace EllieBot;");
sw.WriteLine();
sw.WriteLine("public static class strs");
sw.WriteLine("{");
sw.Indent++;
var typedParamStrings = new List<string>(10);
foreach (var field in fields)
{
var matches = Regex.Matches(field.Value, @"{(?<num>\d)[}:]");
var max = 0;
foreach (Match match in matches)
{
max = Math.Max(max, int.Parse(match.Groups["num"].Value) + 1);
}
typedParamStrings.Clear();
var typeParams = new string[max];
var passedParamString = string.Empty;
for (var i = 0; i < max; i++)
{
typedParamStrings.Add($"in T{i} p{i}");
passedParamString += $", p{i}";
typeParams[i] = $"T{i}";
}
var sig = string.Empty;
var typeParamStr = string.Empty;
if (max > 0)
{
sig = $"({string.Join(", ", typedParamStrings)})";
typeParamStr = $"<{string.Join(", ", typeParams)}>";
}
sw.WriteLine("public static LocStr {0}{1}{2} => new LocStr(\"{3}\"{4});",
field.Name,
typeParamStr,
sig,
field.Name,
passedParamString);
}
sw.Indent--;
sw.WriteLine("}");
sw.Flush();
context.AddSource("strs.g.cs", stringWriter.ToString());
}
context.AddSource("LocStr.g.cs", LOC_STR_SOURCE);
}
private List<TranslationPair> GetFields(string? dataText)
{
if (string.IsNullOrWhiteSpace(dataText))
return new();
Dictionary<string, string> data;
try
{
var output = JsonConvert.DeserializeObject<Dictionary<string, string>>(dataText!);
if (output is null)
return new();
data = output;
}
catch
{
Debug.WriteLine("Failed parsing responses file.");
return new();
}
var list = new List<TranslationPair>();
foreach (var entry in data)
{
list.Add(new(
entry.Key,
entry.Value
));
}
return list;
}
}
}