CSVMetricsLogger/CSV Metrics Logger Generator/CSVConverterGenerator.cs

86 lines
3.1 KiB
C#

using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
namespace CSV_Metrics_Logger_Generator;
[Generator]
public class CSVConverterGenerator : ISourceGenerator
{
private const string ARRAY_DELIMITER = ", ";
#region Implementation of ISourceGenerator
public void Initialize(GeneratorInitializationContext context)
{
context.RegisterForSyntaxNotifications(() => new SyntaxReceiver());
}
public void Execute(GeneratorExecutionContext context)
{
if (context.SyntaxReceiver is not SyntaxReceiver receiver)
return;
foreach (var dataStructure in receiver.DataStructures)
this.ProcessStructure(context, dataStructure);
}
private void ProcessStructure(GeneratorExecutionContext context, TypeDeclarationSyntax dataStructure)
{
var accessModifiers = string.Join(' ', dataStructure.Modifiers.Select(n => n.Text));
var declarationType = dataStructure switch
{
RecordDeclarationSyntax => "record struct",
StructDeclarationSyntax => "struct",
_ => string.Empty
};
var namespaceName = this.GetNamespaceFrom(dataStructure);
var parameterProperties = dataStructure.ParameterList?.Parameters.Select(n => n.Identifier.ValueText).ToList() ?? [];
var bodyProperties = dataStructure.Members.OfType<PropertyDeclarationSyntax>().Select(n => n.Identifier.ValueText).ToList();
var allProperties = new List<string>(parameterProperties);
allProperties.AddRange(bodyProperties);
var numberProperties = allProperties.Count;
var header = string.Join(ARRAY_DELIMITER, allProperties.Select(n => $"\"{n}\""));
var allFieldsString = string.Join(ARRAY_DELIMITER, allProperties.Select(n => $"this.{n}.ToString(CultureInfo.InvariantCulture)"));
var sourceCode = SourceText.From(
$$"""
using System.Globalization;
using CSV_Metrics_Logger;
namespace {{namespaceName}};
{{accessModifiers}} {{declarationType}} {{dataStructure.Identifier}} : IConvertToCSV
{
public uint GetCSVColumnCount()
{
return (uint){{numberProperties}};
}
public IList<string> GetCSVHeaders()
{
return [ {{header}} ];
}
public IList<string> ConvertToCSVDataLine()
{
return [ {{allFieldsString}} ];
}
}
""", Encoding.UTF8);
context.AddSource($"{dataStructure.Identifier}.Generated.cs", sourceCode);
}
private string GetNamespaceFrom(SyntaxNode? node) => node switch
{
BaseNamespaceDeclarationSyntax namespaceDeclarationSyntax => namespaceDeclarationSyntax.Name.ToString(),
null => string.Empty,
_ => this.GetNamespaceFrom(node.Parent)
};
#endregion
}