Version Gates
This document explains how Huml.Net gates parser and lexer behaviour on the active HUML spec version, and provides a step-by-step checklist for adding support for a new spec version.
How Version Gates Work
Huml.Net uses a single code path for all supported spec versions — there are no forked Lexer or
HumlParser classes per spec version. Behavioural differences are expressed as explicit
conditional branches within the single code path, using a consistent >= comparison:
if (_effectiveSpecVersion >= HumlSpecVersion.V0_2)
{
// v0.2-only behaviour
}
All gates use >=, never ==. This makes them forward-compatible: a gate that activates for
v0.2 automatically activates for v0.3, v0.4, and beyond, without any code change.
To find all version gates in the codebase:
grep -rn ">= HumlSpecVersion" src/
HumlSpecVersion is an int-backed enum (V0_1 = 1, V0_2 = 2). The integer backing makes
>= comparisons well-defined and also allows SpecVersionPolicy to use the enum values as
const fields (in src/Huml.Net/Versioning/SpecVersionPolicy.cs).
Adding a New Spec Version
Follow these steps in order when adding support for a new HUML spec version (e.g. v0.3):
Add an enum member to
HumlSpecVersioninsrc/Huml.Net/Versioning/HumlSpecVersion.cs:V0_3 = 3,Update
SpecVersionPolicy.Latest(string constant) andSpecVersionPolicy.LatestVersion(enum constant) insrc/Huml.Net/Versioning/SpecVersionPolicy.csto point to the new version.Add the fixture submodule at
fixtures/v0.3/pinned to thetests@v0.3tag:git submodule add https://github.com/huml-lang/tests fixtures/v0.3 cd fixtures/v0.3 && git checkout v0.3Add a
<Content>include forfixtures/v0.3/intests/Huml.Net.Tests/Huml.Net.Tests.csproj, mirroring the existingv0.1andv0.2entries, so the fixture files are copied to the test output directory.Add a shared suite test method
V03_fixture_passesintests/Huml.Net.Tests/SharedSuiteTests.cs, mirroring the existingV01_fixture_passesandV02_fixture_passesmethods.Add
>= HumlSpecVersion.V0_3gates insrc/Huml.Net/Lexer/Lexer.csandsrc/Huml.Net/Parser/HumlParser.csfor each new behavioural difference introduced by the new spec version.Update
HumlOptions.Defaultand/orHumlOptions.LatestSupportedinsrc/Huml.Net/Versioning/HumlOptions.csif the new version becomes the pinned default.Update the support table in
docs/versioning.md.
Deprecation Process
When a spec version exits the support window, mark its enum member with [Obsolete]:
[Obsolete("HumlSpecVersion.V0_1 is deprecated. HUML v0.1 will leave the support window " +
"when v0.3 ships. Migrate to HumlSpecVersion.V0_2.")]
V0_1 = 1,
V0_1 is the live example — its deprecation message is already in place in
src/Huml.Net/Versioning/HumlSpecVersion.cs.
Any code that must still reference a deprecated version (e.g. SpecVersionPolicy.MinimumSupportedVersion,
test helpers) wraps the reference with a targeted pragma suppression:
#pragma warning disable CS0618
public const HumlSpecVersion MinimumSupportedVersion = HumlSpecVersion.V0_1;
#pragma warning restore CS0618
Keep #pragma warning restore CS0618 on the very next line after the reference. This minimises
the suppression scope and avoids accidentally silencing unrelated warnings.
Testing Version Gates
Use HumlOptions.LatestSupported in tests when you want pinned v0.2 behaviour that ignores any
%HUML header in the input:
var result = HumlSerializer.Parse(input, HumlOptions.LatestSupported);
Use HumlOptions.Default when header-aware behaviour is under test (the parser reads the
%HUML header and applies the version declared there):
var result = HumlSerializer.Parse(input, HumlOptions.Default);
To force a specific version regardless of any header in the input, construct HumlOptions
explicitly and set VersionSource = VersionSource.Options. For deprecated versions, wrap with
the CS0618 pragma:
#pragma warning disable CS0618
private static readonly HumlOptions V01Options =
new() { SpecVersion = HumlSpecVersion.V0_1, VersionSource = VersionSource.Options };
#pragma warning restore CS0618
The V01Options field in tests/Huml.Net.Tests/SharedSuiteTests.cs shows this pattern in use.