mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-11 01:38:27 -04:00
- Added NadekoBot.Generators projects which will contain source generators
- Implemented initial version of the response strings source generator - Creates a class with property names equivalent to key names in responses.en-US.json - Each Property has struct type (with generic type parameters matching the number of string format placeholders) for type safe GetText implementation - Struct types are readonly refs as they should be ephermal, and only used to pass string keys to GetText
This commit is contained in:
159
src/NadekoBot.Generators/LocalizedStringsGenerator.cs
Normal file
159
src/NadekoBot.Generators/LocalizedStringsGenerator.cs
Normal file
@@ -0,0 +1,159 @@
|
||||
using System;
|
||||
using System.CodeDom.Compiler;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.Text;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace NadekoBot.Generators
|
||||
{
|
||||
internal class FieldData
|
||||
{
|
||||
public string Type { get; set; }
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
[Generator]
|
||||
public class LocalizedStringsGenerator : ISourceGenerator
|
||||
{
|
||||
private const string LocStrSource = @"namespace NadekoBot
|
||||
{
|
||||
public readonly ref struct LocStr
|
||||
{
|
||||
public readonly string Key;
|
||||
|
||||
public LocStr(string key)
|
||||
{
|
||||
Key = key;
|
||||
}
|
||||
|
||||
public static implicit operator LocStr(string data)
|
||||
=> new LocStr(data);
|
||||
}
|
||||
|
||||
public readonly ref struct LocStr<T1>
|
||||
{
|
||||
public readonly string Key;
|
||||
|
||||
public LocStr(string key)
|
||||
{
|
||||
Key = key;
|
||||
}
|
||||
|
||||
public static implicit operator LocStr<T1>(string data)
|
||||
=> new LocStr<T1>(data);
|
||||
}
|
||||
|
||||
public readonly ref struct LocStr<T1, T2>
|
||||
{
|
||||
public readonly string Key;
|
||||
|
||||
public LocStr(string key)
|
||||
{
|
||||
Key = key;
|
||||
}
|
||||
|
||||
public static implicit operator LocStr<T1, T2>(string data)
|
||||
=> new LocStr<T1, T2>(data);
|
||||
}
|
||||
|
||||
public readonly ref struct LocStr<T1, T2, T3>
|
||||
{
|
||||
public readonly string Key;
|
||||
|
||||
public LocStr(string key)
|
||||
{
|
||||
Key = key;
|
||||
}
|
||||
|
||||
public static implicit operator LocStr<T1, T2, T3>(string data)
|
||||
=> new LocStr<T1, T2, T3>(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 NadekoBot");
|
||||
sw.WriteLine("{");
|
||||
sw.Indent++;
|
||||
|
||||
sw.WriteLine("public static class Strs");
|
||||
sw.WriteLine("{");
|
||||
sw.Indent++;
|
||||
|
||||
foreach (var field in fields)
|
||||
{
|
||||
sw.WriteLine($"public static {field.Type} {field.Name} => \"{field.Name}\";");
|
||||
}
|
||||
|
||||
sw.Indent--;
|
||||
sw.WriteLine("}");
|
||||
sw.Indent--;
|
||||
sw.WriteLine("}");
|
||||
|
||||
|
||||
sw.Flush();
|
||||
context.AddSource("Strs.cs", stringWriter.ToString());
|
||||
}
|
||||
|
||||
context.AddSource("LocStr.cs", LocStrSource);
|
||||
}
|
||||
|
||||
private List<FieldData> GetFields(string dataText)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(dataText))
|
||||
throw new ArgumentNullException(nameof(dataText));
|
||||
|
||||
var data = JsonConvert.DeserializeObject<Dictionary<string, string>>(dataText);
|
||||
|
||||
var list = new List<FieldData>();
|
||||
foreach (var entry in data)
|
||||
{
|
||||
list.Add(new FieldData()
|
||||
{
|
||||
Type = GetFieldType(entry.Value),
|
||||
Name = entry.Key,
|
||||
});
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private string GetFieldType(string value)
|
||||
{
|
||||
var matches = Regex.Matches(value, @"{(?<num>\d)}");
|
||||
int max = 0;
|
||||
foreach (Match match in matches)
|
||||
{
|
||||
max = Math.Max(max, int.Parse(match.Groups["num"].Value));
|
||||
}
|
||||
|
||||
if (max == 0)
|
||||
return "LocStr";
|
||||
if (max == 1)
|
||||
return "LocStr<string>";
|
||||
if (max == 2)
|
||||
return "LocStr<string, string>";
|
||||
if (max == 3)
|
||||
return "LocStr<string, string, string>";
|
||||
|
||||
return "!Error";
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user