using Microsoft.CodeAnalysis; using ResourceString.Net.Logic.Factories; using ResourceString.Net.Logic.Parsers.Resx; namespace ResourceString.Net; [Generator] public class Generator : IIncrementalGenerator { public void Initialize(IncrementalGeneratorInitializationContext initContext) { // find all additional files that end with .txt var resxFiles = initContext.AdditionalTextsProvider.Where(static file => file.Path.EndsWith(".resx")); var assemblies = initContext.CompilationProvider.Select(static (c, _) => c.Assembly); // read their contents and save their name var config = resxFiles.Combine(assemblies).Select( (t, cancellationToken) => ( name: System.IO.Path.GetFileNameWithoutExtension(t.Left.Path), content: t.Left.GetText(cancellationToken)!.ToString(), assembly: t.Right, path: t.Left.Path ) ); // generate a class that contains their values as const strings initContext.RegisterSourceOutput(config, (spc, t) => { Parser.TryParse(t.content).IfSome(v => { var relativeNamespace = System.IO.Path.GetDirectoryName(t.path).Substring( System.IO.Path.GetDirectoryName(t.assembly.Locations[0].GetLineSpan().Path).Length ).Trim(System.IO.Path.DirectorySeparatorChar).Replace(System.IO.Path.DirectorySeparatorChar, '.'); var ns = string.IsNullOrWhiteSpace(relativeNamespace) ? t.assembly.Name : $"{t.assembly.Name}.{relativeNamespace}"; var resourceFileName = t.name; var className = CodeSnippetFactory.TransformToClassName(t.name); var snippet = CodeSnippetFactory.CreateResourceClassCodeSnippet( CodeSnippetFactory.TransformToNamespace(ns), className, CodeSnippetFactory.CreateResourceMangerMemberCodeSnippet( $"{ns}.{resourceFileName}", className ), v.Resources ); spc.AddSource($"{ns}.{className}", snippet.Value); }); }); } }