Skip to content

Follow-up to #4462: migrate remaining @var fixtures, DRY the prelude bare-@var scan, add warnings coverage#4469

Merged
matthew-dean merged 3 commits into
less:masterfrom
matthew-dean:feat/deprecate-non-value-variable-refs
Jul 18, 2026
Merged

Follow-up to #4462: migrate remaining @var fixtures, DRY the prelude bare-@var scan, add warnings coverage#4469
matthew-dean merged 3 commits into
less:masterfrom
matthew-dean:feat/deprecate-non-value-variable-refs

Conversation

@matthew-dean

@matthew-dean matthew-dean commented Jul 17, 2026

Copy link
Copy Markdown
Member

Follow-up to #4462 (bare-@variable at-rule deprecation). Four pieces:

  1. Fixture migrationfeat: deprecate bare @variable in non-value at-rule positions #4462 left two fixtures on the bare form (layer.less, import-reference.less); migrated to @{…} (byte-identical render).

  2. Warnings-assertion coverage (new) — less.js asserted errors (tests-error/*.txt) but never that warnings fire, so deprecations were unguarded. Adds testWarnings() capturing logger warnings and asserting each render-reachable one, incl. the prelude semantics (bar[@v]→warns, (x:@v)→no warn). Warnings are now suppressed from normal output (LESS_TEST_SHOW_WARNINGS=1 to see them). Documented gaps: variable-in-unknown-value (only fires for an inconsistent bracket edge), property-in-unknown-value (not render-reachable), math-always/dumpLineNumbers (registered but never emitted).

  3. DRY the prelude bare-@var detection — replaced the standalone hasTopLevelBareVariable() (which re-scanned text $parseUntil had already walked, with a hand-rolled ()-only counter and no string/comment handling) by folding an opt-in detectBareVar into $parseUntil's single pass (it already skips strings/comments and tracks brackets; $parseUntil has one caller). Guarded green-to-green by the new tests.

  4. Lockfile repairmaster's pnpm-lock.yaml had a dangling minimatch: 3.1.2 edge failing --frozen-lockfile for every PR; repinned to 3.1.5.

Full grunt test green; all 7 CI jobs pass.

@dosubot dosubot Bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Jul 17, 2026
@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Less parser fallback deprecation handling was adjusted, integration coverage was added for at-rule prelude variable warnings, and test fixtures now interpolate variables in @keyframes and @layer names.

Changes

At-rule interpolation and deprecation parsing

Layer / File(s) Summary
Parser deprecation handling
packages/less/lib/less/parser/parser.js
Removes top-level bare-variable scanning and suppresses the unknown-value variable warning when variable deprecations are enabled.
At-rule prelude warning tests
packages/less/test/less-test.js, packages/less/test/index.js
Adds asynchronous warning-count assertions for at-rule preludes and runs them in the main test sequence.
Structural at-rule fixture updates
packages/test-data/tests-unit/import/import/import-reference.less, packages/test-data/tests-unit/layer/layer.less
Keyframe and layer names now use Less interpolation syntax; the keyframe block formatting is expanded.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

  • less/less.js#4462: Related parser and test changes for variable deprecation warnings in at-rule preludes.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: fixture migration, parser scan cleanup, and added warning coverage.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Jul 17, 2026

Copy link
Copy Markdown

Greptile Summary

This PR completes the bare-variable at-rule migration and adds warning coverage. The main changes are:

  • Migrates the remaining @keyframes and @layer fixtures to interpolation syntax.
  • Detects bare at-rule variables during the permissive parser scan.
  • Adds assertions for render-reachable warnings and suppresses routine warning output.
  • Repairs the dangling minimatch lockfile reference.

Confidence Score: 5/5

This looks safe to merge.

  • No blocking issues found in the changed code.

Reviews (8): Last reviewed commit: "refactor(parser): fold at-rule prelude b..." | Re-trigger Greptile

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/less/lib/less/parser/parser.js`:
- Around line 118-132: Update hasTopLevelBareVariable to accept the incoming
parenthesis depth and return both the updated depth and whether a top-level bare
variable was found. In permissiveValue, initialize parenDepth before iterating
parsed fragments, pass it into hasTopLevelBareVariable for each unquoted item,
retain the returned depth for the next fragment, and use the returned found flag
for deprecation warnings.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6119c9cc-611f-4b83-a8c4-c4a23aa61e21

📥 Commits

Reviewing files that changed from the base of the PR and between 4d6e67e and 31ee756.

📒 Files selected for processing (11)
  • packages/less/lib/less/deprecation.js
  • packages/less/lib/less/parser/parser.js
  • packages/test-data/tests-config/at-rules-compressed-evaluation/at-rules-compressed-evaluation.less
  • packages/test-data/tests-unit/at-rule-variable-deprecated/at-rule-variable-deprecated.css
  • packages/test-data/tests-unit/at-rule-variable-deprecated/at-rule-variable-deprecated.less
  • packages/test-data/tests-unit/container/container.less
  • packages/test-data/tests-unit/import/import/import-reference.less
  • packages/test-data/tests-unit/layer/layer.less
  • packages/test-data/tests-unit/media/media.less
  • packages/test-data/tests-unit/permissive-parse/permissive-parse.less
  • packages/test-data/tests-unit/variables-in-at-rules/variables-in-at-rules.less

Comment thread packages/less/lib/less/parser/parser.js Outdated
@matthew-dean
matthew-dean force-pushed the feat/deprecate-non-value-variable-refs branch from 31ee756 to 2c89713 Compare July 17, 2026 23:33
@matthew-dean matthew-dean changed the title feat: deprecate bare @variable in non-value at-rule positions test: migrate remaining bare @variable at-rule fixtures to @{variable} + repair lockfile Jul 17, 2026
@dosubot dosubot Bot added size:XS This PR changes 0-9 lines, ignoring generated files. and removed size:L This PR changes 100-499 lines, ignoring generated files. labels Jul 17, 2026
Follow-up to less#4462, which deprecated bare @variable in non-value at-rule
positions and migrated most fixtures to @{variable} but left two feature
fixtures on the bare form:
  - tests-unit/layer/layer.less             @layer @layer-name
  - tests-unit/import/import/import-reference.less  @Keyframes @keyframeName
Migrated to @{layer-name} / @{keyframeName} (byte-identical render).

Also repairs pnpm-lock.yaml: master had a dangling `minimatch: 3.1.2`
dependency edge with no package entry (bad-merge artifact), so
`pnpm install --frozen-lockfile` failed for every PR. Repinned to the
resolved 3.1.5 already present; no dependency version changes.
@matthew-dean
matthew-dean force-pushed the feat/deprecate-non-value-variable-refs branch from 2c89713 to 92c62bb Compare July 17, 2026 23:41
@dosubot dosubot Bot added size:M This PR changes 30-99 lines, ignoring generated files. and removed size:XS This PR changes 0-9 lines, ignoring generated files. labels Jul 18, 2026
@matthew-dean matthew-dean changed the title test: migrate remaining bare @variable at-rule fixtures to @{variable} + repair lockfile Follow-up to #4462: migrate remaining at-rule @var fixtures + drop redundant hasTopLevelBareVariable Jul 18, 2026
@matthew-dean
matthew-dean force-pushed the feat/deprecate-non-value-variable-refs branch from f999e46 to 14e4a6e Compare July 18, 2026 16:23

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
packages/less/test/less-test.js (1)

841-865: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Ensure the logger listener is removed if an unexpected error occurs.

If an unexpected exception is thrown inside the test loop (e.g., from an assertion failure or an unhandled bug), the function will exit early and leave the listener attached to the global less.logger. This can pollute subsequent tests. Wrapping the logic in a try...finally block guarantees that the listener is always removed.

♻️ Proposed refactor
         less.logger.addListener(listener);
-        const isPrelude = m => /A bare `@variable` in an at-rule prelude is deprecated/.test(m);
-        const cases = [
-            ['`@bar`: x;\n@foo `@bar` { a: b }', 1, 'bare `@var` in an unknown at-rule prelude warns'],
-            ['`@a`: 1; `@b`: 2;\n@foo `@a` and `@b` { a: b }', 2, 'bare `@vars` around a keyword both warn'],
-            ['`@v`: 1px;\n@foo (x: `@v`) { a: b }', 0, '`@var` inside (...) is a declaration value — no warning'],
-            ['`@v`: x;\n@foo bar[`@v`] { a: b }', 0, '`@var` inside [...] is a lookup, not structural — no warning'],
-        ];
-        for (const [src, expected, label] of cases) {
-            totalTests++;
-            captured.length = 0;
-            try {
-                await less.render(src);
-            } catch (e) {
-                fail('- Integration - at-rule prelude `@var` warning: ' + label + ' threw ' + e + '\n');
-                continue;
-            }
-            const n = captured.filter(isPrelude).length;
-            if (n === expected) {
-                ok('- Integration - at-rule prelude `@var` warning: ' + label + ' OK\n');
-            } else {
-                fail('- Integration - at-rule prelude `@var` warning: ' + label + ' — expected ' + expected + ', got ' + n + '\n');
-            }
-        }
-        less.logger.removeListener(listener);
+        try {
+            const isPrelude = m => /A bare `@variable` in an at-rule prelude is deprecated/.test(m);
+            const cases = [
+                ['`@bar`: x;\n@foo `@bar` { a: b }', 1, 'bare `@var` in an unknown at-rule prelude warns'],
+                ['`@a`: 1; `@b`: 2;\n@foo `@a` and `@b` { a: b }', 2, 'bare `@vars` around a keyword both warn'],
+                ['`@v`: 1px;\n@foo (x: `@v`) { a: b }', 0, '`@var` inside (...) is a declaration value — no warning'],
+                ['`@v`: x;\n@foo bar[`@v`] { a: b }', 0, '`@var` inside [...] is a lookup, not structural — no warning'],
+            ];
+            for (const [src, expected, label] of cases) {
+                totalTests++;
+                captured.length = 0;
+                try {
+                    await less.render(src);
+                } catch (e) {
+                    fail('- Integration - at-rule prelude `@var` warning: ' + label + ' threw ' + e + '\n');
+                    continue;
+                }
+                const n = captured.filter(isPrelude).length;
+                if (n === expected) {
+                    ok('- Integration - at-rule prelude `@var` warning: ' + label + ' OK\n');
+                } else {
+                    fail('- Integration - at-rule prelude `@var` warning: ' + label + ' — expected ' + expected + ', got ' + n + '\n');
+                }
+            }
+        } finally {
+            less.logger.removeListener(listener);
+        }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/less/test/less-test.js` around lines 841 - 865, Wrap the at-rule
prelude warning test setup and loop, beginning after
less.logger.addListener(listener), in a try...finally block, and move
less.logger.removeListener(listener) into the finally clause. Preserve the
existing test counting, rendering, and pass/fail behavior while ensuring the
listener is removed on every exit path.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@packages/less/test/less-test.js`:
- Around line 841-865: Wrap the at-rule prelude warning test setup and loop,
beginning after less.logger.addListener(listener), in a try...finally block, and
move less.logger.removeListener(listener) into the finally clause. Preserve the
existing test counting, rendering, and pass/fail behavior while ensuring the
listener is removed on every exit path.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 84edc41c-caed-4727-917f-fc2b315264eb

📥 Commits

Reviewing files that changed from the base of the PR and between f999e46 and 14e4a6e.

📒 Files selected for processing (3)
  • packages/less/lib/less/parser/parser.js
  • packages/less/test/index.js
  • packages/less/test/less-test.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/less/lib/less/parser/parser.js

@matthew-dean
matthew-dean force-pushed the feat/deprecate-non-value-variable-refs branch from 14e4a6e to 92c62bb Compare July 18, 2026 16:28
@dosubot dosubot Bot added size:XS This PR changes 0-9 lines, ignoring generated files. and removed size:M This PR changes 30-99 lines, ignoring generated files. labels Jul 18, 2026
@matthew-dean matthew-dean changed the title Follow-up to #4462: migrate remaining at-rule @var fixtures + drop redundant hasTopLevelBareVariable test: migrate remaining bare @variable at-rule fixtures to @{variable} + repair lockfile Jul 18, 2026
… output

less.js asserts errors via tests-error/*.txt but had no coverage that warnings
actually fire, so deprecation notices were unguarded (nothing would catch a
regression that silently stopped emitting one).

- Suppress warnings from normal test output (they are noise across the corpus);
  set LESS_TEST_SHOW_WARNINGS=1 to see them.
- Add testWarnings() (run from index.js) which installs a capturing logger
  listener and asserts each render-reachable warning fires: variable-in-at-rule-
  prelude (incl. bar[@v] top-level -> warns and (x:@v) decl-value -> no warn),
  js-eval, mixin-call-whitespace, mixin-call-no-parens, variable-in-unknown-value,
  dot-slash-operator, complex-selector, extend-no-match, compress, at-plugin.

Documented gaps (not render-reachable): property-in-unknown-value (a $prop ref
resolves via the entity path before the permissive text scan), math-always and
dumpLineNumbers (registered in deprecation.js but never emitted via warn()).
@matthew-dean matthew-dean changed the title test: migrate remaining bare @variable at-rule fixtures to @{variable} + repair lockfile Follow-up to #4462: migrate remaining at-rule @var fixtures + warnings-assertion harness Jul 18, 2026
…eUntil (DRY)

The at-rule-prelude deprecation detected a top-level bare @var two ways: the
permissiveValue entity loop (structural), plus a standalone hasTopLevelBareVariable()
that RE-SCANNED the same text $parseUntil had already walked, with its own hand-rolled
paren counter (and no string/comment handling).

Fold that second scan into $parseUntil's single pass: it already skips strings/comments/
escapes and tracks brackets, so add an opt-in `detectBareVar` that records the first bare
@var (not @{interp}) seen at PAREN depth 0 — [...]/{...} don't shield a reference, only a
declaration-value (...) does — exposed as `.bareVarIndex`. $parseUntil has a single caller
(permissiveValue), so the extra arg/property is contained. Delete hasTopLevelBareVariable.

Behaviour preserved (regression-guarded by testWarnings): @foo @bar -> 1, @A and @b -> 2,
bar[@v] -> 1 (bracket is top-level), (x:@v) -> 0 (decl value), and the mixed
(a:@x) y[@z] -> 1. Also drops the testWarnings 'variable-in-unknown-value' case: it only
fires for the inconsistent bracket edge (--x: bar[@bar]) while --x: @bar / 1px @bar /
foo(@bar) resolve silently, so asserting it would lock in an artifact (now documented).
@dosubot dosubot Bot added size:M This PR changes 30-99 lines, ignoring generated files. and removed size:XS This PR changes 0-9 lines, ignoring generated files. labels Jul 18, 2026
@matthew-dean matthew-dean changed the title Follow-up to #4462: migrate remaining at-rule @var fixtures + warnings-assertion harness Follow-up to #4462: migrate remaining @var fixtures, DRY the prelude bare-@var scan, add warnings coverage Jul 18, 2026
@matthew-dean
matthew-dean merged commit 8e1105f into less:master Jul 18, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant