Added sour generator for all kinds of structs
This commit is contained in:
parent
4b67318bdf
commit
6290a4f0e4
@ -0,0 +1,20 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<LangVersion>latest</LangVersion>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<WarningsAsErrors>CS8600;CS8602;CS8603</WarningsAsErrors>
|
||||||
|
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.9.2" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
86
CSV Metrics Logger Generator/CSVConverterGenerator.cs
Normal file
86
CSV Metrics Logger Generator/CSVConverterGenerator.cs
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
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
|
||||||
|
}
|
39
CSV Metrics Logger Generator/SyntaxReceiver.cs
Normal file
39
CSV Metrics Logger Generator/SyntaxReceiver.cs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
using Microsoft.CodeAnalysis;
|
||||||
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||||
|
|
||||||
|
namespace CSV_Metrics_Logger_Generator;
|
||||||
|
|
||||||
|
internal sealed class SyntaxReceiver : ISyntaxReceiver
|
||||||
|
{
|
||||||
|
public List<TypeDeclarationSyntax> DataStructures { get; } = [];
|
||||||
|
|
||||||
|
#region Implementation of ISyntaxReceiver
|
||||||
|
|
||||||
|
public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// The data structures we are looking for:
|
||||||
|
// - any kind of structs (record struct, readonly record struct, regular struct)
|
||||||
|
// - with the attribute [CSVRecord]
|
||||||
|
//
|
||||||
|
|
||||||
|
// Check if the syntax node is a struct declaration:
|
||||||
|
TypeDeclarationSyntax? structNode = syntaxNode switch
|
||||||
|
{
|
||||||
|
RecordDeclarationSyntax rds => rds,
|
||||||
|
StructDeclarationSyntax sds => sds,
|
||||||
|
|
||||||
|
_ => null
|
||||||
|
};
|
||||||
|
|
||||||
|
// No struct?
|
||||||
|
if (structNode is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Check if the struct has the attribute [CSVRecord]:
|
||||||
|
if (structNode.AttributeLists.Any(asl => asl.Attributes.Any(n => n.Name.ToString() == "CSVRecord")))
|
||||||
|
this.DataStructures.Add(structNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
@ -2,6 +2,8 @@
|
|||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSV Metrics Logger", "CSV Metrics Logger\CSV Metrics Logger.csproj", "{BFFEE7AC-0227-4FCA-BBE7-4F6E23CD5CD7}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSV Metrics Logger", "CSV Metrics Logger\CSV Metrics Logger.csproj", "{BFFEE7AC-0227-4FCA-BBE7-4F6E23CD5CD7}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSV Metrics Logger Generator", "CSV Metrics Logger Generator\CSV Metrics Logger Generator.csproj", "{559505B4-5322-4CFD-ABB9-D835C2A7EC09}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@ -12,5 +14,13 @@ Global
|
|||||||
{BFFEE7AC-0227-4FCA-BBE7-4F6E23CD5CD7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{BFFEE7AC-0227-4FCA-BBE7-4F6E23CD5CD7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{BFFEE7AC-0227-4FCA-BBE7-4F6E23CD5CD7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{BFFEE7AC-0227-4FCA-BBE7-4F6E23CD5CD7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{BFFEE7AC-0227-4FCA-BBE7-4F6E23CD5CD7}.Release|Any CPU.Build.0 = Release|Any CPU
|
{BFFEE7AC-0227-4FCA-BBE7-4F6E23CD5CD7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{559505B4-5322-4CFD-ABB9-D835C2A7EC09}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{559505B4-5322-4CFD-ABB9-D835C2A7EC09}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{559505B4-5322-4CFD-ABB9-D835C2A7EC09}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{559505B4-5322-4CFD-ABB9-D835C2A7EC09}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{871708D2-633C-4D78-86EF-A1B72043B652}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{871708D2-633C-4D78-86EF-A1B72043B652}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{871708D2-633C-4D78-86EF-A1B72043B652}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{871708D2-633C-4D78-86EF-A1B72043B652}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
@ -9,4 +9,8 @@
|
|||||||
<WarningsAsErrors>CS8600;CS8602;CS8603</WarningsAsErrors>
|
<WarningsAsErrors>CS8600;CS8602;CS8603</WarningsAsErrors>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\CSV Metrics Logger Generator\CSV Metrics Logger Generator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
4
CSV Metrics Logger/CSVRecordAttribute.cs
Normal file
4
CSV Metrics Logger/CSVRecordAttribute.cs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
namespace CSV_Metrics_Logger;
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Struct)]
|
||||||
|
public sealed class CSVRecordAttribute : Attribute;
|
10
CSV Metrics Logger/IConvertToCSV.cs
Normal file
10
CSV Metrics Logger/IConvertToCSV.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
namespace CSV_Metrics_Logger;
|
||||||
|
|
||||||
|
public interface IConvertToCSV
|
||||||
|
{
|
||||||
|
public uint GetCSVColumnCount();
|
||||||
|
|
||||||
|
public IList<string> GetCSVHeaders();
|
||||||
|
|
||||||
|
public IList<string> ConvertToCSVDataLine();
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user