Skip to content

Fix: Variable name can start with a digit - #43

Open
ᡥᠠᡳᡤᡳᠶᠠ ᡥᠠᠯᠠ·ᠨᡝᡴᠣ 猫 (OverflowCat) wants to merge 1 commit into
microsoft:mainfrom
OverflowCat:main
Open

Fix: Variable name can start with a digit#43
ᡥᠠᡳᡤᡳᠶᠠ ᡥᠠᠯᠠ·ᠨᡝᡴᠣ 猫 (OverflowCat) wants to merge 1 commit into
microsoft:mainfrom
OverflowCat:main

Conversation

@OverflowCat

According to the spec, an <ident-token> cannot start with a digit. However, for variables that begin with a double-hyphen --, the name following it CAN start with a digit.

For example, --7-grid-columns-minus-last-gap (found by yzqzss (@yzqzss) in GitHub's landing page) is a completely valid variable name.

Current grammar does not properly highlight it:

This change to the lexical grammar was made in 2014, although they didn't mention it clearly:

Change the definition of ident-like tokens to allow "--" to start an ident. As part of this, rearrange the ordering of the clauses in the "-" step of consume a token so that s are recognized as such instead of becoming a -- .

The old definition:

Co-authored-by: yzqzss <30341059+yzqzss@users.noreply.github.com>
@OverflowCat

@microsoft-github-policy-service agree

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the detailed description and fix!
LGTM

@yzqzss

Copy link
Copy Markdown

@microsoft-github-policy-service agree

Kristofer Baxter (kristofer-baxter) added a commit to kristofer-baxter/vscode-css that referenced this pull request Aug 11, 2026
Leave the four scroll-animation properties to microsoft#32 and accept digit-prefixed @Property names consistently with the valid custom-property syntax documented in microsoft#43.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Kristofer Baxter (kristofer-baxter) added a commit to kristofer-baxter/vscode-css that referenced this pull request Aug 27, 2026
Add grammar and regression coverage for modern at-rules, functions,
properties, selectors, and media queries. Include `@container`
coverage for the gap first identified in microsoft#15, and accept digit-prefixed
`@property` names consistently with microsoft#43.

Bound the scope leak from unclosed `@container` and `@scope` preludes
with `(?=\{[^)]*$)`. Recover at `{` only when no `)` follows on the
same line, preserving legal balanced blocks in declaration values.
Do not use `;` as a bail-out: `<general-enclosed>` permits top-level
semicolons through `<any-value>`, and legal preludes may span lines.

Leave `animation-timeline`, `animation-range`, `animation-range-start`,
and `animation-range-end` entirely to microsoft#32.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Kristofer Baxter (kristofer-baxter) added a commit to kristofer-baxter/vscode-css that referenced this pull request Aug 27, 2026
Add grammar and regression coverage for modern at-rules, functions,
properties, selectors, and media queries. Include `@container`
coverage for the gap first identified in microsoft#15, and accept digit-prefixed
`@property` names consistently with microsoft#43.

Dedicated prelude regions end only at `)`, so an unclosed parenthesis
would run to end of file where the generic at-rule header on main
recovers at the first `{`. Guard every parenthesised region reachable
inside a prelude with `(?=\{[^)]*$)`: recover at `{` only when no `)`
follows on the same line, preserving legal balanced blocks in
declaration values. Guarding only the outermost regions is not enough,
because an outer `end` cannot be evaluated while an inner rule is
active. Do not use `;` as a bail-out: `<general-enclosed>` permits
top-level semicolons through `<any-value>`, and legal preludes may
span lines.

Leave `animation-timeline`, `animation-range`, `animation-range-start`,
and `animation-range-end` entirely to microsoft#32.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Kristofer Baxter (kristofer-baxter) added a commit to kristofer-baxter/vscode-css that referenced this pull request Aug 27, 2026
Add grammar and regression coverage for modern at-rules, functions,
properties, selectors, and media queries. Include `@container`
coverage for the gap first identified in microsoft#15, and accept digit-prefixed
`@property` names consistently with microsoft#43.

Dedicated prelude regions end only at `)`, so an unclosed parenthesis
would run to end of file where the generic at-rule header on main
recovers at the first `{`. Guard the parenthesised regions reachable
inside a prelude with `(?=\{[^)]*$)`: recover at `{` only when no `)`
follows on the same line, preserving legal balanced blocks in
declaration values. Guarding only the outermost regions is not enough,
because an outer `end` cannot be evaluated while an inner rule is
active. Do not use `;` as a bail-out: `<general-enclosed>` permits
top-level semicolons through `<any-value>`, and legal preludes may
span lines.

Leave `var()` unguarded. A `var()` fallback may legally contain a
balanced curly block spanning lines, and guarding it truncated that
value; main does not recover an unclosed `var(` either, so the
exception gives up nothing main provided.

Give the `:lang()` and `:dir()` string rules the end-of-line fallback
the shared `#string` rule already uses, so an unterminated language
range no longer runs past its line.

Leave `animation-timeline`, `animation-range`, `animation-range-start`,
and `animation-range-end` entirely to microsoft#32.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Kristofer Baxter (kristofer-baxter) added a commit to kristofer-baxter/vscode-css that referenced this pull request Aug 27, 2026
Add grammar and regression coverage for modern at-rules, functions,
properties, selectors, and media queries. Include `@container`
coverage for the gap first identified in microsoft#15, and accept digit-prefixed
`@property` names consistently with microsoft#43.

Dedicated prelude regions end only at `)`, so an unclosed parenthesis
would run to end of file where the generic at-rule header on main
recovers at the first `{`. Guard the parenthesised regions reachable
inside a prelude with `(?=\{[^)]*$)`: recover at `{` only when no `)`
follows on the same line, preserving legal balanced blocks in
declaration values. Guarding only the outermost regions is not enough,
because an outer `end` cannot be evaluated while an inner rule is
active. Do not use `;` as a bail-out: `<general-enclosed>` permits
top-level semicolons through `<any-value>`, and legal preludes may
span lines.

Leave `var()` unguarded. A `var()` fallback may legally contain a
balanced curly block spanning lines, and guarding it truncated that
value; main does not recover an unclosed `var(` either, so the
exception gives up nothing main provided.

Give the `:lang()` and `:dir()` string rules the end-of-line fallback
the shared `#string` rule already uses, so an unterminated language
range no longer runs past its line.

Leave `animation-timeline`, `animation-range`, `animation-range-start`,
and `animation-range-end` entirely to microsoft#32.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Kristofer Baxter (kristofer-baxter) added a commit to kristofer-baxter/vscode-css that referenced this pull request Aug 27, 2026
Add grammar and regression coverage for modern at-rules, functions,
properties, selectors, and media queries. Include `@container`
coverage for the gap first identified in microsoft#15, and accept digit-prefixed
`@property` names consistently with microsoft#43.

Dedicated prelude regions end only at `)`, so an unclosed parenthesis
would run to end of file where the generic at-rule header on main
recovers at the first `{`. Guard the parenthesised regions reachable
inside a prelude with `(?=\{[^)]*$)`: recover at `{` only when no `)`
follows on the same line, preserving legal balanced blocks in
declaration values. Guarding only the outermost regions is not enough,
because an outer `end` cannot be evaluated while an inner rule is
active. Do not use `;` as a bail-out: `<general-enclosed>` permits
top-level semicolons through `<any-value>`, and legal preludes may
span lines.

Leave `var()` unguarded. A `var()` fallback may legally contain a
balanced curly block spanning lines, and guarding it truncated that
value; main does not recover an unclosed `var(` either, so the
exception gives up nothing main provided.

Give the `:lang()` and `:dir()` string rules the end-of-line fallback
the shared `#string` rule already uses, so an unterminated language
range no longer runs past its line.

Leave `animation-timeline`, `animation-range`, `animation-range-start`,
and `animation-range-end` entirely to microsoft#32.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Kristofer Baxter (kristofer-baxter) added a commit to kristofer-baxter/vscode-css that referenced this pull request Aug 28, 2026
Add grammar and regression coverage for modern at-rules, functions,
properties, selectors, and media queries. Include `@container`
coverage for the gap first identified in microsoft#15, and accept digit-prefixed
`@property` names consistently with microsoft#43.

Dedicated prelude regions end only at `)`, so an unclosed parenthesis
would run to end of file where the generic at-rule header on main
recovers at the first `{`. Guard the parenthesised regions reachable
inside a prelude so they recover at `{` only when the rest of the line
does not close the parenthesis, preserving legal balanced blocks in
declaration values. The test is lexical rather than a plain `[^)]*`,
because a `)` inside a comment, string or escape does not close
anything: without that, `@container (width > 1px{ /* ) */` stayed open
where main recovered. Guarding only the outermost regions is not
enough, because an outer `end` cannot be evaluated while an inner rule
is active. Do not use `;` as a bail-out: `<general-enclosed>` permits
top-level semicolons through `<any-value>`, and legal preludes may
span lines.

Leave `var()` and custom function calls unguarded. Both are
declaration values, and `<declaration-value>` admits a balanced curly
block that legally spans lines, as in `--x: --foo({ ... });`. The legal
`--foo({` and the malformed `--foo(a{` are indistinguishable within a
single line, so recovering there would cost legal CSS that main scopes
correctly. Main does not recover an unclosed `var(` either.

Give the `:lang()` string rules the end-of-line fallback
the shared `#string` rule already uses, so an unterminated language
range no longer runs past its line.

Leave `animation-timeline`, `animation-range`, `animation-range-start`,
and `animation-range-end` entirely to microsoft#32.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Kristofer Baxter (kristofer-baxter) added a commit to kristofer-baxter/vscode-css that referenced this pull request Aug 28, 2026
Add grammar and regression coverage for modern at-rules, functions,
properties, selectors, and media queries. Include `@container`
coverage for the gap first identified in microsoft#15, and accept digit-prefixed
`@property` names consistently with microsoft#43.

Dedicated prelude regions end only at `)`, so an unclosed parenthesis
would run to end of file where the generic at-rule header on main
recovers at the first `{`. Guard the parenthesised regions reachable
inside a prelude so they recover at `{` only when the rest of the line
does not close the parenthesis, preserving legal balanced blocks in
declaration values. The test is lexical rather than a plain `[^)]*`,
because a `)` inside a comment, string or escape does not close
anything: without that, `@container (width > 1px{ /* ) */` stayed open
where main recovered. Guarding only the outermost regions is not
enough, because an outer `end` cannot be evaluated while an inner rule
is active. Do not use `;` as a bail-out: `<general-enclosed>` permits
top-level semicolons through `<any-value>`, and legal preludes may
span lines.

Leave `var()` and custom function calls unguarded. Both are
declaration values, and `<declaration-value>` admits a balanced curly
block that legally spans lines, as in `--x: --foo({ ... });`. The legal
`--foo({` and the malformed `--foo(a{` are indistinguishable within a
single line, so recovering there would cost legal CSS that main scopes
correctly. Main does not recover an unclosed `var(` either.

Give the `:lang()` string rules the end-of-line fallback
the shared `#string` rule already uses, so an unterminated language
range no longer runs past its line.

Leave `animation-timeline`, `animation-range`, `animation-range-start`,
and `animation-range-end` entirely to microsoft#32.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Kristofer Baxter (kristofer-baxter) added a commit to kristofer-baxter/vscode-css that referenced this pull request Aug 28, 2026
Add grammar and regression coverage for modern at-rules, functions,
properties, selectors, and media queries. Include `@container`
coverage for the gap first identified in microsoft#15, and accept digit-prefixed
`@property` names consistently with microsoft#43.

Dedicated prelude regions end only at `)`, so an unclosed parenthesis
would run to end of file where the generic at-rule header on main
recovers at the first `{`. Guard the parenthesised regions reachable
inside a prelude so they recover at `{` only when the rest of the line
does not close the parenthesis, preserving legal balanced blocks in
declaration values. The test is lexical rather than a plain `[^)]*`,
because a `)` inside a comment, string or escape does not close
anything: without that, `@container (width > 1px{ /* ) */` stayed open
where main recovered. Guarding only the outermost regions is not
enough, because an outer `end` cannot be evaluated while an inner rule
is active. Do not use `;` as a bail-out: `<general-enclosed>` permits
top-level semicolons through `<any-value>`, and legal preludes may
span lines.

Leave `var()` and custom function calls unguarded. Both are
declaration values, and `<declaration-value>` admits a balanced curly
block that legally spans lines, as in `--x: --foo({ ... });`. The legal
`--foo({` and the malformed `--foo(a{` are indistinguishable within a
single line, so recovering there would cost legal CSS that main scopes
correctly. Main does not recover an unclosed `var(` either.

Give the `:lang()` string rules the end-of-line fallback
the shared `#string` rule already uses, so an unterminated language
range no longer runs past its line.

Leave `animation-timeline`, `animation-range`, `animation-range-start`,
and `animation-range-end` entirely to microsoft#32.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Kristofer Baxter (kristofer-baxter) added a commit to kristofer-baxter/vscode-css that referenced this pull request Aug 31, 2026
Add grammar and regression coverage for modern at-rules, functions,
properties, selectors, and media queries. Include `@container` coverage
for the gap first identified in PR microsoft#15, and accept
digit-prefixed `@property` names consistently with PR microsoft#43.

Dedicated prelude regions end only at `)`, so an unclosed parenthesis
would run to end of file where the generic at-rule header on main
recovers at the first `{`. Guard the parenthesised regions reachable
inside a prelude so they recover at `{` only when the rest of the line
does not close the parenthesis, preserving legal balanced blocks in
declaration values. The test is lexical rather than a plain `[^)]*`,
because a `)` inside a comment, string or escape does not close
anything: without that, `@container (width > 1px{ /* ) */` stayed open
where main recovered. The test also accepts an incomplete trailing
escape, both bare and inside an unterminated string, because a line
ending in an odd number of backslashes otherwise matches no alternative
and the newline-escape rule holds the prelude open. Guarding only the
outermost regions is not enough, because an outer `end` cannot be
evaluated while an inner rule is active. Do not use `;` as a bail-out:
`<general-enclosed>` permits top-level semicolons through `<any-value>`,
and legal preludes may span lines.

Leave `var()` and custom function calls unguarded. Both are declaration
values, and `<declaration-value>` admits a balanced curly block that
legally spans lines, as in `--x: --foo({ ... });`. The legal `--foo({`
and the malformed `--foo(a{` are indistinguishable within a single line,
so recovering there would cost legal CSS that main scopes correctly.
Main does not recover an unclosed `var(` either.

Add `#condition-string` to the `@media` and `@supports` condition
regions. The bail-out only inspects text from the candidate `{` onwards,
so with no string rule active it read the closing quote of `(future:
"a{b")` as an opening one, took the real `)` for shielded, and opened
the body at the brace inside the string. `@container` keeps no string
rule, because there an unterminated string would instead shield a
malformed `{` from the bail-out; that case tokenizes as it already does
on main.

`#condition-string` is a condition-local copy of `#string` rather than
`#string` itself. It differs in one respect: its newline escape ends at
`^` instead of the shared rule's `^(?<!\G)`, which cannot match while
the condition is still open and so swallowed the rest of the stylesheet
after a legal `@media (future: "a{\` continuation. Keeping the copy
local leaves string tokenization everywhere else byte-for-byte as it is
on main.

Give the `:lang()` string rules the end-of-line fallback the shared
`#string` rule already uses, so an unterminated language range no longer
runs past its line.

Leave `animation-timeline`, `animation-range`, `animation-range-start`,
and `animation-range-end` entirely to PR microsoft#32.
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.

4 participants