Fix CSS highlighting desync when a nested rule precedes a custom property - #327821
Closed
srikanthananthula63053 wants to merge 2 commits into
Closed
Fix CSS highlighting desync when a nested rule precedes a custom property#327821srikanthananthula63053 wants to merge 2 commits into
srikanthananthula63053 wants to merge 2 commits into
Conversation
…erty
The CSS TextMate grammar had no pattern for nested rule blocks inside a
property list, so a bare `}` belonging to a nested rule (e.g. `.b { ... }`)
would be matched by the enclosing block's own `end` pattern and close it
prematurely. Anything after the nested rule then fell back to raw
`meta.selector.css` text with no property/value coloring.
Teach `rule-list-innards` to recognize nested selectors and re-enter the
grammar (`$self`) to open a properly balanced nested scope, and tighten
`selector`'s begin pattern so it only matches an actual nested rule
(something followed by `{`) rather than an ordinary declaration.
Verified by tokenizing the grammar directly with vscode-textmate/
vscode-oniguruma, and by diffing full-file tokenization of existing CSS
in the repo before/after: no unintended differences, and one real,
previously mis-highlighted nested rule in chat.css is now fixed.
Fixes #327799
srikanthananthula63053
force-pushed
the
fix-327799-css-nesting-highlight
branch
from
July 29, 2026 07:35
b0129e3 to
0b57f16
Compare
Adds test-css-nesting.css to the vscode-colorize-tests fixtures, covering the exact scenario from microsoft#327799 (a nested rule followed by a custom property) plus related nesting forms: custom property before a nested rule, pseudo-class nesting with a trailing custom property, and a nested rule inside @media. The checked-in colorize-results snapshot locks in the fixed tokenization (e.g. `--c` after a nested rule now scopes as variable.css instead of falling back to unstyled selector text), so a future regression in the grammar will fail this test.
Member
|
Thank you for the PR, but we pull our css grammar from https://github.com/microsoft/vscode-css, so all PRs should go there. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
#a { .b { gap: 1px; } --c: 1px; }.rule-list-innardshad no pattern for a nested rule block, so the enclosing block's ownendpattern (}) matched the first}encountered — even one belonging to a nested rule — closing the outermeta.property-list.cssscope prematurely. Everything after the nested rule then fell back to raw, uncoloredmeta.selector.csstext.rule-list-innardsnow recognizes nested selectors via#selector, andrule-listre-enters the grammar ($self) so a nested{ ... }opens its own properly balanced scope.selector's begin pattern is tightened (with negative lookaheads) so it only matches when a selector is actually followed by{, not an ordinaryproperty: value;declaration, since it now also runs inside a property list where it competes with declaration parsing.Test plan
vscode-textmate+vscode-onigurumadirectly against the grammar file — confirmed the nested rule and the trailing custom property both highlight correctly, with no scope leaking past the nested block's own closing brace.--cbefore.b { ... }) — still correct, and no longer relies on incidental brace-position luck.src/vs/workbench/contrib/chat/browser/widget/media/chat.css(4600+ lines) — the only differences were at genuine nested-rule sites, including an already-shipping nested rule (.codicon { font-size: inherit; }) that this same bug was silently mis-highlighting; it now renders correctly, and the file continues to tokenize cleanly through EOF afterward.&:hover), tag-name nesting, attribute-selector nesting, deeply nested rules, nested@media, andvar()values — all unaffected/correct.extensions/vscode-colorize-tests/test/colorize-fixtures/test-css-nesting.css, covering the exact issue repro plus custom-property-before-nested-rule, pseudo-class nesting with a trailing custom property, and a nested rule inside@media. Ran vianpm run test-extension -- -l vscode-colorize-tests --grep test-css-nesting— passing, with the checked-incolorize-results/colorize-tree-sitter-resultssnapshots locking in the corrected tokenization (e.g.--cafter the nested rule now scopes asvariable.cssinstead of falling back to unstyled selector text). Any future regression in this grammar will now fail this test.Files Changed
extensions/css/syntaxes/css.tmLanguage.json— grammar fix (see Root Cause above).extensions/vscode-colorize-tests/test/colorize-fixtures/test-css-nesting.css— new regression fixture.extensions/vscode-colorize-tests/test/colorize-results/test-css-nesting_css.jsonand.../colorize-tree-sitter-results/test-css-nesting_css.json— checked-in expected tokenization snapshots for the new fixture.