Skip to content

fix: update benchmarks to net10.0 and fix template syntax converters#11

Merged
C0DK merged 18 commits into
mainfrom
claude/fix-benchmarks-parser-tests-17Fz5
Mar 19, 2026
Merged

fix: update benchmarks to net10.0 and fix template syntax converters#11
C0DK merged 18 commits into
mainfrom
claude/fix-benchmarks-parser-tests-17Fz5

Conversation

@C0DK

@C0DK C0DK commented Mar 17, 2026

Copy link
Copy Markdown
Owner
  • 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

claude and others added 18 commits March 17, 2026 22:05
- 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
@C0DK
C0DK merged commit 06403df into main Mar 19, 2026
2 checks passed
@C0DK
C0DK deleted the claude/fix-benchmarks-parser-tests-17Fz5 branch March 19, 2026 19:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants