This note documents a lightweight process for triaging syntax-highlighting bugs in workflow files and turning them into fixture-based regression tests.
This is for TextMate grammar / tokenization issues in:
language/syntaxes/yaml.tmLanguage.jsonlanguage/syntaxes/expressions.tmGrammar.json- workflow syntax injection grammars (for embedded languages)
This is not the right path for:
- parser/validation diagnostics from language services
- schema/completion issues
- runtime extension behavior
- Reproduce in
GitHub Actions Workflowlanguage mode. - Run
Developer: Inspect Editor Tokens and Scopes. - Check whether the bug is:
- wrong token scopes/colors (grammar bug)
- a diagnostic/problem message (language service/parser bug)
- Identify likely grammar file:
- inline
${{ }}/if:expression behavior:language/syntaxes/expressions.tmGrammar.json - general YAML tokenization/comments/keys/scalars:
language/syntaxes/yaml.tmLanguage.json - embedded JS/shell/etc: injection grammar(s)
- inline
- Add a fixture and a focused regression test before patching.
If the issue is syntax highlighting, ask for:
- a minimal workflow snippet (
.yml) - exact line/token that looks wrong
- screenshot (optional but helpful)
- token inspector output for the wrong token (
textmate scopes) - expected behavior (what scope/color should have happened)
Ideally, contributors can include a minimal repro snippet that can be copied directly into a fixture file.
Shared helpers live in:
src/workflow/syntax/syntax-test-utils.ts
Current tests live in:
src/workflow/syntax/*.test.ts
Current fixture files live in:
src/workflow/syntax/fixtures/
The helpers are intentionally lightweight and focus on grammar-regression behavior (not VS Code integration tests).
readJson(relativePath)- Use to load grammar JSON files from
language/syntaxes/.
- Use to load grammar JSON files from
readFixture(relativePath)- Use to load YAML fixture files from
src/workflow/syntax/fixtures/.
- Use to load YAML fixture files from
analyzeSingleOuterEmbeddedBlockFixture(...)- Use when grammar has one outer context and one embedded block rule inside it (for example
github-script+with.script).
- Use when grammar has one outer context and one embedded block rule inside it (for example
analyzeTopLevelInjectionContexts(...)- Use when grammar has multiple top-level included contexts (for example
run+shellper-shell contexts).
- Use when grammar has multiple top-level included contexts (for example
findGithubActionsInlineExpression(line)- Use in expression-regression tests that need to ensure
${{ ... }}does not terminate on}}inside quoted strings (for example#223).
- Use in expression-regression tests that need to ensure
Use behavior-based, kebab-case fixture names:
- format:
<behavior>.yml - examples:
if-comment-after-string.ymlexpression-nested-braces.ymlrun-shell-embedded.yml
Avoid issue-number-only names in fixture filenames. Issue references should live in test comments or fixture comments.
- Add a minimal fixture file under
src/workflow/syntax/fixtures/ - Add/extend a Jest test in
src/workflow/syntax/*.test.ts - Keep assertions narrow (what should be embedded, what should not be consumed, header/body boundaries, etc.)
- Run
npm test
Issue type:
- likely grammar tokenization bug in
language/syntaxes/expressions.tmGrammar.json - symptom:
if: ... 'string' # commentdoes not highlight the comment as a YAML comment
Suggested test plan:
-
Add a fixture with lines like:
jobs: test: if: matrix.os != 'macos-latest' # Cache causes errors on macOS
-
Add a focused test for the
if-expressionrule behavior inexpressions.tmGrammar.json -
Verify the expression matcher does not swallow the trailing comment, while preserving
#inside quoted strings
Note:
- This kind of issue may need a new small helper in
syntax-test-utils.tsfor line/capture-level grammar matching, in addition to the embedded-block helpers already present.
For syntax-highlighting bugs in this area, contributors can submit:
- A fixture file in
src/workflow/syntax/fixtures/ - A failing Jest assertion in
src/workflow/syntax/*.test.ts - A short comment linking the issue number and describing the expected scopes/behavior
That gives maintainers a reproducible regression case even before a fix is implemented.