fix: update benchmarks to net10.0 and fix template syntax converters#11
Merged
Conversation
- Upgrade BenchmarkDotNet from 0.14.0 to 0.15.8 and target net10.0
(net8.0 runtime is not available on this machine)
- Update RuntimeMoniker from Net80 to Net10_0 in AllTemplatesBenchmark
- Fix ToScribanSyntax, ToHandlebarsSyntax, ToStubbleSyntax to handle
the {% end %} keyword introduced in refactor/tokenizer (was {% endif %})
- Add ToFluidSyntax to properly convert {% end %} → {% endif %}
(Fluid/Liquid requires explicit endif/endunless closing tags)
- Use stack-based conversion in ToHandlebarsSyntax and ToFluidSyntax
so each {% end %} emits the correct closing tag for its block type
https://claude.ai/code/session_01DZ2iHjScBAtPgRfbR6W2LX
- Remove unused `foo: ""` field from FileGenerator globalOptions tuple; simplify the tuple to a plain string since only Visibility is used - Delete TemplateParser.cs which contained only an empty namespace declaration (it was a leftover stub from the refactor/tokenizer branch) - Remove unused private RenderExpression method from ConditionalTemplateNode (it was never called; rendering delegates to child nodes) https://claude.ai/code/session_01DZ2iHjScBAtPgRfbR6W2LX
…ethod - Rename *TemplateToken classes to *TemplateNode to match the ITemplateNode interface name they implement: - CompositeTemplateToken → CompositeTemplateNode - LiteralTemplateToken → LiteralTemplateNode - VariableTemplateToken → VariableTemplateNode - ConditionalTemplateToken → ConditionalTemplateNode - Rename GenerateRenderer() → GenerateRenderExpression() on ITemplateNode and all implementations, to better describe what the method returns (a C# expression string, not a rendered template) - Rename private escape() → Escape() in LiteralTemplateNode to follow PascalCase conventions for private methods https://claude.ai/code/session_01DZ2iHjScBAtPgRfbR6W2LX
Tests that malformed templates produce SB003 diagnostics with correct
messages:
- Invalid variable name (e.g. {{ 123invalid }}) → "not a valid variable name"
- Invalid block expression (e.g. {% badkeyword %}) → "not a valid expression"
- Unclosed conditional ({% if foo %} with no {% end %}) → "Conditional doesnt end"
- SB003 is always reported as DiagnosticSeverity.Error
Removes the stale TODO comment block that referenced the old Broken.html
fixture (deleted in refactor/tokenizer).
https://claude.ai/code/session_01DZ2iHjScBAtPgRfbR6W2LX
New ParserTests.cs tests the Parser class directly without going through the source generator pipeline: - Plain text and empty templates produce LiteralTemplateNode - Variable syntax: required, optional (?), array (..) - Composite nodes for templates with mixed literals and variables - if/unless/else/end conditional blocks produce ConditionalTemplateNode with correctly populated IfTrue/IfFalse branches - unless inverts which branch is IfTrue vs IfFalse - GetVariables traverses the full AST including conditionals - ParserError thrown with correct Reason and Match position for: invalid variable names, invalid block keywords, unclosed conditionals https://claude.ai/code/session_01DZ2iHjScBAtPgRfbR6W2LX
Adds a realistic full web-page HTML template with 20 boolean conditionals and ~50 string variables covering: site header/nav, hero section, article with featured image and tags, sidebar with author widget and newsletter form, and footer with social links. This gives the benchmark a much heavier workload than the existing small-component templates (ArticleCard, UserProfile, etc.) and exercises nested conditionals, if/else branches, and a large parameter set — a more representative real-world scenario. https://claude.ai/code/session_01DZ2iHjScBAtPgRfbR6W2LX
- Update repository structure: add Benchmarks section, Parser.cs, TemplateToken.cs, ParserTests.cs; remove stale FileGenerator-only entry - Update architecture section: document Parser/AST layer, ITemplateNode interface with GenerateRenderExpression/GetVariables, ClassGenerator split - Add Benchmarks section: note net10.0 target, ReflectedScenario behaviour, syntax conversion, and benchmark template constraints - Add Diagnostic Codes table (SB001–SB003) - Update Testing section: document ParserTests.cs alongside FileGeneratorTests - Update Adding a New Feature workflow to include ParserTests step - Add known limitation: variables must be unique per template (no deduplication) - Update command: csharpier format . (not just csharpier .) - Update Project Settings Reference: add benchmarks target framework row https://claude.ai/code/session_01DZ2iHjScBAtPgRfbR6W2LX
BenchmarkDotNet writes run logs to BenchmarkDotNet.Artifacts/ next to the project file. These are local artifacts and should not be tracked. https://claude.ai/code/session_01DZ2iHjScBAtPgRfbR6W2LX
Parser stored the context but never used it — all errors are raised as ParserError exceptions that FileGenerator catches and converts to diagnostics. Remove the dead parameter and property: - Parser: drop Context property and context constructor parameter - ClassGenerator.GenerateFileContent: drop context parameter (only passed it through to Parser) - FileGenerator: update call site to not pass spc to ClassGenerator - ParserTests: remove now-unnecessary default(SourceProductionContext) argument and Microsoft.CodeAnalysis using https://claude.ai/code/session_01DZ2iHjScBAtPgRfbR6W2LX
BuildFactory was passing a bare TemplateArgument for array variables,
but the generated constructor expects IEnumerable<TemplateArgument>.
This caused an expression-tree type mismatch at factory compile time
for any benchmark template using {{..var}} syntax.
- BuildFactory: wrap sample value in a single-element TemplateArgument[]
and pass it as IEnumerable<TemplateArgument> to match the constructor
- _data: pass string[] (not plain string) for array variables so
competitor engines that support iteration receive the right type
- RenderFluid: guard against string[] values — Fluid's SetValue accepts
arrays directly; the previous (string) cast would throw at runtime
https://claude.ai/code/session_01DZ2iHjScBAtPgRfbR6W2LX
Scriban has no 'unless' keyword. The previous conversion emitted
{{ unless VAR }} which Scriban would silently ignore or error on,
producing wrong benchmark output for any template using {% unless %}.
Translate {% unless VAR %} to {{ if !VAR }} which Scriban understands.
The {% else %} and {% end %} conversions are unaffected.
https://claude.ai/code/session_01DZ2iHjScBAtPgRfbR6W2LX
Variables used multiple times in a template are now collapsed into a single constructor parameter. Conflicting types (e.g. Bool vs TemplateArgument) or array/scalar mismatches for the same name throw TemplateError → SB003 diagnostic. Optional resolution: a variable is required if any of its occurrences is required. Adds three new tests: duplicate variable, required-overrides-optional, type conflict. https://claude.ai/code/session_01DZ2iHjScBAtPgRfbR6W2LX
…onals
The regex-based approach would greedily consume the wrong {% end %} tag when
conditionals were nested (e.g. {% if isLoggedIn %}...{% if isPremium %}...{% end %}...{% end %}).
Rewrites ToStubbleSyntax to use the same stack-based BlockTagPattern approach
already used by ToFluidSyntax and ToHandlebarsSyntax. Also handles {% else %}
correctly by emitting the inverse section ({{/name}}{{^name}} or {{/name}}{{#name}}).
https://claude.ai/code/session_01DZ2iHjScBAtPgRfbR6W2LX
…rd scenarios
New results measured with BenchmarkDotNet v0.15.8 on .NET 10.0.4.
Table now includes all 6 scenarios (ListItem, SimpleGreeting, ArticleCard,
ProfileCard, UserProfile, FullPage) and updated comparison ratios.
Also fixes stale {% endunless %} reference (correct syntax is {% end %}).
https://claude.ai/code/session_01DZ2iHjScBAtPgRfbR6W2LX
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
(net8.0 runtime is not available on this machine)
the {% end %} keyword introduced in refactor/tokenizer (was {% endif %})
(Fluid/Liquid requires explicit endif/endunless closing tags)
so each {% end %} emits the correct closing tag for its block type
https://claude.ai/code/session_01DZ2iHjScBAtPgRfbR6W2LX