Skip to content

Commit 7dc6a88

Browse files
Use System.Text.Json and Scriban
1 parent f2c700c commit 7dc6a88

File tree

6 files changed

+43
-77
lines changed

6 files changed

+43
-77
lines changed

exercises/practice/leap/.meta/Generator.tpl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ using Xunit;
22

33
public class LeapTests
44
{
5-
{{#test_cases}}
6-
[Fact{{#unless @first}}(Skip = "Remove this Skip property to run this test"){{/unless}}]
7-
public void {{test_method_name}}()
5+
{{for testCase in testCases}}
6+
[Fact{{if !for.first}}(Skip = "Remove this Skip property to run this test"){{end}}]
7+
public void {{testCase.testMethodName}}()
88
{
9-
Assert.{{expected}}(Leap.IsLeapYear({{input.year}}));
9+
Assert.{{testCase.expected ? "True" : "False"}}(Leap.IsLeapYear({{testCase.input.year}}));
1010
}
11-
{{/test_cases}}
11+
{{end}}
1212
}

generators/CanonicalData.cs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,39 @@
11
using System.Collections.Immutable;
2+
using System.Text.Json;
3+
using System.Text.Json.Nodes;
24

35
using LibGit2Sharp;
46

5-
using Newtonsoft.Json.Linq;
6-
77
namespace Generators;
88

9-
internal record CanonicalData(Exercise Exercise, JObject[] TestCases);
9+
internal record CanonicalData(Exercise Exercise, JsonNode[] TestCases);
1010

1111
internal static class CanonicalDataParser
1212
{
1313
static CanonicalDataParser() => ProbSpecs.Sync();
1414

1515
internal static CanonicalData Parse(Exercise exercise) => new(exercise, ParseTestCases(exercise));
1616

17-
private static JObject[] ParseTestCases(Exercise exercise)
18-
{
19-
var jsonObject = JObject.Parse(File.ReadAllText(Paths.CanonicalDataFile(exercise)));
20-
return ParseTestCases(jsonObject, ImmutableQueue<string>.Empty).ToArray();
21-
}
17+
private static JsonNode[] ParseTestCases(Exercise exercise) =>
18+
ParseTestCases(ParseCanonicalData(exercise), ImmutableQueue<string>.Empty).ToArray();
19+
20+
private static JsonNode ParseCanonicalData(Exercise exercise) =>
21+
JsonNode.Parse(File.ReadAllText(Paths.CanonicalDataFile(exercise)))!;
2222

23-
private static IEnumerable<JObject> ParseTestCases(JObject jsonObject, ImmutableQueue<string> path)
23+
private static IEnumerable<JsonNode> ParseTestCases(JsonNode jsonNode, ImmutableQueue<string> path)
2424
{
25-
var updatedPath = jsonObject.TryGetValue("description", out var description)
26-
? path.Enqueue(description.Value<string>()!)
25+
var updatedPath = jsonNode["description"] is {} description
26+
? path.Enqueue(description.GetValue<string>())
2727
: path;
2828

29-
return jsonObject.TryGetValue("cases", out var cases)
30-
? ((JArray)cases).Cast<JObject>().SelectMany(child => ParseTestCases(child, updatedPath))
31-
: [ToTestCase(jsonObject, updatedPath)];
29+
return jsonNode["cases"] is {} cases
30+
? cases.AsArray().SelectMany(child => ParseTestCases(child!, updatedPath))
31+
: [ToTestCase(jsonNode, updatedPath)];
3232
}
3333

34-
private static JObject ToTestCase(JObject testCaseJson, IEnumerable<string> path)
34+
private static JsonNode ToTestCase(JsonNode testCaseJson, IEnumerable<string> path)
3535
{
36-
testCaseJson["path"] = JArray.FromObject(path);
36+
testCaseJson["path"] = JsonSerializer.SerializeToNode(path);
3737
return testCaseJson;
3838
}
3939

generators/Generators.csproj

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,10 @@
99

1010
<ItemGroup>
1111
<PackageReference Include="CommandLineParser" Version="2.9.1" />
12-
<PackageReference Include="Handlebars.Net" Version="2.1.6" />
13-
<PackageReference Include="Handlebars.Net.Extension.NewtonsoftJson" Version="1.0.3" />
14-
<PackageReference Include="Handlebars.Net.Helpers" Version="2.4.10" />
1512
<PackageReference Include="Humanizer.Core" Version="2.14.1" />
1613
<PackageReference Include="LibGit2Sharp" Version="0.31.0" />
1714
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.12.0" />
18-
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
15+
<PackageReference Include="Scriban" Version="5.12.1" />
1916
<PackageReference Include="Tomlyn" Version="0.18.0" />
2017
</ItemGroup>
2118

generators/Naming.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@ namespace Generators;
44

55
internal static class Naming
66
{
7-
internal static string ToMethodName(params object[] path) =>
8-
path.Cast<string>()
9-
.Unwords()
7+
internal static string ToMethodName(params string[] path) =>
8+
path.Unwords()
109
.Words()
1110
.Select(Transform)
1211
.Unwords()

generators/Templates.cs

Lines changed: 18 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,42 @@
1-
using System.Dynamic;
2-
using System.Globalization;
1+
using System.Text.Json;
2+
using System.Text.Json.Nodes;
33

4-
using HandlebarsDotNet;
5-
using HandlebarsDotNet.Helpers;
4+
using Microsoft.CodeAnalysis.CSharp;
65

7-
using Newtonsoft.Json.Linq;
6+
using Scriban;
7+
using Scriban.Runtime;
88

99
namespace Generators;
1010

1111
internal static class Templates
1212
{
13-
private static readonly IHandlebars HandlebarsContext = Handlebars.Create();
14-
15-
static Templates()
13+
public static string RenderTestsCode(CanonicalData canonicalData)
1614
{
17-
HandlebarsHelpers.Register(HandlebarsContext, options => { options.UseCategoryPrefix = false; });
18-
HandlebarsContext.Configuration.FormatProvider = CultureInfo.InvariantCulture;
19-
20-
HandlebarsContext.RegisterHelper("lit", (writer, context, parameters) =>
21-
writer.WriteSafeString(Formatting.FormatLiteral(parameters.First())));
22-
23-
HandlebarsContext.RegisterHelper("equals", (output, options, context, arguments) =>
24-
{
25-
if (arguments.Length != 2) throw new HandlebarsException("{{#equals}} helper must have exactly two arguments");
26-
27-
if (arguments[0]!.Equals(arguments[1]!))
28-
options.Template(output, context);
29-
else
30-
options.Inverse(output, context);
31-
});
15+
var template = Template.Parse(File.ReadAllText(Paths.TemplateFile(canonicalData.Exercise)));
16+
return template.Render(TemplateData.ForCanonicalData(canonicalData));
3217
}
3318

34-
public static string RenderTestsCode(CanonicalData canonicalData) =>
35-
CompileTemplate(canonicalData.Exercise)(TemplateData.ForCanonicalData(canonicalData));
36-
37-
private static HandlebarsTemplate<object, object> CompileTemplate(Exercise exercise) =>
38-
HandlebarsContext.Compile(File.ReadAllText(Paths.TemplateFile(exercise)));
39-
4019
private static class TemplateData
4120
{
42-
internal static Dictionary<string, object> ForCanonicalData(CanonicalData canonicalData)
21+
internal static JsonElement ForCanonicalData(CanonicalData canonicalData)
4322
{
4423
var testCases = canonicalData.TestCases.Select(Create).ToArray();
24+
var testCasesByProperty = GroupTestCasesByProperty(testCases);
4525

46-
return new()
47-
{
48-
["test_cases"] = testCases.ToArray(),
49-
["test_cases_by_property"] = GroupTestCasesByProperty(testCases)
50-
};
26+
return JsonSerializer.SerializeToElement(new { testCases, testCasesByProperty });
5127
}
5228

53-
private static ExpandoObject Create(JToken testCase)
29+
private static JsonElement Create(JsonNode testCase)
5430
{
55-
dynamic testData = testCase.ToObject<ExpandoObject>()!;
56-
testData.test_method_name = Naming.ToMethodName(testData.path.ToArray());
57-
testData.short_test_method_name = Naming.ToMethodName(testData.description);
58-
59-
if (testCase["expected"] is JArray expected)
60-
{
61-
testData.expected = expected.Select(e => e.ToString()).ToArray();
62-
}
31+
testCase["testMethodName"] = Naming.ToMethodName(testCase["path"]!.AsArray().GetValues<string>().ToArray());
32+
testCase["shortMethodName"] = Naming.ToMethodName(testCase["description"]!.GetValue<string>());
6333

64-
return testData;
34+
return JsonSerializer.SerializeToElement(testCase);
6535
}
6636

67-
private static Dictionary<string, dynamic[]> GroupTestCasesByProperty(IEnumerable<dynamic> testCases) =>
37+
private static Dictionary<string, JsonElement[]> GroupTestCasesByProperty(IEnumerable<JsonElement> testCases) =>
6838
testCases
69-
.GroupBy(testCase => (string)testCase.property)
39+
.GroupBy(testCase => testCase.GetProperty("property").GetString()!)
7040
.ToDictionary(kv => kv.Key, kv => kv.ToArray());
7141
}
72-
}
42+
}

generators/TestCasesConfiguration.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ internal static CanonicalData RemoveExcludedTestCases(CanonicalData canonicalDat
99
{
1010
var excludedTestCaseIds = ExcludedTestCaseIds(canonicalData.Exercise);
1111
var includedTestCases = canonicalData.TestCases
12-
.Where(testCase => !excludedTestCaseIds.Contains(testCase["uuid"]!.ToObject<string>()!))
12+
.Where(testCase => !excludedTestCaseIds.Contains(testCase["uuid"]!.GetValue<string>()))
1313
.ToArray();
1414

1515
return canonicalData with { TestCases = includedTestCases };

0 commit comments

Comments
 (0)