Replace all raw string comparisons with StringKey, source generator that creates cache keys for all names for Gen7 plugin
All checks were successful
Build / Build (push) Successful in 2m21s

This commit is contained in:
2026-08-27 18:30:57 +02:00
parent 3a58f55bbf
commit 942be8eaeb
160 changed files with 1035 additions and 491 deletions

View File

@@ -0,0 +1,73 @@
using System.Text;
using PkmnLib.Plugin.Gen7.SourceGen.Parsing;
namespace PkmnLib.Plugin.Gen7.SourceGen.Emit;
/// <summary>
/// Emits a constants class of <c>public static readonly StringKey</c> fields for a
/// <see cref="ClassSpec"/>.
/// </summary>
public static class ConstantClassEmitter
{
public static string Emit(ClassSpec spec, List<ExtractionDiagnostic> diagnostics)
{
var sb = new StringBuilder();
sb.AppendLine($"// <auto-generated from Data/{spec.SourceFile} by PkmnLib.Plugin.Gen7.SourceGen />");
sb.AppendLine("#nullable enable");
sb.AppendLine("using PkmnLib.Static.Utils;");
sb.AppendLine();
sb.AppendLine("namespace PkmnLib.Plugin.Gen7.Common;");
sb.AppendLine();
sb.AppendLine($"public static class {spec.ClassName}");
sb.AppendLine("{");
var seen = new Dictionary<string, string>(StringComparer.Ordinal);
foreach (var name in spec.Names)
{
var identifier = Sanitize(name);
if (identifier.Length == 0)
{
diagnostics.Add(new ExtractionDiagnostic("PKMN7G002",
$"Name '{name}' in {spec.ClassName} does not produce a usable identifier and was skipped."));
continue;
}
if (seen.TryGetValue(identifier, out var existing))
{
diagnostics.Add(new ExtractionDiagnostic("PKMN7G001",
$"Names '{existing}' and '{name}' in {spec.ClassName} both map to identifier '{identifier}'; '{name}' was skipped."));
continue;
}
seen.Add(identifier, name);
sb.AppendLine($" public static readonly StringKey {identifier} = \"{name}\";");
}
sb.AppendLine("}");
return sb.ToString();
}
/// <summary>
/// Converts a raw data name to a PascalCase identifier: segments split on <c>_</c>/<c>-</c>
/// runs, non-alphanumeric characters stripped, and a leading <c>_</c> added when the result
/// would start with a digit.
/// </summary>
public static string Sanitize(string raw)
{
var sb = new StringBuilder(raw.Length);
var newSegment = true;
foreach (var c in raw)
{
if (c is '_' or '-')
{
newSegment = true;
continue;
}
if (!char.IsLetterOrDigit(c))
continue;
sb.Append(newSegment ? char.ToUpperInvariant(c) : c);
newSegment = false;
}
if (sb.Length == 0)
return string.Empty;
if (char.IsDigit(sb[0]))
sb.Insert(0, '_');
return sb.ToString();
}
}