Skip to content

feat(validation): warn about missing variables used as bare condition operands - #231

Merged
vaceslav merged 1 commit into
mainfrom
feat/validation-missing-condition-vars
Sep 27, 2026
Merged

vaceslav merged 1 commit into
mainfrom
feat/validation-missing-condition-vars

Conversation

@vaceslav

Copy link
Copy Markdown
Contributor

Changes

ValidateTemplate(template, data) now warns when a condition tests a variable that is missing from the data for truthiness on its own (a bare operand). Such a variable is silently false, which usually hides a typo ({{#if IsActiv}}).

  • New ValidationWarningType.MissingConditionVariable = 2. The message names the variable and the condition: Condition 'A and Missing' uses variable 'Missing', which is not provided in the data. It is treated as false. Location is the marker ({{#if A and Missing}}).
  • Bare operands are found in the parsed condition AST (ConditionalEvaluator.CollectBareOperandVariables): the whole condition, and the operands of and / or / not. Nested operator nodes are always descended into.
  • Reported: {{#if Missing}}, {{#if not Missing}}, {{#if A and Missing}}, {{#elseif Missing}}, inline {{#if Missing}}x{{/if}}, table-row conditionals, headers/footers, and conditions inside loops. Inside loops the check uses the same scoped resolution as missing placeholders: item properties, named iteration variables, globals resolve, and @metadata / . / this are skipped. Conditions in loops over empty collections are not checked, the same as placeholders.
  • Not reported: operands of exists / is empty / is not empty (they are meant for missing values); comparison operands (Status = Active bareword fallback stays as it is); in and the string operators; invalid conditions (already an InvalidConditionalExpression error); validation without data.
  • Inline {{(...)}} expressions are not checked (decision). Today the validator reports a whole inline expression as one missing variable (Variable '(A and B)' is referenced ... but not provided), even when every operand is present. That is a separate existing false positive. A bare-operand warning on top of it would report the same expression twice. The right fix is to validate inline expressions through the AST instead, which is a behavior change to Errors/IsValid, so it belongs in its own PR.
  • The warning is not added to MissingVariables or Errors, and IsValid does not change. Existing DOCX consumers see only an additional warning.
  • One shared implementation (Core/MissingConditionVariableCheck.cs), called from ScopedVariableValidator (DOCX) and from the OdtTemplateValidator scope walker (ODT). The TemplateProcessor facade therefore gets it too. Each condition/variable pair is reported once.
  • Docs: warning types table in the developer quick start, notes in condition-evaluation and in the conditionals guide for template authors, library README/Examples/ARCHITECTURE.

Tests

  • Integration/ValidationMissingConditionVariableTests: every case runs as DOCX and ODT, both directly and through the facade, and asserts identical warnings/errors/missing variables. Covered: bare/not/and/or/grouping/elseif/inline/dotted path; no warning for exists / is empty / is not empty / comparisons / in / string operators / literals; no data; invalid condition; dedupe; several variables; loop scoping (item properties, named vars, @first/@last/@index, this, globals); missing item property in a loop; item property used outside its loop; empty loop; inline expressions; table-row conditional and header.
  • Conditionals/CollectBareOperandVariablesTests: the AST walk.
  • Odt/OdtValidationParityTests: new "missing bare condition operands" case.
  • Release build with -p:ContinuousIntegrationBuild=true (0 warnings), all test projects on net10/9/8, dotnet format --verify-no-changes, dotnet pack, mkdocs build --strict.

Public API impact

Additive: ValidationWarningType.MissingConditionVariable = 2 (in PublicAPI.Unshipped.txt, with XML docs). Behavior change limited to ValidationResult.Warnings: validation with data can return additional warnings. Errors, MissingVariables and IsValid are unchanged.

@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 96.42857% with 1 line in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...Dev.Templify/Core/MissingConditionVariableCheck.cs 92.85% 0 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

@vaceslav
vaceslav merged commit 9cd92bb into main Sep 27, 2026
12 checks passed
@vaceslav
vaceslav deleted the feat/validation-missing-condition-vars branch September 27, 2026 13:33
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