What
The TextMate grammar in docs/common/src/utils/slint.tmLanguage.json (also served as editors/vscode/slint.tmLanguage.json) has a callback-setup rule whose 2nd pattern greedily begins on any identifier( and only ends at )\s*=>. As a result, any plain function call written with an unqualified name — e.g. max(...), min(...), mod(...), debug(...) at top-level of a property body — opens the callback-setup scope and never closes it, swallowing every following token to EOF.
Dotted function names (Math.max(...), TimeUtil.foo(...)) are not affected because the rule's identifier class [a-zA-Z_][a-zA-Z0-9_-]* excludes ., so they fall through to function-call.
Repro
component Foo inherits Rectangle {
property <float> a:
max(1, 2);
property <length> next: 5px; // not highlighted
VerticalLayout { ... } // not highlighted
}
After max(, property and VerticalLayout lose their scopes. Confirmed against slint.tmLanguage.json from master (and the published slint-nightly VSCode/Cursor extension 2026.4.2500) using vscode-textmate + vscode-oniguruma: the rule stack pushed by max( is never popped.
Cause
"callback-setup": {
"patterns": [
{ "match": "(?<!-)([a-zA-Z_][a-zA-Z0-9_-]*)\\s*=>", ... },
{
"begin": "(?<!-)([a-zA-Z_][a-zA-Z0-9_-]*)\\s*\\(",
"end": "\\)\\s*=>",
...
}
]
}
The begin pattern fires on every id( but only ends on )\s*=>. For ordinary function calls the => never arrives.
Suggested fix
Add a positive lookahead that requires => after the closing paren before entering the scope. Slint callback bindings have flat parameter lists (just identifiers + commas), so a single-line, no-nested-paren lookahead is sufficient:
"begin": "(?<!-)([a-zA-Z_][a-zA-Z0-9_-]*)(?=\\s*\\([^()]*\\)\\s*=>)\\s*\\("
Verified locally: max(...), min(...), debug(...) etc. now fall through to function-call, while clicked => { ... } and moved(x, y) => { ... } callback bindings still highlight correctly.
Happy to send this as a PR if useful.
Side note: @rust-attr(...) has no grammar rule either
Tangentially, while looking at this, I noticed the grammar has no rule for @rust-attr(...), so those annotations render as plain text. PR #11569 also adds a rust-attr / rust-attr-body rule pair that scopes the whole annotation under meta.attribute.rust-attr.slint (with sensible sub-scopes for type names, identifiers, strings, ::, =, , and nested parens). Happy to split that into its own PR if you'd prefer to evaluate the two changes separately.
Disclosure: this issue and the accompanying PR #11569 were authored by Claude Opus 4.7 (Anthropic) running inside Cursor, on behalf of @1Mr-Newton. The diagnosis, suggested fix, tokenizer-based verification, and write-up were all produced by the model; @1Mr-Newton reviewed before filing. Flagging up-front so triage can apply whatever extra scrutiny is preferred for AI-assisted reports.
What
The TextMate grammar in
docs/common/src/utils/slint.tmLanguage.json(also served aseditors/vscode/slint.tmLanguage.json) has acallback-setuprule whose 2nd pattern greedily begins on anyidentifier(and only ends at)\s*=>. As a result, any plain function call written with an unqualified name — e.g.max(...),min(...),mod(...),debug(...)at top-level of a property body — opens the callback-setup scope and never closes it, swallowing every following token to EOF.Dotted function names (
Math.max(...),TimeUtil.foo(...)) are not affected because the rule's identifier class[a-zA-Z_][a-zA-Z0-9_-]*excludes., so they fall through tofunction-call.Repro
After
max(,propertyandVerticalLayoutlose their scopes. Confirmed againstslint.tmLanguage.jsonfrommaster(and the publishedslint-nightlyVSCode/Cursor extension2026.4.2500) usingvscode-textmate+vscode-oniguruma: the rule stack pushed bymax(is never popped.Cause
The begin pattern fires on every
id(but only ends on)\s*=>. For ordinary function calls the=>never arrives.Suggested fix
Add a positive lookahead that requires
=>after the closing paren before entering the scope. Slint callback bindings have flat parameter lists (just identifiers + commas), so a single-line, no-nested-paren lookahead is sufficient:Verified locally:
max(...),min(...),debug(...)etc. now fall through tofunction-call, whileclicked => { ... }andmoved(x, y) => { ... }callback bindings still highlight correctly.Happy to send this as a PR if useful.
Side note:
@rust-attr(...)has no grammar rule eitherTangentially, while looking at this, I noticed the grammar has no rule for
@rust-attr(...), so those annotations render as plain text. PR #11569 also adds arust-attr/rust-attr-bodyrule pair that scopes the whole annotation undermeta.attribute.rust-attr.slint(with sensible sub-scopes for type names, identifiers, strings,::,=,,and nested parens). Happy to split that into its own PR if you'd prefer to evaluate the two changes separately.