Skip to content

fix(describe): quote and escape MDL strings in one place (mendixlabs/mxcli#1006) - #348

Merged
ako merged 2 commits into
mainfrom
fix/workflow-describe-quote-doubling
Aug 31, 2026
Merged

fix(describe): quote and escape MDL strings in one place (mendixlabs/mxcli#1006)#348
ako merged 2 commits into
mainfrom
fix/workflow-describe-quote-doubling

Conversation

@ako

@ako ako commented Aug 31, 2026

Copy link
Copy Markdown
Owner

Fixes mendixlabs/mxcli#1006. DESCRIBE WORKFLOW emitted single-quoted payloads without doubling the quotes inside them, so its own output was a syntax error:

targeting users xpath '[System.UserRoles = '[%UserRole_Banker%]']'
  -> line 6:48 mismatched input '[%UserRole_Banker%]' expecting ';'

The string terminates at = ', and every later statement cascades — so describe output could not be fed back to check or exec for any workflow with an XPath-targeted user task.

The reported case is one of six

The emitters wrote fmt.Sprintf("… '%s'", v): quotes in the format string, escaping (when present) as a separate statement at the call site. That's one thing to remember per site, and 6 of 23 sites didn't:

site payload
targeting users xpath reported
targeting groups xpath same emitter, unreported
user task caption Manager's review — no XPath needed
workflow-level due date the task-level one, two functions away, does escape
outcome value ×2 Won't fix

The fix

mdlQuoted(s) returns the complete literal, quotes included, so an unescaped emit cannot be written by omission. All 23 sites now go through it; the file has zero remaining '%s' and zero remaining inline ReplaceAll.

Tests

Four new tests, all verified to fail against the original emitters:

--- FAIL: TestDescribeWorkflow_XPathUserSourceReparses
    mismatched input '[%UserRole_Banker%]' expecting ';'     <- the reported error, exactly
--- FAIL: TestDescribeWorkflow_XPathGroupSourceReparses
--- FAIL: TestDescribeWorkflow_ApostropheInCaptionAndOutcomeReparses
    line 4:29 mismatched input 's' expecting ';'
--- FAIL: TestDescribers_HaveNoHandRolledStringLiterals
    cmd_workflows.go:201, :207, :222, :247, :273, :327, :342, :345, :374, :427 …

Two deliberate choices:

  • Assert the emitted MDL parses, not that it contains a particular escape. A substring assertion has to encode the very escape under test, so it can pass for the wrong reason. The harness wraps the fragment in a minimal create workflow … end workflow; and runs visitor.Build. It routes through formatWorkflowActivities rather than the per-activity formatter, because the statement terminator is appended by the caller — calling the formatter directly produces unparseable output for reasons unrelated to the bug.
  • A source scan for '%s' alongside the emit tests. Emit tests only cover the positions the test constructs; the real failure mode is a new site added later. mdlQuoted carrying its own quotes is what makes that scan sound rather than a style rule.

Two sibling issues from the same reporter are separate PRs: mendixlabs/mxcli#1007 (annotations) and #1005 (jump targets).

🤖 Generated with Claude Code

DESCRIBE WORKFLOW emitted single-quoted payloads without doubling the
quotes inside them, so its own output was a syntax error:

  targeting users xpath '[System.UserRoles = '[%UserRole_Banker%]']'
  -> line 6:48 mismatched input '[%UserRole_Banker%]' expecting ';'

The string terminates at `= '` and every later statement cascades, so
DESCRIBE WORKFLOW output could not be fed back to check or exec for any
workflow with an XPath-targeted user task.

The reported case is one of six. The emitters wrote

  fmt.Sprintf("... '%s'", v)

with the quotes in the format string and the escaping, when present, as
a separate statement at the call site — one thing to remember per site,
and 6 of 23 sites did not do it: both `targeting … xpath` variants, the
user task caption, the workflow-level due date (the task-level one two
functions away does escape), and both outcome values. The caption needs
no XPath to reach: `Manager's review`.

mdlQuoted(s) now returns the complete literal, quotes included, so an
unescaped emit cannot be written by omission, and all 23 sites go
through it.

Tests assert the emitted MDL PARSES rather than that it contains a
particular escape — a substring assertion would encode the escape under
test and pass for the wrong reason. A source scan guards the class,
because emit tests only cover the positions they construct and the real
failure mode is a new site added later.

Reported as mendixlabs#1006 (the XPath variant only).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@ako
ako merged commit b2371f9 into main Aug 31, 2026
13 of 14 checks passed
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.

1 participant