Skip to content

Commit

Permalink
refactor: Use source generator instead of T4 template
Browse files Browse the repository at this point in the history
Tweak source generator output

Merge fixes
  • Loading branch information
alexmg committed Aug 29, 2024
1 parent 7fc5de3 commit b8f517b
Show file tree
Hide file tree
Showing 14 changed files with 217 additions and 1,362 deletions.
16 changes: 11 additions & 5 deletions Moniker.sln
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29411.108
# Visual Studio Version 17
VisualStudioVersion = 17.11.35208.52
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Moniker", "src\Moniker\Moniker.csproj", "{4AE3D031-1238-4411-BB00-59A5308A2467}"
EndProject
Expand All @@ -13,13 +13,15 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
ProjectSection(SolutionItems) = preProject
.gitignore = .gitignore
src\Directory.Build.props = src\Directory.Build.props
README.md = README.md
GitVersion.yml = GitVersion.yml
README.md = README.md
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Moniker.PerformanceTests", "test\Moniker.PerformanceTests\Moniker.PerformanceTests.csproj", "{FF324EAB-F8AE-4B7E-B8E0-07BD24B537DD}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Moniker.PerformanceTests", "test\Moniker.PerformanceTests\Moniker.PerformanceTests.csproj", "{FF324EAB-F8AE-4B7E-B8E0-07BD24B537DD}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Moniker.ApprovalTests", "test\Moniker.ApprovalTests\Moniker.ApprovalTests.csproj", "{C0555388-7087-408C-93C5-22D3FC2DA574}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Moniker.ApprovalTests", "test\Moniker.ApprovalTests\Moniker.ApprovalTests.csproj", "{C0555388-7087-408C-93C5-22D3FC2DA574}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Moniker.Generator", "src\Moniker.Generator\Moniker.Generator.csproj", "{1780C6FE-1D7D-41A9-A652-69203E4A5D6F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down Expand Up @@ -47,6 +49,10 @@ Global
{C0555388-7087-408C-93C5-22D3FC2DA574}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C0555388-7087-408C-93C5-22D3FC2DA574}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C0555388-7087-408C-93C5-22D3FC2DA574}.Release|Any CPU.Build.0 = Release|Any CPU
{1780C6FE-1D7D-41A9-A652-69203E4A5D6F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1780C6FE-1D7D-41A9-A652-69203E4A5D6F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1780C6FE-1D7D-41A9-A652-69203E4A5D6F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1780C6FE-1D7D-41A9-A652-69203E4A5D6F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
6 changes: 6 additions & 0 deletions src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@
<RepositoryUrl>https://github.com/alexmg/Moniker</RepositoryUrl>
</PropertyGroup>

<PropertyGroup>
<LangVersion>latest</LangVersion>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<None Include="..\..\icon.png" Pack="true" PackagePath="\" />
<None Include="..\..\README.md" Pack="true" PackagePath="\" />
Expand Down
1 change: 0 additions & 1 deletion src/Moniker.Cli/Moniker.Cli.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
<Description>Moniker CLI is a tiny .NET Core Global Tool for generating fun names.</Description>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<LangVersion>latest</LangVersion>
<PackAsTool>true</PackAsTool>
<ToolCommandName>moniker</ToolCommandName>
</PropertyGroup>
Expand Down
4 changes: 2 additions & 2 deletions src/Moniker.Cli/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ public int OnExecute()
private static int Main(string[] args)
=> CommandLineApplication.Execute<Program>(args);

private static string GetVersion() =>
(string)typeof(Program).Assembly
private static string? GetVersion() =>
(string?)typeof(Program).Assembly
.GetType("GitVersionInformation")!
.GetField("FullSemVer")!
.GetValue(null);
Expand Down
18 changes: 18 additions & 0 deletions src/Moniker.Generator/Moniker.Generator.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<Nullable>enable</Nullable>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.11.0" />
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

</Project>
112 changes: 112 additions & 0 deletions src/Moniker.Generator/Utf8StringsGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;

namespace Moniker.Generator;

/// <inheritdoc />
[Generator]
public class Utf8StringsGenerator : ISourceGenerator
{
/// <inheritdoc/>
public void Initialize(GeneratorInitializationContext context)
{
// No initialization required
}

/// <inheritdoc/>
public void Execute(GeneratorExecutionContext context)
{
var additionalFiles = context.AdditionalFiles
.Where(f => Path.GetExtension(f.Path).Equals(".txt", StringComparison.OrdinalIgnoreCase));

foreach (var file in additionalFiles)
{
var className = Path.GetFileNameWithoutExtension(file.Path);
var sourceText = GenerateSourceForFile(className, file);

context.AddSource($"{className}.g.cs", SourceText.From(sourceText, Encoding.UTF8));
}
}

private static string GenerateSourceForFile(string className, AdditionalText file)
{
var offsets = new List<int>();
var charCounts = new List<int>();
var offset = 0;
var stringBuilder = new StringBuilder();

stringBuilder.AppendLine("//------------------------------------------------------------------------------");
stringBuilder.AppendLine("// <auto-generated>");
stringBuilder.AppendLine("// This code was generated by a tool.");
stringBuilder.AppendLine("// Changes to this file may cause incorrect behavior and will be lost if");
stringBuilder.AppendLine("// the code is re-generated.");
stringBuilder.AppendLine("// </auto-generated>");
stringBuilder.AppendLine("//------------------------------------------------------------------------------");
stringBuilder.AppendLine("#nullable enable");
stringBuilder.AppendLine();
stringBuilder.AppendLine("using System;");
stringBuilder.AppendLine();
stringBuilder.AppendLine("namespace Moniker;");
stringBuilder.AppendLine();
stringBuilder.AppendLine($"internal static class {className}");
stringBuilder.AppendLine("{");
stringBuilder.AppendLine(" public static Utf8Strings Strings => new(Count, Data, Offsets, CharCounts);");
stringBuilder.AppendLine();
stringBuilder.AppendLine(" private static ReadOnlySpan<byte> Data =>");

foreach (var textLine in file.GetText()?.Lines.ToArray() ?? [])
{
var line = textLine.ToString().Trim();
if (line.Length == 0 || line[0] == '#')
continue;

var byteLength = Encoding.UTF8.GetByteCount(line);

if (line.Length > 0)
{
stringBuilder.AppendLine($" \"{line}\"u8 + // [{offset}..{offset + byteLength}]");
}

offsets.Add(offset);
charCounts.Add(line.Length);
offset += byteLength;
}

offsets.Add(offset);
stringBuilder.AppendLine(" \"\"u8;");
stringBuilder.AppendLine();
stringBuilder.AppendLine($" private const int Size = {offsets.Last()};");
stringBuilder.AppendLine();
stringBuilder.AppendLine($" public const int Count = {offsets.Count - 1};");
stringBuilder.AppendLine();

AppendReadOnlySpan(stringBuilder, "Offsets", "int", offsets);
stringBuilder.AppendLine();
AppendReadOnlySpan(stringBuilder, "CharCounts", "byte", charCounts);

stringBuilder.AppendLine("}");

return stringBuilder.ToString();
}

private static void AppendReadOnlySpan(StringBuilder stringBuilder, string name, string type, List<int> values)
{
stringBuilder.AppendLine($" private static ReadOnlySpan<{type}> {name} =>");
stringBuilder.AppendLine(" [");

var groups = from e in values.Select((v, i) => (Index: i, Value: v))
group e.Value.ToString() by e.Index / 15;

foreach (var group in groups)
{
stringBuilder.AppendLine($" {string.Join(", ", group)},");
}

stringBuilder.AppendLine(" ];");
}
}
6 changes: 0 additions & 6 deletions src/Moniker/Moniker.cs

This file was deleted.

26 changes: 12 additions & 14 deletions src/Moniker/Moniker.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,12 @@
<PropertyGroup>
<Description>Moniker is a tiny .NET library for generating fun names.</Description>
<TargetFramework>net8.0</TargetFramework>
<LangVersion>latest</LangVersion>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>

<ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute">
<_Parameter1>Moniker.Tests</_Parameter1>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute">
<_Parameter1>$(AssemblyName).Tests</_Parameter1>
</AssemblyAttribute>
</ItemGroup>

Expand All @@ -21,22 +19,22 @@
</ItemGroup>

<ItemGroup>
<None Update="Moniker.g.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>Moniker.g.cs</LastGenOutput>
</None>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.11.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" PrivateAssets="all" />
</ItemGroup>

<ItemGroup>
<Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
<AdditionalFiles Include="*.txt" />
</ItemGroup>

<ItemGroup>
<Compile Update="Moniker.g.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Moniker.g.tt</DependentUpon>
</Compile>
<ProjectReference Include="..\Moniker.Generator\Moniker.Generator.csproj"
OutputItemType="Analyzer"
ReferenceOutputAssembly="false" />
</ItemGroup>

<ItemGroup>
<Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
</ItemGroup>

</Project>
Loading

0 comments on commit b8f517b

Please sign in to comment.