-
Notifications
You must be signed in to change notification settings - Fork 45
Support specifying a font name for external font source generation #24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
683524f
d881b69
ee604a1
4b29a56
39b7139
f41e595
9070e21
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk"> | ||
|
|
||
| <!-- Simulate consuming nuget package props file. --> | ||
| <Import Project="../Figgle.Generator/build/Figgle.Generator.props" /> | ||
|
|
||
| <PropertyGroup> | ||
| <TargetFramework>net7.0</TargetFramework> | ||
| </PropertyGroup> | ||
|
|
||
| <ItemGroup> | ||
| <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.3.1" /> | ||
| <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" /> | ||
| <PackageReference Include="xunit" Version="2.4.2" /> | ||
| <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5"> | ||
| <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||
| <PrivateAssets>all</PrivateAssets> | ||
| </PackageReference> | ||
| <PackageReference Include="coverlet.collector" Version="3.0.2"> | ||
| <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||
| <PrivateAssets>all</PrivateAssets> | ||
| </PackageReference> | ||
| </ItemGroup> | ||
|
|
||
| <ItemGroup> | ||
| <AdditionalFiles Include="../Figgle.Generator.Tests/ANSI Shadow.flf" FontName="My External Font" /> | ||
| </ItemGroup> | ||
|
|
||
| <ItemGroup> | ||
| <ProjectReference Include="..\Figgle.Generator\Figgle.Generator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" /> | ||
|
|
||
| <!-- | ||
| Figgle.Generator has a runtime dependency to Figgle.dll which is packaged into the generator's nuget package | ||
| and loaded automatically when a project consumes the nuget. | ||
|
|
||
| Since this test project is referencing the generator manually, we must also manually include | ||
| Figgle.dll as an "analyzer" so the compiler can find it when running the generator. | ||
| --> | ||
| <ProjectReference Include="..\Figgle\Figgle.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" /> | ||
| </ItemGroup> | ||
|
|
||
| </Project> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| using System.Collections.Generic; | ||
| using System.Diagnostics.CodeAnalysis; | ||
| using System; | ||
| using Xunit; | ||
|
|
||
| namespace Figgle.Generator.AcceptanceTests; | ||
|
|
||
| [GenerateFiggleText("HelloWorld", "My External Font", "Hello World!")] | ||
| public partial class FiggleSourceGeneratorAcceptanceTests | ||
| { | ||
| [Fact] | ||
| public void HelloWorldTextWithExternalFontIsSourceGenerated_RenderedTextMatches() | ||
| { | ||
| string expectedText = """ | ||
| ██╗ ██╗███████╗██╗ ██╗ ██████╗ ██╗ ██╗ ██████╗ ██████╗ ██╗ ██████╗ ██╗ | ||
| ██║ ██║██╔════╝██║ ██║ ██╔═══██╗ ██║ ██║██╔═══██╗██╔══██╗██║ ██╔══██╗██║ | ||
| ███████║█████╗ ██║ ██║ ██║ ██║ ██║ █╗ ██║██║ ██║██████╔╝██║ ██║ ██║██║ | ||
| ██╔══██║██╔══╝ ██║ ██║ ██║ ██║ ██║███╗██║██║ ██║██╔══██╗██║ ██║ ██║╚═╝ | ||
| ██║ ██║███████╗███████╗███████╗╚██████╔╝ ╚███╔███╔╝╚██████╔╝██║ ██║███████╗██████╔╝██╗ | ||
| ╚═╝ ╚═╝╚══════╝╚══════╝╚══════╝ ╚═════╝ ╚══╝╚══╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝╚═════╝ ╚═╝ | ||
| """; | ||
|
|
||
| Assert.Equal(expectedText, HelloWorld.Trim(), NewlineIgnoreComparer.Instance); | ||
| } | ||
|
|
||
| private sealed class NewlineIgnoreComparer : IEqualityComparer<string> | ||
| { | ||
| public static NewlineIgnoreComparer Instance { get; } = new(); | ||
|
|
||
| public bool Equals(string? x, string? y) | ||
| { | ||
| return StringComparer.Ordinal.Equals(Normalize(x), Normalize(y)); | ||
| } | ||
|
|
||
| public int GetHashCode(string obj) | ||
| { | ||
| return StringComparer.Ordinal.GetHashCode(Normalize(obj)); | ||
| } | ||
|
|
||
| [return: NotNullIfNotNull("s")] | ||
| private static string? Normalize(string? s) => s?.Replace("\r", ""); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -25,6 +25,7 @@ | |
| <ItemGroup> | ||
| <None Update="ANSI Shadow.flf"> | ||
| <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> | ||
| <DependentUpon>FiggleSourceGeneratorTests_ExternalFonts.cs</DependentUpon> | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| </None> | ||
| </ItemGroup> | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,13 +9,14 @@ | |
| using System.Threading; | ||
| using Microsoft.CodeAnalysis; | ||
| using Microsoft.CodeAnalysis.CSharp; | ||
| using Microsoft.CodeAnalysis.Diagnostics; | ||
| using Microsoft.CodeAnalysis.Text; | ||
| using Xunit; | ||
| using Xunit.Sdk; | ||
|
|
||
| namespace Figgle.Generator.Tests; | ||
|
|
||
| public class FiggleSourceGeneratorTests | ||
| public partial class FiggleSourceGeneratorTests | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. NOTE: The code for testing external fonts was getting a bit much and was cluttering the original test file. To improve code organization I split the external font tests and support code to another file. Using |
||
| { | ||
| private readonly ImmutableArray<MetadataReference> _references; | ||
|
|
||
|
|
@@ -614,64 +615,22 @@ internal partial class Inner | |
| Assert.Equal("Unable to generate Figgle text for nested type 'Inner'. Generation is only supported for non-nested types.", diagnostic.GetMessage()); | ||
| } | ||
|
|
||
| [Theory] | ||
| [InlineData("ANSI Shadow")] | ||
| [InlineData("ansi shadow")] | ||
| public void ExternalFontInAdditionalFiles_RendersText(string fontName) | ||
| { | ||
| string source = | ||
| $$""" | ||
| namespace Test.Namespace | ||
| { | ||
| [GenerateFiggleText("Member", "{{fontName}}", "Figgle")] | ||
| internal partial class DemoUsage | ||
| { | ||
| } | ||
| } | ||
| """; | ||
| string expected = | ||
| """ | ||
| // Copyright Drew Noakes. Licensed under the Apache-2.0 license. See the LICENSE file for more details. | ||
|
|
||
| // <auto-generated> | ||
| // This code was generated by Figgle.Generator. | ||
| // | ||
| // Changes to this file may cause incorrect behavior and will be lost if | ||
| // the code is regenerated. | ||
| // </auto-generated> | ||
|
|
||
| namespace Test.Namespace | ||
| { | ||
| partial class DemoUsage | ||
| { | ||
| public static string Member { get; } = @"███████╗██╗ ██████╗ ██████╗ ██╗ ███████╗ | ||
| ██╔════╝██║██╔════╝ ██╔════╝ ██║ ██╔════╝ | ||
| █████╗ ██║██║ ███╗██║ ███╗██║ █████╗ | ||
| ██╔══╝ ██║██║ ██║██║ ██║██║ ██╔══╝ | ||
| ██║ ██║╚██████╔╝╚██████╔╝███████╗███████╗ | ||
| ╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝╚══════╝ | ||
|
|
||
| "; | ||
| } | ||
| } | ||
| """; | ||
|
|
||
| using var fontStream = File.OpenRead("ANSI Shadow.flf"); | ||
| var additionalFonts = ImmutableArray.Create(new ExternalFontAdditionalText("ANSI Shadow.flf", fontStream)); | ||
| ValidateOutput(source, additionalFonts, expected); | ||
| } | ||
|
|
||
| private void ValidateOutput(string source, params string[] outputs) | ||
| { | ||
| ValidateOutput(source, ImmutableArray<ExternalFontAdditionalText>.Empty, outputs); | ||
| ValidateOutput( | ||
| source, | ||
| ImmutableArray<ExternalFontAdditionalText>.Empty, | ||
| optionsProvider: null, | ||
| outputs); | ||
| } | ||
|
|
||
| private void ValidateOutput( | ||
| string source, | ||
| ImmutableArray<ExternalFontAdditionalText> additionalFonts, | ||
| TestAnalyzerConfigOptionsProvider? optionsProvider, | ||
| params string[] outputs) | ||
| { | ||
| var (compilation, diagnostics) = RunGenerator(source, additionalFonts); | ||
| var (compilation, diagnostics) = RunGenerator(source, additionalFonts, optionsProvider); | ||
|
|
||
| ValidateNoErrors(diagnostics); | ||
|
|
||
|
|
@@ -683,23 +642,23 @@ private void ValidateOutput( | |
|
|
||
| private (Compilation Compilation, ImmutableArray<Diagnostic> Diagnostics) RunGenerator( | ||
| string source, | ||
| ImmutableArray<ExternalFontAdditionalText>? optionalAdditionalFonts = null) | ||
| ImmutableArray<ExternalFontAdditionalText>? additionalFonts = null, | ||
| TestAnalyzerConfigOptionsProvider? optionsProvider = null) | ||
| { | ||
| var additionalFonts = optionalAdditionalFonts | ||
| ?? ImmutableArray<ExternalFontAdditionalText>.Empty; | ||
|
|
||
| var syntaxTree = CSharpSyntaxTree.ParseText(source); | ||
|
|
||
| var compilation = CSharpCompilation.Create( | ||
| "testAssembly", | ||
| new SyntaxTree[] { syntaxTree }, | ||
| [syntaxTree], | ||
| _references, | ||
| new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); | ||
|
|
||
| ISourceGenerator generator = new FiggleSourceGenerator(); | ||
|
|
||
| var driver = CSharpGeneratorDriver.Create(generator) | ||
| .AddAdditionalTexts(additionalFonts.As<AdditionalText>()); | ||
| var driver = CSharpGeneratorDriver.Create( | ||
| [generator], | ||
| additionalTexts: additionalFonts, | ||
| optionsProvider: optionsProvider); | ||
|
|
||
| driver.RunGeneratorsAndUpdateCompilation( | ||
| compilation, | ||
|
|
@@ -722,24 +681,6 @@ private static void ValidateNoErrors(ImmutableArray<Diagnostic> diagnostics) | |
| } | ||
| } | ||
|
|
||
| private sealed class ExternalFontAdditionalText : AdditionalText | ||
| { | ||
| private readonly SourceText _sourceText; | ||
|
|
||
| public ExternalFontAdditionalText(string path, Stream externalFont) | ||
| { | ||
| Path = path; | ||
| _sourceText = SourceText.From(externalFont); | ||
| } | ||
|
|
||
| public override string Path { get; } | ||
|
|
||
| public override SourceText? GetText(CancellationToken cancellationToken = default) | ||
| { | ||
| return _sourceText; | ||
| } | ||
| } | ||
|
|
||
| private sealed class NewlineIgnoreComparer : IEqualityComparer<string> | ||
| { | ||
| public static NewlineIgnoreComparer Instance { get; } = new(); | ||
|
|
||

There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A possible extension to this would be to generate const strings for any external font names, so that if the file is removed or the build item removed, then the code wouldn't compile. Some open questions (like how to create a valid C# member name from an arbitrary file name) but thought I'd throw it out there. This PR is great as is.