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