mirror of
https://git.lewd.wtf/PGR/ascnet
synced 2025-12-12 22:24:35 +01:00
table reader v1
This commit is contained in:
28
AscNet.Table/AscNet.Table.csproj
Normal file
28
AscNet.Table/AscNet.Table.csproj
Normal file
@@ -0,0 +1,28 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<EnforceExtendedAnalyzerRules>false</EnforceExtendedAnalyzerRules>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
|
||||
<CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath>
|
||||
<IsRoslynComponent>true</IsRoslynComponent>
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.1.0" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.3" PrivateAssets="all" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" GeneratePathProperty="true" PrivateAssets="all" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- Package the generator in the analyzer directory of the nuget package -->
|
||||
<None Include="$(OutputPath)\$(AssemblyName).dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" />
|
||||
|
||||
<!-- Package the Newtonsoft.Json dependency alongside the generator assembly -->
|
||||
<None Include="$(PkgNewtonsoft_Json)\lib\netstandard2.0\*.dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
8
AscNet.Table/Properties/launchSettings.json
Normal file
8
AscNet.Table/Properties/launchSettings.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"profiles": {
|
||||
"DebugRoslyn": {
|
||||
"commandName": "DebugRoslynComponent",
|
||||
"targetProject": "..\\AscNet.Common\\AscNet.Common.csproj"
|
||||
}
|
||||
}
|
||||
}
|
||||
146
AscNet.Table/TableGenerator.cs
Normal file
146
AscNet.Table/TableGenerator.cs
Normal file
@@ -0,0 +1,146 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Microsoft.CodeAnalysis;
|
||||
|
||||
namespace AscNet.Table
|
||||
{
|
||||
[Generator]
|
||||
public class TableGenerator : ISourceGenerator
|
||||
{
|
||||
public void Execute(GeneratorExecutionContext context)
|
||||
{
|
||||
List<object> fails = new();
|
||||
foreach (var table in context.AdditionalFiles.Where(x => x.Path.EndsWith(".tab.bytes")))
|
||||
{
|
||||
try
|
||||
{
|
||||
string ns = string.Join("", Path.GetDirectoryName(table.Path)?.Split(new string[] { "table" }, StringSplitOptions.None).Skip(1)!)
|
||||
.Replace('\\', '/').Replace('/', '.');
|
||||
|
||||
byte[] fileBytes = File.ReadAllBytes(table.Path);
|
||||
string fileTsv = Encoding.UTF8.GetString(fileBytes.Skip(128).ToArray());
|
||||
|
||||
IEnumerable<string> tsvLines = fileTsv.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
string[] nameList = tsvLines.First().Split('\t');
|
||||
List<string[]> resolvedTypes = new();
|
||||
|
||||
foreach (var items in tsvLines.Skip(1).Select(x => x.Split('\t')))
|
||||
{
|
||||
List<string> types = new();
|
||||
foreach (var item in items)
|
||||
{
|
||||
if (string.IsNullOrEmpty(item))
|
||||
{
|
||||
types.Add("global::System.String");
|
||||
continue;
|
||||
}
|
||||
else if (int.TryParse(item, out var res))
|
||||
{
|
||||
types.Add("global::System.Int32");
|
||||
continue;
|
||||
}
|
||||
types.Add("global::System.String");
|
||||
}
|
||||
resolvedTypes.Add(types.ToArray());
|
||||
}
|
||||
|
||||
Dictionary<string, string> properties = new();
|
||||
Dictionary<string, int> listCount = new();
|
||||
|
||||
for (int i = 0; i < nameList.Length; i++)
|
||||
{
|
||||
string headName = nameList[i];
|
||||
if (string.IsNullOrEmpty(headName))
|
||||
continue;
|
||||
|
||||
string[] types = resolvedTypes.Select(x => x[i]).ToArray();
|
||||
string propName = headName.Split('[').First();
|
||||
|
||||
|
||||
string resolvedType = types.All(x => x.Equals(types.First())) ? types.First() : "global::System.String";
|
||||
if (headName.Contains('['))
|
||||
{
|
||||
if (listCount.ContainsKey(propName))
|
||||
listCount[propName] += 1;
|
||||
else
|
||||
listCount.Add(propName, 1);
|
||||
resolvedType = $"global::System.Collections.Generic.List<{resolvedType}>";
|
||||
}
|
||||
|
||||
if (!properties.ContainsKey(propName))
|
||||
properties.Add(propName, $"public {resolvedType} {propName} {{ get; set; }}");
|
||||
}
|
||||
|
||||
string file = $@"// <auto-generated/>
|
||||
namespace AscNet.Table{ns}
|
||||
{{
|
||||
public class {Path.GetFileName(table.Path).Split('.').First()}Table
|
||||
{{
|
||||
{string.Join("\r\n\t\t", properties.Values)}
|
||||
}}
|
||||
|
||||
public class {Path.GetFileName(table.Path).Split('.').First()}TableReader : global::AscNet.Common.Util.TableReader<{Path.GetFileName(table.Path).Split('.').First()}TableReader, {Path.GetFileName(table.Path).Split('.').First()}Table>
|
||||
{{
|
||||
protected override string FilePath {{ get {{ return ""{string.Join("", table.Path.Replace("\\", "/").Split(new string[] {"/Resources/"}, StringSplitOptions.None).Skip(1))}""; }} }}
|
||||
protected override void Load()
|
||||
{{
|
||||
string tsvStr = global::System.Text.Encoding.UTF8.GetString(global::System.IO.File.ReadAllBytes(FilePath).Skip(128).ToArray());
|
||||
using var reader = new global::System.IO.StringReader(tsvStr.Replace(""\t"", "",""));
|
||||
using var csv = new global::CsvHelper.CsvReader(reader, new global::CsvHelper.Configuration.CsvConfiguration(global::System.Globalization.CultureInfo.InvariantCulture) {{ BadDataFound = null, HeaderValidated = null, MissingFieldFound = null }});
|
||||
csv.Context.RegisterClassMap<{Path.GetFileName(table.Path).Split('.').First()}TableMap>();
|
||||
All = csv.GetRecords<{Path.GetFileName(table.Path).Split('.').First()}Table>().ToList();
|
||||
}}
|
||||
}}
|
||||
|
||||
public sealed class {Path.GetFileName(table.Path).Split('.').First()}TableMap : global::CsvHelper.Configuration.ClassMap<{Path.GetFileName(table.Path).Split('.').First()}Table>
|
||||
{{
|
||||
public {Path.GetFileName(table.Path).Split('.').First()}TableMap()
|
||||
{{
|
||||
{string.Join("\r\n\t\t\t", properties.Keys.Where(x => !listCount.ContainsKey(x)).Select(x => $"Map(m => m.{x}).Name(\"{x}\");"))}
|
||||
{string.Join("\r\n\t\t\t", listCount.Keys.Select(x => $@"
|
||||
Map(m => m.{x}).Convert(args =>
|
||||
{{
|
||||
{properties[x].Split(' ')[1]} tags = new {properties[x].Split(' ')[1]}();
|
||||
|
||||
for (int i = 1; i <= {listCount[x]}; i++)
|
||||
{{
|
||||
string tagValue = args.Row.GetField<string>($""{x}[{{i}}]"");
|
||||
if (!string.IsNullOrEmpty(tagValue))
|
||||
{{
|
||||
{(properties[x].Split('<')[1].StartsWith("global::System.Int32") ? @"
|
||||
if (int.TryParse(tagValue, out int tag))
|
||||
{
|
||||
tags.Add(tag);
|
||||
}": @"
|
||||
tags.Add(tagValue);
|
||||
")}
|
||||
}}
|
||||
}}
|
||||
|
||||
return tags;
|
||||
}});
|
||||
"))}
|
||||
}}
|
||||
}}
|
||||
}}";
|
||||
context.AddSource($"AscNet.Table{ns}.{Path.GetFileName(table.Path).Split('.').First()}.g.cs", file);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
fails.Add(new
|
||||
{
|
||||
msg = ex.Message,
|
||||
file = table.Path
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Initialize(GeneratorInitializationContext context) { }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user