using Microsoft.CodeAnalysis;
using PkmnLib.Plugin.Gen7.SourceGen.Emit;
using PkmnLib.Plugin.Gen7.SourceGen.Parsing;
namespace PkmnLib.Plugin.Gen7.SourceGen;
///
/// Generates public static readonly StringKey constant classes (move names, type names,
/// move flags, etc.) from the Gen 7 data files, which are exposed to the generator as
/// AdditionalFiles.
///
[Generator]
public sealed class DataConstantsGenerator : IIncrementalGenerator
{
private static readonly DiagnosticDescriptor ParseFailure = new("PKMN7G000", "Data file parse failure", "{0}",
"PkmnLib.SourceGen", DiagnosticSeverity.Error, true);
private static readonly DiagnosticDescriptor DuplicateIdentifier = new("PKMN7G001", "Duplicate constant identifier",
"{0}", "PkmnLib.SourceGen", DiagnosticSeverity.Error, true);
private static readonly DiagnosticDescriptor UnusableName = new("PKMN7G002", "Unusable constant name", "{0}",
"PkmnLib.SourceGen", DiagnosticSeverity.Error, true);
public void Initialize(IncrementalGeneratorInitializationContext context)
{
var results = context.AdditionalTextsProvider
.Where(static text => DataExtractor.IsKnownFile(Path.GetFileName(text.Path))).Select(static (text, ct) =>
DataExtractor.Extract(Path.GetFileName(text.Path), text.GetText(ct)?.ToString()));
context.RegisterSourceOutput(results, static (context, result) =>
{
foreach (var diagnostic in result.Diagnostics)
{
Report(context, diagnostic);
}
foreach (var spec in result.Classes)
{
var diagnostics = new List();
var source = ConstantClassEmitter.Emit(spec, diagnostics);
foreach (var diagnostic in diagnostics)
{
Report(context, diagnostic);
}
context.AddSource($"{spec.ClassName}.g.cs", source);
}
});
}
private static void Report(SourceProductionContext context, ExtractionDiagnostic diagnostic)
{
var descriptor = diagnostic.Id switch
{
"PKMN7G001" => DuplicateIdentifier,
"PKMN7G002" => UnusableName,
_ => ParseFailure,
};
context.ReportDiagnostic(Diagnostic.Create(descriptor, Location.None, diagnostic.Message));
}
}